Loading core/java/android/content/pm/ApplicationInfo.java +15 −0 Original line number Diff line number Diff line Loading @@ -505,6 +505,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} Loading Loading @@ -1114,6 +1122,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_EPHEMERAL) != 0; } /** * @hide */ public boolean isRequiredForSystemUser() { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER) != 0; } /** * @hide */ Loading core/java/android/content/pm/AppsQueryHelper.java +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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()); } Loading Loading @@ -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; } Loading core/java/android/content/pm/IPackageManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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); } core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java +14 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } Loading services/core/java/com/android/server/pm/PackageManagerService.java +38 −31 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -1867,46 +1867,30 @@ 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) { Loading Loading @@ -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 */ Loading
core/java/android/content/pm/ApplicationInfo.java +15 −0 Original line number Diff line number Diff line Loading @@ -505,6 +505,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} Loading Loading @@ -1114,6 +1122,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_EPHEMERAL) != 0; } /** * @hide */ public boolean isRequiredForSystemUser() { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER) != 0; } /** * @hide */ Loading
core/java/android/content/pm/AppsQueryHelper.java +18 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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()); } Loading Loading @@ -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; } Loading
core/java/android/content/pm/IPackageManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -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); }
core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java +14 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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); } Loading
services/core/java/com/android/server/pm/PackageManagerService.java +38 −31 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -1867,46 +1867,30 @@ 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) { Loading Loading @@ -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 */