diff options
| author | 2015-12-16 23:07:20 +0000 | |
|---|---|---|
| committer | 2015-12-16 23:07:20 +0000 | |
| commit | 6142f90b9f99c33c4f75c2057fb1db3bc77425cf (patch) | |
| tree | aa930d6d054780ee72c99485d0bd0e721bd08fcb | |
| parent | 906fd73e1194781037c1124ef39c66dbc4d8851c (diff) | |
| parent | bdbc9692c7cb365d9d3f239baa2377724a6f7bc8 (diff) | |
Merge "Introduced PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER"
6 files changed, 89 insertions, 32 deletions
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 807c0a239185..fe279d1d9b6f 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -506,6 +506,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int PRIVATE_FLAG_EPHEMERAL = 1 << 9; /** + * When set, signals that the application is required for the system user and should not be + * uninstalled. + * + * @hide + */ + public static final int PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER = 1 << 10; + + /** * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants. * {@hide} */ @@ -1117,6 +1125,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { /** * @hide */ + public boolean isRequiredForSystemUser() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER) != 0; + } + + /** + * @hide + */ @Override protected ApplicationInfo getApplicationInfo() { return this; } diff --git a/core/java/android/content/pm/AppsQueryHelper.java b/core/java/android/content/pm/AppsQueryHelper.java index 084bc18ea6fe..e5425897afad 100644 --- a/core/java/android/content/pm/AppsQueryHelper.java +++ b/core/java/android/content/pm/AppsQueryHelper.java @@ -51,6 +51,11 @@ public class AppsQueryHelper { */ public static int GET_IMES = 1 << 2; + /** + * Return all apps that are flagged as required for the system user. + */ + public static int GET_REQUIRED_FOR_SYSTEM_USER = 1 << 3; + private final IPackageManager mPackageManager; private List<ApplicationInfo> mAllApps; @@ -73,6 +78,7 @@ public class AppsQueryHelper { boolean nonLaunchableApps = (flags & GET_NON_LAUNCHABLE_APPS) > 0; boolean interactAcrossUsers = (flags & GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM) > 0; boolean imes = (flags & GET_IMES) > 0; + boolean requiredForSystemUser = (flags & GET_REQUIRED_FOR_SYSTEM_USER) > 0; if (mAllApps == null) { mAllApps = getAllApps(user.getIdentifier()); } @@ -143,6 +149,18 @@ public class AppsQueryHelper { } } + if (requiredForSystemUser) { + final int allAppsSize = mAllApps.size(); + for (int i = 0; i < allAppsSize; i++) { + final ApplicationInfo appInfo = mAllApps.get(i); + if (systemAppsOnly && !appInfo.isSystemApp()) { + continue; + } + if (appInfo.isRequiredForSystemUser()) { + result.add(appInfo.packageName); + } + } + } return result; } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 4d0d146050e8..39f59554c1df 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -523,4 +523,6 @@ interface IPackageManager { boolean setEphemeralApplicationCookie(String packageName, in byte[] cookie, int userId); Bitmap getEphemeralApplicationIcon(String packageName, int userId); boolean isEphemeralApplication(String packageName, int userId); + + boolean setRequiredForSystemUser(String packageName, boolean systemUserApp); } diff --git a/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java index dcf2c890a3cf..9c03e1aa72ab 100644 --- a/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java +++ b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java @@ -90,6 +90,18 @@ public class AppsQueryHelperTests extends AndroidTestCase { assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "app4"), apps); } + public void testQueryAppsRequiredForSystemUser() { + // Test query only system apps required for system user + List<String> apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_REQUIRED_FOR_SYSTEM_USER, + true, UserHandle.SYSTEM); + assertEqualsIgnoreOrder(Arrays.asList("sys_app3"), apps); + + // Test query all apps required for system user + apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_REQUIRED_FOR_SYSTEM_USER, false, + UserHandle.SYSTEM); + assertEqualsIgnoreOrder(Arrays.asList("sys_app3", "app4"), apps); + } + private class AppsQueryHelperTestable extends AppsQueryHelper { @Override @@ -104,7 +116,9 @@ public class AppsQueryHelperTests extends AndroidTestCase { final ApplicationInfo ai3 = new ApplicationInfo(); ai3.packageName = "sys_app3"; ai3.flags |= ApplicationInfo.FLAG_SYSTEM; + ai3.privateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER; final ApplicationInfo ai4 = new ApplicationInfo(); + ai4.privateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER; ai4.packageName = "app4"; return Arrays.asList(ai1, ai2, ai3, ai4); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index d64b8982c709..42e8b018f004 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1845,12 +1845,12 @@ public class PackageManagerService extends IPackageManager.Stub { boolean factoryTest, boolean onlyCore) { PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore); - m.enableSystemUserApps(); + m.enableSystemUserPackages(); ServiceManager.addService("package", m); return m; } - private void enableSystemUserApps() { + private void enableSystemUserPackages() { if (!UserManager.isSplitSystemUser()) { return; } @@ -1867,48 +1867,32 @@ public class PackageManagerService extends IPackageManager.Stub { | AppsQueryHelper.GET_IMES, /* systemAppsOnly */ true, UserHandle.SYSTEM)); ArraySet<String> wlApps = SystemConfig.getInstance().getSystemUserWhitelistedApps(); enableApps.addAll(wlApps); + enableApps.addAll(queryHelper.queryApps(AppsQueryHelper.GET_REQUIRED_FOR_SYSTEM_USER, + /* systemAppsOnly */ false, UserHandle.SYSTEM)); ArraySet<String> blApps = SystemConfig.getInstance().getSystemUserBlacklistedApps(); enableApps.removeAll(blApps); - - List<String> systemApps = queryHelper.queryApps(0, /* systemAppsOnly */ true, + Log.i(TAG, "Applications installed for system user: " + enableApps); + List<String> allAps = queryHelper.queryApps(0, /* systemAppsOnly */ false, UserHandle.SYSTEM); - final int systemAppsSize = systemApps.size(); + final int allAppsSize = allAps.size(); synchronized (mPackages) { - for (int i = 0; i < systemAppsSize; i++) { - String pName = systemApps.get(i); + for (int i = 0; i < allAppsSize; i++) { + String pName = allAps.get(i); PackageSetting pkgSetting = mSettings.mPackages.get(pName); // Should not happen, but we shouldn't be failing if it does if (pkgSetting == null) { continue; } - boolean installed = enableApps.contains(pName); - pkgSetting.setInstalled(installed, UserHandle.USER_SYSTEM); + boolean install = enableApps.contains(pName); + if (pkgSetting.getInstalled(UserHandle.USER_SYSTEM) != install) { + Log.i(TAG, (install ? "Installing " : "Uninstalling ") + pName + + " for system user"); + pkgSetting.setInstalled(install, UserHandle.USER_SYSTEM); + } } } } - static String[] splitString(String str, char sep) { - int count = 1; - int i = 0; - while ((i=str.indexOf(sep, i)) >= 0) { - count++; - i++; - } - - String[] res = new String[count]; - i=0; - count = 0; - int lastI=0; - while ((i=str.indexOf(sep, i)) >= 0) { - res[count] = str.substring(lastI, i); - count++; - i++; - lastI = i; - } - res[count] = str.substring(lastI, str.length()); - return res; - } - private static void getDefaultDisplayMetrics(Context context, DisplayMetrics metrics) { DisplayManager displayManager = (DisplayManager) context.getSystemService( Context.DISPLAY_SERVICE); @@ -13782,6 +13766,29 @@ public class PackageManagerService extends IPackageManager.Stub { } } + @Override + public boolean setRequiredForSystemUser(String packageName, boolean systemUserApp) { + int callingUid = Binder.getCallingUid(); + if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) { + throw new SecurityException( + "setRequiredForSystemUser can only be run by the system or root"); + } + synchronized (mPackages) { + PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps == null) { + Log.w(TAG, "Package doesn't exist: " + packageName); + return false; + } + if (systemUserApp) { + ps.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER; + } else { + ps.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER; + } + mSettings.writeLPr(); + } + return true; + } + /* * This method handles package deletion in general */ diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index 5cf92a9f6a7f..2921032b5572 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -49,6 +49,7 @@ abstract class SettingBase { void setPrivateFlags(int pkgPrivateFlags) { this.pkgPrivateFlags = pkgPrivateFlags & (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED - | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK); + | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK + | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER); } } |