Merge branch 'prep-for-InstalledAppProviderService' into 'master'
Prep for InstalledAppProviderService This is basically a collection of little fixes in preparations for !299 . See merge request !313
This commit is contained in:
		
						commit
						1bfd3425c9
					
				@ -14,6 +14,7 @@ import junit.framework.AssertionFailedError;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.FDroidProviderTest;
 | 
			
		||||
import org.fdroid.fdroid.receiver.PackageAddedReceiver;
 | 
			
		||||
import org.fdroid.fdroid.receiver.PackageRemovedReceiver;
 | 
			
		||||
import org.fdroid.fdroid.receiver.PackageUpgradedReceiver;
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,11 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.Apk;
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.TestUtils;
 | 
			
		||||
import org.fdroid.fdroid.Utils;
 | 
			
		||||
import org.fdroid.fdroid.mock.MockApk;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
@ -1,12 +1,10 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.Apk;
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.RepoProvider;
 | 
			
		||||
import org.fdroid.fdroid.TestUtils;
 | 
			
		||||
import org.fdroid.fdroid.mock.MockApk;
 | 
			
		||||
import org.fdroid.fdroid.mock.MockApp;
 | 
			
		||||
import org.fdroid.fdroid.mock.MockRepo;
 | 
			
		||||
@ -333,5 +331,4 @@ public class ApkProviderTest extends BaseApkProviderTest {
 | 
			
		||||
        assertEquals(1, apk.versionCode);
 | 
			
		||||
        assertEquals(10, apk.repo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,14 +1,12 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentResolver;
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
import android.content.res.Resources;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.App;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.InstalledAppCacheUpdater;
 | 
			
		||||
import org.fdroid.fdroid.R;
 | 
			
		||||
import org.fdroid.fdroid.TestUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@ -1,11 +1,10 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
import android.database.Cursor;
 | 
			
		||||
import android.net.Uri;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.Apk;
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.TestUtils;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.annotation.TargetApi;
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
@ -10,12 +10,6 @@ import android.os.Build;
 | 
			
		||||
import android.provider.ContactsContract;
 | 
			
		||||
import android.test.ProviderTestCase2MockContext;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.FDroidProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.InstalledAppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.RepoProvider;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import mock.MockContextEmptyComponents;
 | 
			
		||||
@ -1,11 +1,9 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.InstalledAppProvider;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import mock.MockInstallablePackageManager;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tests the ability of the {@link  org.fdroid.fdroid.data.InstalledAppCacheUpdater} to stay in sync with
 | 
			
		||||
 * Tests the ability of the {@link  InstalledAppCacheUpdater} to stay in sync with
 | 
			
		||||
 * the {@link android.content.pm.PackageManager}.
 | 
			
		||||
 * For practical reasons, it extends FDroidProviderTest<InstalledAppProvider>, although there is also a
 | 
			
		||||
 * separate test for the InstalledAppProvider which tests the CRUD operations in more detail.
 | 
			
		||||
@ -1,11 +1,8 @@
 | 
			
		||||
package org.fdroid.fdroid;
 | 
			
		||||
package org.fdroid.fdroid.data;
 | 
			
		||||
 | 
			
		||||
import android.content.ContentValues;
 | 
			
		||||
 | 
			
		||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.AppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.InstalledAppProvider;
 | 
			
		||||
import org.fdroid.fdroid.data.RepoProvider;
 | 
			
		||||
import org.fdroid.fdroid.TestUtils;
 | 
			
		||||
 | 
			
		||||
import mock.MockInstallablePackageManager;
 | 
			
		||||
 | 
			
		||||
@ -1571,9 +1571,6 @@ public class AppDetails extends AppCompatActivity {
 | 
			
		||||
                        btMain.setText(R.string.menu_launch);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        btMain.setText(R.string.menu_uninstall);
 | 
			
		||||
                        if (!app.uninstallable) {
 | 
			
		||||
                            btMain.setVisibility(View.GONE);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                btMain.setOnClickListener(mOnClickListener);
 | 
			
		||||
 | 
			
		||||
@ -32,19 +32,25 @@ public class Apk extends ValueObject implements Comparable<Apk> {
 | 
			
		||||
 | 
			
		||||
    public Utils.CommaSeparatedList nativecode; // null if empty or unknown
 | 
			
		||||
 | 
			
		||||
    // ID (md5 sum of public key) of signature. Might be null, in the
 | 
			
		||||
    // transition to this field existing.
 | 
			
		||||
    /**
 | 
			
		||||
     * ID (md5 sum of public key) of signature. Might be null, in the
 | 
			
		||||
     * transition to this field existing.
 | 
			
		||||
     */
 | 
			
		||||
    public String sig;
 | 
			
		||||
 | 
			
		||||
    // True if compatible with the device.
 | 
			
		||||
    /**
 | 
			
		||||
     * True if compatible with the device.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean compatible;
 | 
			
		||||
 | 
			
		||||
    public String apkName; // F-Droid style APK name
 | 
			
		||||
    public SanitizedFile installedFile; // the .apk file on this device's filesystem
 | 
			
		||||
 | 
			
		||||
    // If not null, this is the name of the source tarball for the
 | 
			
		||||
    // application. Null indicates that it's a developer's binary
 | 
			
		||||
    // build - otherwise it's built from source.
 | 
			
		||||
    /**
 | 
			
		||||
     * If not null, this is the name of the source tarball for the
 | 
			
		||||
     * application. Null indicates that it's a developer's binary
 | 
			
		||||
     * build - otherwise it's built from source.
 | 
			
		||||
     */
 | 
			
		||||
    public String srcname;
 | 
			
		||||
 | 
			
		||||
    public int repoVersion;
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,9 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
 | 
			
		||||
    private static final String TAG = "App";
 | 
			
		||||
 | 
			
		||||
    // True if compatible with the device (i.e. if at least one apk is)
 | 
			
		||||
    /**
 | 
			
		||||
     * True if compatible with the device (i.e. if at least one apk is)
 | 
			
		||||
     */
 | 
			
		||||
    public boolean compatible;
 | 
			
		||||
 | 
			
		||||
    public String packageName = "unknown";
 | 
			
		||||
@ -84,27 +86,39 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
    public Date added;
 | 
			
		||||
    public Date lastUpdated;
 | 
			
		||||
 | 
			
		||||
    // List of categories (as defined in the metadata
 | 
			
		||||
    // documentation) or null if there aren't any.
 | 
			
		||||
    /**
 | 
			
		||||
     * List of categories (as defined in the metadata documentation) or null if there aren't any.
 | 
			
		||||
     */
 | 
			
		||||
    public Utils.CommaSeparatedList categories;
 | 
			
		||||
 | 
			
		||||
    // List of anti-features (as defined in the metadata
 | 
			
		||||
    // documentation) or null if there aren't any.
 | 
			
		||||
    /**
 | 
			
		||||
     * List of anti-features (as defined in the metadata documentation) or null if there aren't any.
 | 
			
		||||
     */
 | 
			
		||||
    public Utils.CommaSeparatedList antiFeatures;
 | 
			
		||||
 | 
			
		||||
    // List of special requirements (such as root privileges) or
 | 
			
		||||
    // null if there aren't any.
 | 
			
		||||
    /**
 | 
			
		||||
     * List of special requirements (such as root privileges) or null if there aren't any.
 | 
			
		||||
     */
 | 
			
		||||
    public Utils.CommaSeparatedList requirements;
 | 
			
		||||
 | 
			
		||||
    // True if all updates for this app are to be ignored
 | 
			
		||||
    /**
 | 
			
		||||
     * True if all updates for this app are to be ignored
 | 
			
		||||
     */
 | 
			
		||||
    public boolean ignoreAllUpdates;
 | 
			
		||||
 | 
			
		||||
    // True if the current update for this app is to be ignored
 | 
			
		||||
    /**
 | 
			
		||||
     * True if the current update for this app is to be ignored
 | 
			
		||||
     */
 | 
			
		||||
    public int ignoreThisUpdate;
 | 
			
		||||
 | 
			
		||||
    // To be displayed at 48dp (x1.0)
 | 
			
		||||
    /**
 | 
			
		||||
     * To be displayed at 48dp (x1.0)
 | 
			
		||||
     */
 | 
			
		||||
    public String iconUrl;
 | 
			
		||||
    // To be displayed at 72dp (x1.5)
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * To be displayed at 72dp (x1.5)
 | 
			
		||||
     */
 | 
			
		||||
    public String iconUrlLarge;
 | 
			
		||||
 | 
			
		||||
    public String installedVersionName;
 | 
			
		||||
@ -115,8 +129,6 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
 | 
			
		||||
    public String installedSig;
 | 
			
		||||
 | 
			
		||||
    public boolean uninstallable;
 | 
			
		||||
 | 
			
		||||
    public static String getIconName(String packageName, int versionCode) {
 | 
			
		||||
        return packageName + "_" + versionCode + ".png";
 | 
			
		||||
    }
 | 
			
		||||
@ -250,14 +262,21 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
    /**
 | 
			
		||||
     * Instantiate from a locally installed package.
 | 
			
		||||
     */
 | 
			
		||||
    @TargetApi(9)
 | 
			
		||||
    public App(Context context, PackageManager pm, String packageName)
 | 
			
		||||
            throws CertificateEncodingException, IOException, PackageManager.NameNotFoundException {
 | 
			
		||||
        final ApplicationInfo appInfo = pm.getApplicationInfo(packageName,
 | 
			
		||||
                PackageManager.GET_META_DATA);
 | 
			
		||||
        final PackageInfo packageInfo = pm.getPackageInfo(packageName,
 | 
			
		||||
                PackageManager.GET_SIGNATURES | PackageManager.GET_PERMISSIONS);
 | 
			
		||||
 | 
			
		||||
        PackageInfo packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
 | 
			
		||||
        setFromPackageInfo(pm, packageInfo);
 | 
			
		||||
        this.installedApk = new Apk();
 | 
			
		||||
        SanitizedFile apkFile = SanitizedFile.knownSanitized(packageInfo.applicationInfo.publicSourceDir);
 | 
			
		||||
        initApkFromApkFile(context, this.installedApk, packageInfo, apkFile);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @TargetApi(9)
 | 
			
		||||
    private void setFromPackageInfo(PackageManager pm, PackageInfo packageInfo)
 | 
			
		||||
            throws CertificateEncodingException, IOException, PackageManager.NameNotFoundException {
 | 
			
		||||
 | 
			
		||||
        this.packageName = packageInfo.packageName;
 | 
			
		||||
        final String installerPackageName = pm.getInstallerPackageName(packageName);
 | 
			
		||||
        CharSequence installerPackageLabel = null;
 | 
			
		||||
        if (!TextUtils.isEmpty(installerPackageName)) {
 | 
			
		||||
@ -273,13 +292,13 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
            installerPackageLabel = installerPackageName;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ApplicationInfo appInfo = packageInfo.applicationInfo;
 | 
			
		||||
        final CharSequence appDescription = appInfo.loadDescription(pm);
 | 
			
		||||
        if (TextUtils.isEmpty(appDescription)) {
 | 
			
		||||
            this.summary = "(installed by " + installerPackageLabel + ")";
 | 
			
		||||
        } else {
 | 
			
		||||
            this.summary = (String) appDescription.subSequence(0, 40);
 | 
			
		||||
        }
 | 
			
		||||
        this.packageName = appInfo.packageName;
 | 
			
		||||
        this.added = new Date(packageInfo.firstInstallTime);
 | 
			
		||||
        this.lastUpdated = new Date(packageInfo.lastUpdateTime);
 | 
			
		||||
        this.description = "<p>";
 | 
			
		||||
@ -292,8 +311,20 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
 | 
			
		||||
        this.name = (String) appInfo.loadLabel(pm);
 | 
			
		||||
        this.icon = getIconName(packageName, packageInfo.versionCode);
 | 
			
		||||
        this.compatible = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        final Apk apk = new Apk();
 | 
			
		||||
    private void initApkFromApkFile(Context context, Apk apk, PackageInfo packageInfo, SanitizedFile apkFile)
 | 
			
		||||
            throws IOException, CertificateEncodingException {
 | 
			
		||||
        // TODO include signature hash calculation here
 | 
			
		||||
        apk.hashType = "sha256";
 | 
			
		||||
        apk.hash = Utils.getBinaryHash(apkFile, apk.hashType);
 | 
			
		||||
        initInstalledApk(context, apk, packageInfo, apkFile);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initInstalledApk(Context context, Apk apk, PackageInfo packageInfo, SanitizedFile apkFile)
 | 
			
		||||
            throws IOException, CertificateEncodingException {
 | 
			
		||||
        apk.compatible = true;
 | 
			
		||||
        apk.versionName = packageInfo.versionName;
 | 
			
		||||
        apk.versionCode = packageInfo.versionCode;
 | 
			
		||||
        apk.added = this.added;
 | 
			
		||||
@ -303,16 +334,12 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
        apk.packageName = this.packageName;
 | 
			
		||||
        apk.permissions = Utils.CommaSeparatedList.make(packageInfo.requestedPermissions);
 | 
			
		||||
        apk.apkName = apk.packageName + "_" + apk.versionCode + ".apk";
 | 
			
		||||
 | 
			
		||||
        final SanitizedFile apkFile = SanitizedFile.knownSanitized(appInfo.publicSourceDir);
 | 
			
		||||
        apk.hashType = "sha256";
 | 
			
		||||
        apk.hash = Utils.getBinaryHash(apkFile, apk.hashType);
 | 
			
		||||
        apk.installedFile = apkFile;
 | 
			
		||||
 | 
			
		||||
        JarFile jarFile = new JarFile(apkFile);
 | 
			
		||||
        JarFile apkJar = new JarFile(apkFile);
 | 
			
		||||
        HashSet<String> abis = new HashSet<>(3);
 | 
			
		||||
        Pattern pattern = Pattern.compile("^lib/([a-z0-9-]+)/.*");
 | 
			
		||||
        for (Enumeration<JarEntry> jarEntries = jarFile.entries(); jarEntries.hasMoreElements();) {
 | 
			
		||||
        for (Enumeration<JarEntry> jarEntries = apkJar.entries(); jarEntries.hasMoreElements();) {
 | 
			
		||||
            JarEntry jarEntry = jarEntries.nextElement();
 | 
			
		||||
            Matcher matcher = pattern.matcher(jarEntry.getName());
 | 
			
		||||
            if (matcher.matches()) {
 | 
			
		||||
@ -330,7 +357,6 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
            apk.features = Utils.CommaSeparatedList.make(featureNames);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final JarFile apkJar = new JarFile(apkFile);
 | 
			
		||||
        final JarEntry aSignedEntry = (JarEntry) apkJar.getEntry("AndroidManifest.xml");
 | 
			
		||||
 | 
			
		||||
        if (aSignedEntry == null) {
 | 
			
		||||
@ -387,11 +413,6 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
            fdroidSig[j * 2 + 1] = (byte) (d >= 10 ? ('a' + d - 10) : ('0' + d));
 | 
			
		||||
        }
 | 
			
		||||
        apk.sig = Utils.hashBytes(fdroidSig, "md5");
 | 
			
		||||
 | 
			
		||||
        this.installedApk = apk;
 | 
			
		||||
        boolean system = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
 | 
			
		||||
        boolean updatedSystemApp = (appInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
 | 
			
		||||
        this.uninstallable = !system || updatedSystemApp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isValid() {
 | 
			
		||||
@ -464,16 +485,20 @@ public class App extends ValueObject implements Comparable<App> {
 | 
			
		||||
        return updates;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // True if there are new versions (apks) available and the user wants
 | 
			
		||||
    // to be notified about them
 | 
			
		||||
    /**
 | 
			
		||||
     * True if there are new versions (apks) available and the user wants
 | 
			
		||||
     * to be notified about them
 | 
			
		||||
     */
 | 
			
		||||
    public boolean canAndWantToUpdate() {
 | 
			
		||||
        boolean canUpdate = hasUpdates();
 | 
			
		||||
        boolean wantsUpdate = !ignoreAllUpdates && ignoreThisUpdate < suggestedVersionCode;
 | 
			
		||||
        return canUpdate && wantsUpdate && !isFiltered();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Whether the app is filtered or not based on AntiFeatures and root
 | 
			
		||||
    // permission (set in the Settings page)
 | 
			
		||||
    /**
 | 
			
		||||
     * Whether the app is filtered or not based on AntiFeatures and root
 | 
			
		||||
     * permission (set in the Settings page)
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isFiltered() {
 | 
			
		||||
        return new AppFilter().filter(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -121,8 +121,10 @@ public class Repo extends ValueObject {
 | 
			
		||||
        return !TextUtils.isEmpty(this.signingCertificate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // this happens when a repo is configed with a fingerprint, but the client
 | 
			
		||||
    // has not connected to it yet to download its signing certificate
 | 
			
		||||
    /**
 | 
			
		||||
     * This happens when a repo is configed with a fingerprint, but the client
 | 
			
		||||
     * has not connected to it yet to download its signing certificate
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isSignedButUnverified() {
 | 
			
		||||
        return TextUtils.isEmpty(this.signingCertificate) && !TextUtils.isEmpty(this.fingerprint);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -229,7 +229,7 @@ public class WifiStateChangeService extends IntentService {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String formatIpAddress(int ipAddress) {
 | 
			
		||||
    static String formatIpAddress(int ipAddress) {
 | 
			
		||||
        if (ipAddress == 0) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -238,7 +238,6 @@ public class SwapAppsView extends ListView implements
 | 
			
		||||
            TextView nameView;
 | 
			
		||||
            ImageView iconView;
 | 
			
		||||
            Button btnInstall;
 | 
			
		||||
            TextView btnAttemptInstall;
 | 
			
		||||
            TextView statusInstalled;
 | 
			
		||||
            TextView statusIncompatible;
 | 
			
		||||
 | 
			
		||||
@ -343,22 +342,24 @@ public class SwapAppsView extends ListView implements
 | 
			
		||||
 | 
			
		||||
                ImageLoader.getInstance().displayImage(app.iconUrl, iconView, displayImageOptions);
 | 
			
		||||
 | 
			
		||||
                btnInstall.setVisibility(View.GONE);
 | 
			
		||||
                btnAttemptInstall.setVisibility(View.GONE);
 | 
			
		||||
                statusInstalled.setVisibility(View.GONE);
 | 
			
		||||
                statusIncompatible.setVisibility(View.GONE);
 | 
			
		||||
 | 
			
		||||
                if (app.hasUpdates()) {
 | 
			
		||||
                    btnInstall.setText(R.string.menu_upgrade);
 | 
			
		||||
                    btnInstall.setVisibility(View.VISIBLE);
 | 
			
		||||
                    statusIncompatible.setVisibility(View.GONE);
 | 
			
		||||
                    statusInstalled.setVisibility(View.GONE);
 | 
			
		||||
                } else if (app.isInstalled()) {
 | 
			
		||||
                    btnInstall.setVisibility(View.GONE);
 | 
			
		||||
                    statusIncompatible.setVisibility(View.GONE);
 | 
			
		||||
                    statusInstalled.setVisibility(View.VISIBLE);
 | 
			
		||||
                } else if (!app.compatible) {
 | 
			
		||||
                    btnAttemptInstall.setVisibility(View.VISIBLE);
 | 
			
		||||
                    btnInstall.setVisibility(View.GONE);
 | 
			
		||||
                    statusIncompatible.setVisibility(View.VISIBLE);
 | 
			
		||||
                    statusInstalled.setVisibility(View.GONE);
 | 
			
		||||
                } else {
 | 
			
		||||
                    btnInstall.setText(R.string.menu_install);
 | 
			
		||||
                    btnInstall.setVisibility(View.VISIBLE);
 | 
			
		||||
                    statusIncompatible.setVisibility(View.GONE);
 | 
			
		||||
                    statusInstalled.setVisibility(View.GONE);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                OnClickListener installListener = new OnClickListener() {
 | 
			
		||||
@ -372,14 +373,11 @@ public class SwapAppsView extends ListView implements
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                btnInstall.setOnClickListener(installListener);
 | 
			
		||||
                btnAttemptInstall.setOnClickListener(installListener);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private void showProgress() {
 | 
			
		||||
                progressView.setVisibility(View.VISIBLE);
 | 
			
		||||
                btnInstall.setVisibility(View.GONE);
 | 
			
		||||
                btnAttemptInstall.setVisibility(View.GONE);
 | 
			
		||||
                statusInstalled.setVisibility(View.GONE);
 | 
			
		||||
                statusIncompatible.setVisibility(View.GONE);
 | 
			
		||||
            }
 | 
			
		||||
@ -410,7 +408,6 @@ public class SwapAppsView extends ListView implements
 | 
			
		||||
            holder.nameView = (TextView) view.findViewById(R.id.name);
 | 
			
		||||
            holder.iconView = (ImageView) view.findViewById(android.R.id.icon);
 | 
			
		||||
            holder.btnInstall = (Button) view.findViewById(R.id.btn_install);
 | 
			
		||||
            holder.btnAttemptInstall = (TextView) view.findViewById(R.id.btn_attempt_install);
 | 
			
		||||
            holder.statusInstalled = (TextView) view.findViewById(R.id.status_installed);
 | 
			
		||||
            holder.statusIncompatible = (TextView) view.findViewById(R.id.status_incompatible);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:id="@+id/header"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    android:layout_alignParentTop="true">
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
@ -1,7 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    android:id="@+id/header"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    android:layout_alignParentTop="true">
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
							
								
								
									
										32
									
								
								app/src/main/res/layout-sw480dp/start_swap_header.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								app/src/main/res/layout-sw480dp/start_swap_header.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:id="@+id/header"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="130dp"
 | 
			
		||||
    android:layout_alignParentTop="true"
 | 
			
		||||
    tools:showIn="@layout/swap_blank">
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:scaleType="centerCrop"
 | 
			
		||||
        android:src="@drawable/swap_start_header" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_centerHorizontal="true"
 | 
			
		||||
        android:layout_alignParentBottom="true"
 | 
			
		||||
        android:padding="20dp"
 | 
			
		||||
        android:paddingLeft="30dp"
 | 
			
		||||
        android:paddingRight="30dp"
 | 
			
		||||
        android:paddingEnd="30dp"
 | 
			
		||||
        android:gravity="center"
 | 
			
		||||
        android:textAlignment="center"
 | 
			
		||||
        android:text="@string/swap_intro"
 | 
			
		||||
        android:textColor="@android:color/white"
 | 
			
		||||
        android:textSize="18sp"
 | 
			
		||||
        tools:ignore="UnusedAttribute" />
 | 
			
		||||
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
@ -1,32 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:id="@+id/header"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
    android:layout_height="130dp"
 | 
			
		||||
    android:layout_alignParentTop="true"
 | 
			
		||||
    tools:showIn="@layout/swap_blank">
 | 
			
		||||
 | 
			
		||||
    <ImageView
 | 
			
		||||
        android:layout_width="match_parent"
 | 
			
		||||
        android:layout_height="match_parent"
 | 
			
		||||
        android:scaleType="centerCrop"
 | 
			
		||||
        android:src="@drawable/swap_start_header" />
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
        android:layout_width="wrap_content"
 | 
			
		||||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:layout_centerHorizontal="true"
 | 
			
		||||
        android:layout_alignParentBottom="true"
 | 
			
		||||
        android:padding="20dp"
 | 
			
		||||
        android:paddingLeft="30dp"
 | 
			
		||||
        android:paddingRight="30dp"
 | 
			
		||||
        android:paddingEnd="30dp"
 | 
			
		||||
        android:gravity="center"
 | 
			
		||||
        android:textAlignment="center"
 | 
			
		||||
        android:text="@string/swap_intro"
 | 
			
		||||
        android:textColor="@android:color/white"
 | 
			
		||||
        android:textSize="18sp"
 | 
			
		||||
        tools:ignore="UnusedAttribute" />
 | 
			
		||||
 | 
			
		||||
    android:layout_height="wrap_content"
 | 
			
		||||
    android:layout_alignParentTop="true">
 | 
			
		||||
</RelativeLayout>
 | 
			
		||||
@ -55,13 +55,6 @@
 | 
			
		||||
            android:textColor="@color/swap_incompatible"
 | 
			
		||||
            android:text="@string/app_incompatible" />
 | 
			
		||||
 | 
			
		||||
        <TextView
 | 
			
		||||
            android:id="@+id/btn_attempt_install"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:textColor="@color/swap_light_blue"
 | 
			
		||||
            android:text="@string/swap_attempt_install" />
 | 
			
		||||
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
    <TextView
 | 
			
		||||
 | 
			
		||||
@ -335,7 +335,6 @@
 | 
			
		||||
    <string name="bluetooth_unavailable">Bluetooth unavailable</string>
 | 
			
		||||
    <string name="swap_cant_send_no_bluetooth">Cannot send F-Droid, because Bluetooth is unavailable on this device.</string>
 | 
			
		||||
    <string name="loading">Loading…</string>
 | 
			
		||||
    <string name="swap_attempt_install">Try to install</string>
 | 
			
		||||
    <string name="swap_connection_misc_error">An error occurred while connecting to device, we can\'t seem to swap with it.</string>
 | 
			
		||||
    <string name="swap_not_enabled">Swapping not enabled</string>
 | 
			
		||||
    <string name="swap_not_enabled_description">Before swapping, your device must be made visible.</string>
 | 
			
		||||
 | 
			
		||||
@ -5,11 +5,13 @@ import org.junit.Test;
 | 
			
		||||
import java.io.File;
 | 
			
		||||
 | 
			
		||||
import static org.junit.Assert.assertEquals;
 | 
			
		||||
import static org.junit.Assume.assumeTrue;
 | 
			
		||||
 | 
			
		||||
public class SanitizedFileTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSanitizedFile() {
 | 
			
		||||
        assumeTrue("/".equals(System.getProperty("file.separator")));
 | 
			
		||||
 | 
			
		||||
        File directory = new File("/tmp/blah");
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,20 @@
 | 
			
		||||
package org.fdroid.fdroid.net;
 | 
			
		||||
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import java.net.InetAddress;
 | 
			
		||||
import java.net.UnknownHostException;
 | 
			
		||||
 | 
			
		||||
public class WifiStateChangeServiceTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testFormatIpAddress() throws UnknownHostException {
 | 
			
		||||
        for (long i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i += 98273) {
 | 
			
		||||
            String ip = WifiStateChangeService.formatIpAddress((int) i);
 | 
			
		||||
            InetAddress.getByName(ip);
 | 
			
		||||
        }
 | 
			
		||||
        InetAddress.getByName(WifiStateChangeService.formatIpAddress(Integer.MAX_VALUE));
 | 
			
		||||
        InetAddress.getByName(WifiStateChangeService.formatIpAddress(Integer.MIN_VALUE));
 | 
			
		||||
        InetAddress.getByName(WifiStateChangeService.formatIpAddress(0));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user