Merge "Introduced PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER"
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 807c0a2..fe279d1 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -506,6 +506,14 @@
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 @@
/**
* @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 084bc18..e542589 100644
--- a/core/java/android/content/pm/AppsQueryHelper.java
+++ b/core/java/android/content/pm/AppsQueryHelper.java
@@ -51,6 +51,11 @@
*/
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 @@
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 @@
}
}
+ 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 4d0d146..39f59554 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -523,4 +523,6 @@
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 dcf2c89..9c03e1a 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 @@
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 @@
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 d64b898..42e8b01 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 @@
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 @@
| 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 @@
}
}
+ @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 5cf92a9..2921032 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 @@
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);
}
}