exclude ROM apps from default swap app listing
Apps that are built as part of the ROM and signed by the platform keys should very rarely be swapped. This removes them from the default list by comparing the signing keys. This filter is deliberately only included on the list function and not on the search function. If people want to share system apps, they'll be able to find them with the search function, but the system apps won't show up by default. https://source.android.com/devices/tech/ota/sign_builds#certificates-keys closes #440
This commit is contained in:
parent
59ec2a7751
commit
c42d7164cf
@ -18,6 +18,7 @@ import org.fdroid.fdroid.data.Schema.InstalledAppTable;
|
||||
import org.fdroid.fdroid.data.Schema.InstalledAppTable.Cols;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
public class InstalledAppProvider extends FDroidProvider {
|
||||
@ -81,6 +82,20 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
|
||||
private static final UriMatcher MATCHER = new UriMatcher(-1);
|
||||
|
||||
/**
|
||||
* Built-in apps that are signed by the various Android ROM keys.
|
||||
*
|
||||
* @see <a href="https://source.android.com/devices/tech/ota/sign_builds#certificates-keys">Certificates and private keys</a>
|
||||
*/
|
||||
private static final String[] SYSTEM_PACKAGES = {
|
||||
"android", // platform key
|
||||
"com.android.email", // test/release key
|
||||
"com.android.contacts", // shared key
|
||||
"com.android.providers.downloads", // media key
|
||||
};
|
||||
|
||||
private static String[] systemSignatures;
|
||||
|
||||
static {
|
||||
MATCHER.addURI(getAuthority(), null, CODE_LIST);
|
||||
MATCHER.addURI(getAuthority(), PATH_SEARCH + "/*", CODE_SEARCH);
|
||||
@ -117,6 +132,36 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
return packageName; // all else fails, return packageName
|
||||
}
|
||||
|
||||
/**
|
||||
* Add SQL selection statement to exclude {@link InstalledApp}s that were
|
||||
* signed by the platform/shared/media/testkey keys.
|
||||
*
|
||||
* @see <a href="https://source.android.com/devices/tech/ota/sign_builds#certificates-keys">Certificates and private keys</a>
|
||||
*/
|
||||
private QuerySelection selectNotSystemSignature(QuerySelection selection) {
|
||||
if (systemSignatures == null) {
|
||||
Log.i(TAG, "selectNotSystemSignature: systemSignature == null, querying for it");
|
||||
HashSet<String> signatures = new HashSet<>();
|
||||
for (String packageName : SYSTEM_PACKAGES) {
|
||||
Cursor cursor = query(InstalledAppProvider.getAppUri(packageName), new String[]{Cols.SIGNATURE},
|
||||
null, null, null);
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
signatures.add(cursor.getString(cursor.getColumnIndex(Cols.SIGNATURE)));
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
systemSignatures = signatures.toArray(new String[signatures.size()]);
|
||||
}
|
||||
|
||||
Log.i(TAG, "excluding InstalledApps signed by system signatures");
|
||||
for (String systemSignature : systemSignatures) {
|
||||
selection = selection.add("NOT " + Cols.SIGNATURE + " IN (?)", new String[]{systemSignature});
|
||||
}
|
||||
return selection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTableName() {
|
||||
return InstalledAppTable.NAME;
|
||||
@ -185,6 +230,7 @@ public class InstalledAppProvider extends FDroidProvider {
|
||||
QuerySelection selection = new QuerySelection(customSelection, selectionArgs);
|
||||
switch (MATCHER.match(uri)) {
|
||||
case CODE_LIST:
|
||||
selection = selectNotSystemSignature(selection);
|
||||
break;
|
||||
|
||||
case CODE_SINGLE:
|
||||
|
@ -23,6 +23,8 @@ import rx.subjects.PublishSubject;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -146,7 +148,10 @@ public class InstalledAppProviderService extends IntentService {
|
||||
* Make sure that {@link InstalledAppProvider}, our database of installed apps,
|
||||
* is in sync with what the {@link PackageManager} tells us is installed. Once
|
||||
* completed, the relevant {@link android.content.ContentProvider}s will be
|
||||
* notified of any changes to installed statuses.
|
||||
* notified of any changes to installed statuses. The packages are processed
|
||||
* in alphabetically order so that "{@code android}" is processed first. That
|
||||
* is always present and signed by the system key, so it is the source of the
|
||||
* system key for comparing all packages.
|
||||
* <p>
|
||||
* The installed app cache could get out of sync, e.g. if F-Droid crashed/ or
|
||||
* ran out of battery half way through responding to {@link Intent#ACTION_PACKAGE_ADDED}.
|
||||
@ -169,6 +174,12 @@ public class InstalledAppProviderService extends IntentService {
|
||||
|
||||
List<PackageInfo> packageInfoList = context.getPackageManager()
|
||||
.getInstalledPackages(PackageManager.GET_SIGNATURES);
|
||||
Collections.sort(packageInfoList, new Comparator<PackageInfo>() {
|
||||
@Override
|
||||
public int compare(PackageInfo o1, PackageInfo o2) {
|
||||
return o1.packageName.compareTo(o2.packageName);
|
||||
}
|
||||
});
|
||||
for (PackageInfo packageInfo : packageInfoList) {
|
||||
if (cachedInfo.containsKey(packageInfo.packageName)) {
|
||||
if (packageInfo.lastUpdateTime < 1262300400000L // 2010-01-01 00:00
|
||||
@ -314,6 +325,11 @@ public class InstalledAppProviderService extends IntentService {
|
||||
context.getContentResolver().delete(uri, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the fingerprint used to represent an APK signing key in F-Droid.
|
||||
* This is a custom fingerprint algorithm that was kind of accidentally
|
||||
* created, but is still in use.
|
||||
*/
|
||||
private static String getPackageSig(PackageInfo info) {
|
||||
if (info == null || info.signatures == null || info.signatures.length < 1) {
|
||||
return "";
|
||||
|
Loading…
x
Reference in New Issue
Block a user