summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/pm/PackageParser.java13
-rw-r--r--core/java/android/content/pm/PackageUserState.java73
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java2
-rw-r--r--services/core/java/com/android/server/pm/Settings.java333
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java375
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java177
7 files changed, 850 insertions, 136 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 503ca091b2fa..5c31f796974d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4955,6 +4955,19 @@ public class PackageParser {
}
}
+ public List<String> getChildPackageNames() {
+ if (childPackages == null) {
+ return null;
+ }
+ final int childCount = childPackages.size();
+ final List<String> childPackageNames = new ArrayList<>(childCount);
+ for (int i = 0; i < childCount; i++) {
+ String childPackageName = childPackages.get(i).packageName;
+ childPackageNames.add(childPackageName);
+ }
+ return childPackageNames;
+ }
+
public boolean hasChildPackage(String packageName) {
final int childCount = (childPackages != null) ? childPackages.size() : 0;
for (int i = 0; i < childCount; i++) {
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 995d2ccce953..8ce8a13ea783 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -29,6 +29,7 @@ import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import android.util.ArraySet;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
/**
@@ -147,4 +148,76 @@ public class PackageUserState {
return componentInfo.enabled;
}
+
+ @Override
+ final public boolean equals(Object obj) {
+ if (!(obj instanceof PackageUserState)) {
+ return false;
+ }
+ final PackageUserState oldState = (PackageUserState) obj;
+ if (ceDataInode != oldState.ceDataInode) {
+ return false;
+ }
+ if (installed != oldState.installed) {
+ return false;
+ }
+ if (stopped != oldState.stopped) {
+ return false;
+ }
+ if (notLaunched != oldState.notLaunched) {
+ return false;
+ }
+ if (hidden != oldState.hidden) {
+ return false;
+ }
+ if (suspended != oldState.suspended) {
+ return false;
+ }
+ if (blockUninstall != oldState.blockUninstall) {
+ return false;
+ }
+ if (enabled != oldState.enabled) {
+ return false;
+ }
+ if ((lastDisableAppCaller == null && oldState.lastDisableAppCaller != null)
+ || (lastDisableAppCaller != null
+ && !lastDisableAppCaller.equals(oldState.lastDisableAppCaller))) {
+ return false;
+ }
+ if (domainVerificationStatus != oldState.domainVerificationStatus) {
+ return false;
+ }
+ if (appLinkGeneration != oldState.appLinkGeneration) {
+ return false;
+ }
+ if ((disabledComponents == null && oldState.disabledComponents != null)
+ || (disabledComponents != null && oldState.disabledComponents == null)) {
+ return false;
+ }
+ if (disabledComponents != null) {
+ if (disabledComponents.size() != oldState.disabledComponents.size()) {
+ return false;
+ }
+ for (int i = disabledComponents.size() - 1; i >=0; --i) {
+ if (!oldState.disabledComponents.contains(disabledComponents.valueAt(i))) {
+ return false;
+ }
+ }
+ }
+ if ((enabledComponents == null && oldState.enabledComponents != null)
+ || (enabledComponents != null && oldState.enabledComponents == null)) {
+ return false;
+ }
+ if (enabledComponents != null) {
+ if (enabledComponents.size() != oldState.enabledComponents.size()) {
+ return false;
+ }
+ for (int i = enabledComponents.size() - 1; i >=0; --i) {
+ if (!oldState.enabledComponents.contains(enabledComponents.valueAt(i))) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 325a93755443..4b7d210d0880 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3146,7 +3146,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// reader
synchronized (mPackages) {
for (int i=names.length-1; i>=0; i--) {
- String cur = mSettings.mRenamedPackages.get(names[i]);
+ String cur = mSettings.getRenamedPackage(names[i]);
out[i] = cur != null ? cur : names[i];
}
}
@@ -6795,7 +6795,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// reader
synchronized (mPackages) {
// Look to see if we already know about this package.
- String oldName = mSettings.mRenamedPackages.get(pkg.packageName);
+ String oldName = mSettings.getRenamedPackage(pkg.packageName);
if (pkg.mOriginalPackages != null && pkg.mOriginalPackages.contains(oldName)) {
// This package has been renamed to its original name. Let's
// use that.
@@ -8104,7 +8104,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (pkg.mOriginalPackages != null) {
// This package may need to be renamed to a previously
// installed name. Let's check on that...
- final String renamed = mSettings.mRenamedPackages.get(pkg.mRealPackage);
+ final String renamed = mSettings.getRenamedPackage(pkg.mRealPackage);
if (pkg.mOriginalPackages.contains(renamed)) {
// This package had originally been installed as the
// original name, and we have already taken care of
@@ -14044,14 +14044,15 @@ public class PackageManagerService extends IPackageManager.Stub {
if (DEBUG_INSTALL) Slog.d(TAG, "installNewPackageLI: " + pkg);
synchronized(mPackages) {
- if (mSettings.mRenamedPackages.containsKey(pkgName)) {
+ final String renamedPackage = mSettings.getRenamedPackage(pkgName);
+ if (renamedPackage != null) {
// A package with the same name is already installed, though
// it has been renamed to an older name. The package we
// are trying to install should be installed as an update to
// the existing one, but that has not been requested, so bail.
res.setError(INSTALL_FAILED_ALREADY_EXISTS, "Attempt to re-install " + pkgName
+ " without first uninstalling package running as "
- + mSettings.mRenamedPackages.get(pkgName));
+ + renamedPackage);
return;
}
if (mPackages.containsKey(pkgName)) {
@@ -14910,7 +14911,7 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mPackages) {
// Check if installing already existing package
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
- String oldName = mSettings.mRenamedPackages.get(pkgName);
+ String oldName = mSettings.getRenamedPackage(pkgName);
if (pkg.mOriginalPackages != null
&& pkg.mOriginalPackages.contains(oldName)
&& mPackages.containsKey(oldName)) {
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 851f0859753b..14ca72c14584 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -105,7 +105,7 @@ abstract class PackageSettingBase extends SettingBase {
PackageKeySetData keySetData = new PackageKeySetData();
- private static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
+ static final PackageUserState DEFAULT_USER_STATE = new PackageUserState();
// Whether this package is currently stopped, thus can not be
// started until explicitly launched by the user.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5126305dd0d1..31a1c36c7fd5 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY;
@@ -32,6 +33,7 @@ import static android.os.Process.SYSTEM_UID;
import static com.android.server.pm.PackageManagerService.DEBUG_DOMAIN_VERIFICATION;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -369,9 +371,9 @@ final class Settings {
// Packages that have been renamed since they were first installed.
// Keys are the new names of the packages, values are the original
- // names. The packages appear everwhere else under their original
+ // names. The packages appear everywhere else under their original
// names.
- final ArrayMap<String, String> mRenamedPackages = new ArrayMap<String, String>();
+ private final ArrayMap<String, String> mRenamedPackages = new ArrayMap<String, String>();
// For every user, it is used to find the package name of the default Browser App.
final SparseArray<String> mDefaultBrowserApp = new SparseArray<String>();
@@ -428,30 +430,24 @@ final class Settings {
PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi,
- int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add) {
+ int pkgFlags, int pkgPrivateFlags, UserHandle user, boolean add)
+ throws PackageManagerException {
final String name = pkg.packageName;
final String parentPackageName = (pkg.parentPackage != null)
? pkg.parentPackage.packageName : null;
-
- List<String> childPackageNames = null;
- if (pkg.childPackages != null) {
- final int childCount = pkg.childPackages.size();
- childPackageNames = new ArrayList<>(childCount);
- for (int i = 0; i < childCount; i++) {
- String childPackageName = pkg.childPackages.get(i).packageName;
- childPackageNames.add(childPackageName);
- }
- }
-
PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
resourcePath, legacyNativeLibraryPathString, primaryCpuAbi, secondaryCpuAbi,
- pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /* allowInstall */,
- parentPackageName, childPackageNames);
+ pkg.mVersionCode, pkgFlags, pkgPrivateFlags, user, add, true /*allowInstall*/,
+ parentPackageName, pkg.getChildPackageNames());
return p;
}
- PackageSetting peekPackageLPr(String name) {
- return mPackages.get(name);
+ PackageSetting peekPackageLPr(String pkgName) {
+ return mPackages.get(pkgName);
+ }
+
+ String getRenamedPackage(String pkgName) {
+ return mRenamedPackages.get(pkgName);
}
void setInstallStatus(String pkgName, final int status) {
@@ -510,6 +506,7 @@ final class Settings {
}
}
+ /** Gets and optionally creates a new shared user id. */
SharedUserSetting getSharedUserLPw(String name,
int pkgFlags, int pkgPrivateFlags, boolean create) {
SharedUserSetting s = mSharedUsers.get(name);
@@ -687,40 +684,157 @@ final class Settings {
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, int vc, int pkgFlags, int pkgPrivateFlags,
UserHandle installUser, boolean add, boolean allowInstall, String parentPackage,
- List<String> childPackageNames) {
- PackageSetting p = mPackages.get(name);
- UserManagerService userManager = UserManagerService.getInstance();
- if (p != null) {
- p.primaryCpuAbiString = primaryCpuAbiString;
- p.secondaryCpuAbiString = secondaryCpuAbiString;
- if (childPackageNames != null) {
- p.childPackageNames = new ArrayList<>(childPackageNames);
+ List<String> childPackageNames) throws PackageManagerException {
+ final UserManagerService userManager = UserManagerService.getInstance();
+ final PackageSetting disabledPackage = getDisabledSystemPkgLPr(name);
+ final PackageSetting peekPackage = peekPackageLPr(name);
+ final PackageSetting oldPackage =
+ peekPackage == null ? null : new PackageSetting(peekPackage);
+ final PackageSetting p = updatePackageSetting(peekPackage, name, realName,
+ origPackage, disabledPackage, sharedUser, codePath, resourcePath,
+ legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString, vc,
+ pkgFlags, pkgPrivateFlags, installUser, allowInstall, parentPackage,
+ childPackageNames, userManager);
+ final boolean newPackageCreated = (peekPackage == null || p != peekPackage);
+ final boolean renamedPackage = newPackageCreated && origPackage != null;
+ if (renamedPackage) {
+ mRenamedPackages.put(name, origPackage.name);
+ }
+ if (newPackageCreated) {
+ if (p.appId == 0) {
+ // Assign new user ID
+ p.appId = newUserIdLPw(p);
+ } else {
+ // Add new setting to list of user IDs
+ addUserIdLPw(p.appId, p, name);
+ }
+ if (p.appId < 0) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Package " + name + " could not be assigned a valid uid");
+ throw new PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE,
+ "Creating application package " + name + " failed");
}
+ if (add) {
+ // Finish adding new package by adding it and updating shared
+ // user preferences
+ addPackageSettingLPw(p, name, sharedUser);
+ }
+ }
+ if (peekPackageLPr(name) != null) {
+ final List<UserInfo> allUsers = getAllUsers(UserManagerService.getInstance());
+ if (allUsers != null) {
+ for (UserInfo user : allUsers) {
+ final PackageUserState oldUserState = oldPackage == null
+ ? PackageSettingBase.DEFAULT_USER_STATE
+ : oldPackage.readUserState(user.id);
+ if (!oldUserState.equals(p.readUserState(user.id))) {
+ writePackageRestrictionsLPr(user.id);
+ }
+ }
+ }
+ }
+ return p;
+ }
- if (!p.codePath.equals(codePath)) {
+ /**
+ * Updates the given package setting using the provided information.
+ * <p>
+ * WARNING: The provided PackageSetting object may be mutated.
+ *
+ * @param pkgSetting The package setting to update. If {@code null} a new PackageSetting
+ * object is created and populated.
+ * @param pkgName The name of the package.
+ * @param realPkgName The real name of the package. A package can change its name during
+ * an update. In that case, all references are to the package's original name, but, we
+ * still need it's real [new] name.
+ * @param originalPkg If the package name has changed, the package setting for the originally
+ * installed package. May be {@code null}.
+ * @param disabledPkg If the package is a system package that has been updated, the package
+ * setting for the disabled system package. May be {@code null}.
+ * @param sharedUser Shared user settings if the package declares a shared user ID.
+ * May be {@code null}.
+ * @param codePath The path to the applications code.
+ * @param resourcePath The path to the application's resources.
+ * @param legacyNativeLibraryPath The path where native libraries are unpacked.
+ * @param primaryCpuAbi The primary CPU architecture. May be {@code null}.
+ * @param secondaryCpuAbi The secondary CPU architecture, if one is defined.
+ * May be {@code null}.
+ * @param versionCode The version code of the package.
+ * @param pkgFlags Application flags for the package. {@link ApplicationInfo#flags}.
+ * @param pkgPrivateFlags Private application flags for the package.
+ * {@link ApplicationInfo#privateFlags}.
+ * @param installUser The user to install the package for. May be {@code null}.
+ * @param allowInstall Whether or not the user state for a newly created package setting can
+ * be installed.
+ * @param parentPkgName The name of the parent package. May be {@code null}.
+ * @param childPkgNames A list of child package names. May be {@code null}.
+ * @param userManager The user manager service.
+ * @return An updated package setting. It may be different than pkgSetting even when pkgSetting
+ * is not {@code null}.
+ * @throws PackageManagerException
+ */
+ static PackageSetting updatePackageSetting(@Nullable PackageSetting pkgSetting,
+ @NonNull String pkgName, @Nullable String realPkgName,
+ @Nullable PackageSetting originalPkg, @Nullable PackageSetting disabledPkg,
+ @Nullable SharedUserSetting sharedUser, @NonNull File codePath,
+ @NonNull File resourcePath, @Nullable String legacyNativeLibraryPath,
+ @Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi, int versionCode,
+ int pkgFlags, int pkgPrivateFlags, @Nullable UserHandle installUser,
+ boolean allowInstall, @Nullable String parentPkgName,
+ @Nullable List<String> childPkgNames, @NonNull UserManagerService userManager)
+ throws PackageManagerException {
+ if (pkgSetting != null) {
+ if (pkgSetting.sharedUser != sharedUser) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Package " + pkgName + " shared user changed from "
+ + (pkgSetting.sharedUser != null ? pkgSetting.sharedUser.name : "<nothing>")
+ + " to "
+ + (sharedUser != null ? sharedUser.name : "<nothing>")
+ + "; replacing with new");
+ pkgSetting = null;
+ } else {
+ // If what we are scanning is a system (and possibly privileged) package,
+ // then make it so, regardless of whether it was previously installed only
+ // in the data partition.
+ pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
+ pkgSetting.pkgPrivateFlags |=
+ pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+ }
+ }
+ if (pkgSetting != null) {
+ pkgSetting.primaryCpuAbiString = primaryCpuAbi;
+ pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
+ if (childPkgNames != null) {
+ pkgSetting.childPackageNames = new ArrayList<>(childPkgNames);
+ }
+
+ if (!pkgSetting.codePath.equals(codePath)) {
// Check to see if its a disabled system app
- if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ if ((pkgSetting.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
// This is an updated system app with versions in both system
// and data partition. Just let the most recent version
// take precedence.
- Slog.w(PackageManagerService.TAG, "Trying to update system app code path from "
- + p.codePathString + " to " + codePath.toString());
+ Slog.w(PackageManagerService.TAG,
+ "Trying to update system app code path from "
+ + pkgSetting.codePathString + " to " + codePath.toString());
} else {
// Just a change in the code path is not an issue, but
// let's log a message about it.
- Slog.i(PackageManagerService.TAG, "Package " + name + " codePath changed from "
- + p.codePath + " to " + codePath + "; Retaining data and using new");
+ Slog.i(PackageManagerService.TAG,
+ "Package " + pkgName + " codePath changed from "
+ + pkgSetting.codePath + " to " + codePath
+ + "; Retaining data and using new");
// The owner user's installed flag is set false
// when the application was installed by other user
// and the installed flag is not updated
// when the application is appended as system app later.
- if ((pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 &&
- getDisabledSystemPkgLPr(name) == null) {
- List<UserInfo> allUserInfos = getAllUsers();
+ if ((pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0
+ && disabledPkg == null) {
+ List<UserInfo> allUserInfos = getAllUsers(userManager);
if (allUserInfos != null) {
for (UserInfo userInfo : allUserInfos) {
- p.setInstalled(true, userInfo.id);
+ pkgSetting.setInstalled(true, userInfo.id);
}
}
}
@@ -731,62 +845,48 @@ final class Settings {
* package settings since we might have moved from
* internal to external storage or vice versa.
*/
- p.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
+ pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
}
}
- if (p.sharedUser != sharedUser) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + name + " shared user changed from "
- + (p.sharedUser != null ? p.sharedUser.name : "<nothing>")
- + " to "
- + (sharedUser != null ? sharedUser.name : "<nothing>")
- + "; replacing with new");
- p = null;
- } else {
- // If what we are scanning is a system (and possibly privileged) package,
- // then make it so, regardless of whether it was previously installed only
- // in the data partition.
- p.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
- p.pkgPrivateFlags |= pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
- }
}
- if (p == null) {
- if (origPackage != null) {
+ // TODO: split package setting creation logic out; invoke where getPackageLPw() is
+ // called from
+ if (pkgSetting == null) {
+ if (originalPkg != null) {
// We are consuming the data from an existing package.
- p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
- legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
- null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags,
- parentPackage, childPackageNames);
+ pkgSetting = new PackageSetting(originalPkg.name, pkgName, codePath, resourcePath,
+ legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
+ null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
+ parentPkgName, childPkgNames);
if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
- + name + " is adopting original package " + origPackage.name);
+ + pkgName + " is adopting original package " + originalPkg.name);
// Note that we will retain the new package's signature so
// that we can keep its data.
- PackageSignatures s = p.signatures;
- p.copyFrom(origPackage);
- p.signatures = s;
- p.sharedUser = origPackage.sharedUser;
- p.appId = origPackage.appId;
- p.origPackage = origPackage;
- p.getPermissionsState().copyFrom(origPackage.getPermissionsState());
- mRenamedPackages.put(name, origPackage.name);
- name = origPackage.name;
+ PackageSignatures s = pkgSetting.signatures;
+ pkgSetting.copyFrom(originalPkg);
+ pkgSetting.signatures = s;
+ pkgSetting.sharedUser = originalPkg.sharedUser;
+ pkgSetting.appId = originalPkg.appId;
+ pkgSetting.origPackage = originalPkg;
+ pkgSetting.getPermissionsState().copyFrom(originalPkg.getPermissionsState());
+ pkgName = originalPkg.name;
// Update new package state.
- p.setTimeStamp(codePath.lastModified());
+ pkgSetting.setTimeStamp(codePath.lastModified());
} else {
- p = new PackageSetting(name, realName, codePath, resourcePath,
- legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
- null /* cpuAbiOverrideString */, vc, pkgFlags, pkgPrivateFlags,
- parentPackage, childPackageNames);
- p.setTimeStamp(codePath.lastModified());
- p.sharedUser = sharedUser;
+ pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath,
+ legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
+ null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
+ parentPkgName, childPkgNames);
+ pkgSetting.setTimeStamp(codePath.lastModified());
+ pkgSetting.sharedUser = sharedUser;
// If this is not a system app, it starts out stopped.
if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
if (DEBUG_STOPPED) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
- Slog.i(PackageManagerService.TAG, "Stopping package " + name, e);
+ Slog.i(PackageManagerService.TAG, "Stopping package " + pkgName, e);
}
- List<UserInfo> users = getAllUsers();
+ List<UserInfo> users = getAllUsers(userManager);
final int installUserId = installUser != null ? installUser.getIdentifier() : 0;
if (users != null && allowInstall) {
for (UserInfo user : users) {
@@ -800,7 +900,7 @@ final class Settings {
|| (installUserId == UserHandle.USER_ALL
&& !isAdbInstallDisallowed(userManager, user.id))
|| installUserId == user.id;
- p.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
+ pkgSetting.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
installed,
true, // stopped,
true, // notLaunched
@@ -809,80 +909,64 @@ final class Settings {
null, null, null,
false, // blockUninstall
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, 0);
- writePackageRestrictionsLPr(user.id);
}
}
}
if (sharedUser != null) {
- p.appId = sharedUser.userId;
+ pkgSetting.appId = sharedUser.userId;
} else {
// Clone the setting here for disabled system packages
- PackageSetting dis = mDisabledSysPackages.get(name);
- if (dis != null) {
+ if (disabledPkg != null) {
// For disabled packages a new setting is created
// from the existing user id. This still has to be
// added to list of user id's
// Copy signatures from previous setting
- if (dis.signatures.mSignatures != null) {
- p.signatures.mSignatures = dis.signatures.mSignatures.clone();
+ if (disabledPkg.signatures.mSignatures != null) {
+ pkgSetting.signatures.mSignatures =
+ disabledPkg.signatures.mSignatures.clone();
}
- p.appId = dis.appId;
+ pkgSetting.appId = disabledPkg.appId;
// Clone permissions
- p.getPermissionsState().copyFrom(dis.getPermissionsState());
+ pkgSetting.getPermissionsState().copyFrom(
+ disabledPkg.getPermissionsState());
// Clone component info
- List<UserInfo> users = getAllUsers();
+ List<UserInfo> users = getAllUsers(userManager);
if (users != null) {
for (UserInfo user : users) {
int userId = user.id;
- p.setDisabledComponentsCopy(
- dis.getDisabledComponents(userId), userId);
- p.setEnabledComponentsCopy(
- dis.getEnabledComponents(userId), userId);
+ pkgSetting.setDisabledComponentsCopy(
+ disabledPkg.getDisabledComponents(userId), userId);
+ pkgSetting.setEnabledComponentsCopy(
+ disabledPkg.getEnabledComponents(userId), userId);
}
}
- // Add new setting to list of user ids
- addUserIdLPw(p.appId, p, name);
- } else {
- // Assign new user id
- p.appId = newUserIdLPw(p);
}
}
}
- if (p.appId < 0) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + name + " could not be assigned a valid uid");
- return null;
- }
- if (add) {
- // Finish adding new package by adding it and updating shared
- // user preferences
- addPackageSettingLPw(p, name, sharedUser);
- }
} else {
if (installUser != null && allowInstall) {
// The caller has explicitly specified the user they want this
// package installed for, and the package already exists.
// Make sure it conforms to the new request.
- List<UserInfo> users = getAllUsers();
+ List<UserInfo> users = getAllUsers(userManager);
if (users != null) {
for (UserInfo user : users) {
if ((installUser.getIdentifier() == UserHandle.USER_ALL
&& !isAdbInstallDisallowed(userManager, user.id))
|| installUser.getIdentifier() == user.id) {
- boolean installed = p.getInstalled(user.id);
+ boolean installed = pkgSetting.getInstalled(user.id);
if (!installed) {
- p.setInstalled(true, user.id);
- writePackageRestrictionsLPr(user.id);
+ pkgSetting.setInstalled(true, user.id);
}
}
}
}
}
}
- return p;
+ return pkgSetting;
}
- boolean isAdbInstallDisallowed(UserManagerService userManager, int userId) {
+ static boolean isAdbInstallDisallowed(UserManagerService userManager, int userId) {
return userManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
userId);
}
@@ -1382,7 +1466,7 @@ final class Settings {
}
void writeAllUsersPackageRestrictionsLPr() {
- List<UserInfo> users = getAllUsers();
+ List<UserInfo> users = getAllUsers(UserManagerService.getInstance());
if (users == null) return;
for (UserInfo user : users) {
@@ -2958,18 +3042,19 @@ final class Settings {
final PendingPackage pp = mPendingPackages.get(i);
Object idObj = getUserIdLPr(pp.sharedId);
if (idObj != null && idObj instanceof SharedUserSetting) {
- PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
- (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
- pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
- pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags, pp.pkgPrivateFlags,
- null, true /* add */, false /* allowInstall */, pp.parentPackageName,
- pp.childPackageNames);
- if (p == null) {
+ try {
+ PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
+ (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
+ pp.legacyNativeLibraryPathString, pp.primaryCpuAbiString,
+ pp.secondaryCpuAbiString, pp.versionCode, pp.pkgFlags,
+ pp.pkgPrivateFlags, null /*installUser*/, true /*add*/,
+ false /*allowInstall*/, pp.parentPackageName, pp.childPackageNames);
+ p.copyFrom(pp);
+ } catch (PackageManagerException e) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Unable to create application package for " + pp.name);
continue;
}
- p.copyFrom(pp);
} else if (idObj != null) {
String msg = "Bad package setting: package " + pp.name + " has shared uid "
+ pp.sharedId + " that is not a shared uid\n";
@@ -4188,10 +4273,10 @@ final class Settings {
return false;
}
- List<UserInfo> getAllUsers() {
+ private static List<UserInfo> getAllUsers(UserManagerService userManager) {
long id = Binder.clearCallingIdentity();
try {
- return UserManagerService.getInstance().getUsers(false);
+ return userManager.getUsers(false);
} catch (NullPointerException npe) {
// packagemanager not yet initialized
} finally {
@@ -4600,7 +4685,7 @@ final class Settings {
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final Date date = new Date();
boolean printedSomething = false;
- List<UserInfo> users = getAllUsers();
+ List<UserInfo> users = getAllUsers(UserManagerService.getInstance());
for (final PackageSetting ps : mPackages.values()) {
if (packageName != null && !packageName.equals(ps.realName)
&& !packageName.equals(ps.name)) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 46ff4b43d179..a9391344c7b4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -22,15 +22,21 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import android.annotation.NonNull;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
import android.content.pm.UserInfo;
+import android.os.Process;
import android.os.UserHandle;
+import android.os.UserManagerInternal;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
@@ -40,14 +46,22 @@ import android.util.Log;
import android.util.LongSparseArray;
import com.android.internal.os.AtomicFile;
+import com.android.internal.util.FastPrintWriter;
+import com.android.server.LocalServices;
+import org.hamcrest.core.IsNot;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.PrintStream;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.List;
@@ -67,7 +81,6 @@ public class PackageManagerSettingsTests {
throws ReflectiveOperationException, IllegalAccessException {
/* write out files and read */
writeOldFiles();
- createUserManagerServiceRef();
Settings settings =
new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object());
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -80,7 +93,6 @@ public class PackageManagerSettingsTests {
throws ReflectiveOperationException, IllegalAccessException {
// write out files and read
writeOldFiles();
- createUserManagerServiceRef();
Settings settings =
new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object());
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -115,7 +127,6 @@ public class PackageManagerSettingsTests {
public void testNewPackageRestrictionsFile() throws ReflectiveOperationException {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
- createUserManagerServiceRef();
Settings settings =
new Settings(InstrumentationRegistry.getContext().getFilesDir(), new Object());
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -167,6 +178,353 @@ public class PackageManagerSettingsTests {
assertThat(hasEnabled, is(false));
}
+ private static final String PACKAGE_NAME = "com.android.bar";
+ private static final String REAL_PACKAGE_NAME = "com.android.foo";
+ private static final File INITIAL_CODE_PATH =
+ new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-1");
+ private static final File UPDATED_CODE_PATH =
+ new File(InstrumentationRegistry.getContext().getFilesDir(), "com.android.bar-2");
+ private static final int INITIAL_VERSION_CODE = 10023;
+ private static final int UPDATED_VERSION_CODE = 10025;
+
+ /** Update existing package; don't install */
+ @Test
+ public void testUpdatePackageSetting01()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting pkgSetting01 = createPackageSetting(0 /*pkgFlags*/);
+ final PackageSetting oldPkgSetting01 = new PackageSetting(pkgSetting01);
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ pkgSetting01,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
+ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
+ null /*installUser*/,
+ false /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(pkgSetting01));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ final PackageUserState oldUserState = oldPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, oldUserState, false /*userStateChanged*/);
+ }
+
+ /** Update existing package; install for UserHandle.SYSTEM */
+ @Test
+ public void testUpdatePackageSetting02()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting pkgSetting01 = createPackageSetting(0 /*pkgFlags*/);
+ final PackageSetting oldPkgSetting01 = new PackageSetting(pkgSetting01);
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ pkgSetting01,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ UserHandle.SYSTEM /*installUser*/,
+ true /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(pkgSetting01));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ final PackageUserState oldUserState = oldPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ // The user state won't be changed in this scenario; the default user state is for
+ // the package to be installed.
+ verifyUserState(userState, oldUserState, false /*userStateChanged*/,
+ false /*notLaunched*/, false /*stopped*/);
+ }
+
+ /** Update existing package; install for {@code null} */
+ @Test
+ public void testUpdatePackageSetting03()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting pkgSetting01 = createPackageSetting(0 /*pkgFlags*/);
+ final PackageSetting oldPkgSetting01 = new PackageSetting(pkgSetting01);
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ pkgSetting01,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ null /*installUser*/,
+ true /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(pkgSetting01));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ final PackageUserState oldUserState = oldPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, oldUserState, false /*userStateChanged*/);
+ }
+
+ /** Update renamed package */
+ @Test
+ public void testUpdatePackageSetting04()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting originalPkgSetting = createPackageSetting(0 /*pkgFlags*/);
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ null /*pkgSetting*/,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ originalPkgSetting /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ UserHandle.SYSTEM /*installUser*/,
+ false /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(not(originalPkgSetting)));
+ // ABI isn't pulled from the original package setting
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("x86_64"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("x86"));
+ assertThat(testPkgSetting01.origPackage, is(originalPkgSetting));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, PackageSettingBase.DEFAULT_USER_STATE /*oldUserState*/,
+ false /*userStateChanged*/);
+ }
+
+ /** Update new package */
+ @Test
+ public void testUpdatePackageSetting05()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ null /*pkgSetting*/,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ null /*installUser*/,
+ false /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(notNullValue()));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, PackageSettingBase.DEFAULT_USER_STATE /*oldUserState*/,
+ false /*userStateChanged*/);
+ }
+
+ /** Update new package; install for {@code null} user */
+ @Test
+ public void testUpdatePackageSetting06()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ null /*pkgSetting*/,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ null /*installUser*/,
+ true /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(notNullValue()));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, PackageSettingBase.DEFAULT_USER_STATE /*oldUserState*/,
+ true /*userStateChanged*/, true /*notLaunched*/, true /*stopped*/);
+ }
+
+ /** Update new package; install for UserHandle.SYSTEM */
+ @Test
+ public void testUpdatePackageSetting07()
+ throws ReflectiveOperationException, PackageManagerException {
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ null /*pkgSetting*/,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ null /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ UserHandle.SYSTEM /*installUser*/,
+ true /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(notNullValue()));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, PackageSettingBase.DEFAULT_USER_STATE /*oldUserState*/,
+ true /*userStateChanged*/, true /*notLaunched*/, true /*stopped*/);
+ }
+
+ /** Update package, but, shared user changed; ensure old setting not modified */
+ @Test
+ public void testUpdatePackageSetting08()
+ throws ReflectiveOperationException, PackageManagerException {
+ final SharedUserSetting testSharedUser =
+ new SharedUserSetting("testSharedUser", 0 /*pkgFlags*/, 0 /*_pkgPrivateFlags*/);
+ testSharedUser.userId = Process.FIRST_APPLICATION_UID + 9995;
+ final PackageSetting pkgSetting01 = createPackageSetting(0 /*pkgFlags*/);
+ final PackageSetting oldPkgSetting01 = new PackageSetting(pkgSetting01);
+ final PackageSetting testPkgSetting01 = Settings.updatePackageSetting(
+ pkgSetting01,
+ PACKAGE_NAME,
+ null /*realPkgName*/,
+ null /*originalPkg*/,
+ null /*disabledPkg*/,
+ testSharedUser /*sharedUser*/,
+ UPDATED_CODE_PATH /*codePath*/,
+ UPDATED_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPath*/,
+ "arm64-v8a" /*primaryCpuAbi*/,
+ "armeabi" /*secondaryCpuAbi*/,
+ UPDATED_VERSION_CODE /*versionCode*/,
+ 0 /*pkgFlags*/,
+ 0 /*pkgPrivateFlags*/,
+ UserHandle.SYSTEM /*installUser*/,
+ true /*allowInstall*/,
+ null /*parentPkgName*/,
+ null /*childPkgNames*/,
+ UserManagerService.getInstance());
+ assertThat(testPkgSetting01, is(not(pkgSetting01)));
+ assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
+ assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
+ assertThat(testPkgSetting01.origPackage, is(nullValue()));
+ assertThat(testPkgSetting01.appId, is(19995));
+ assertThat(testPkgSetting01.pkgFlags, is(0));
+ assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
+ // package setting should not have been modified
+ assertThat(pkgSetting01.primaryCpuAbiString, is("x86_64"));
+ assertThat(pkgSetting01.secondaryCpuAbiString, is("x86"));
+ final PackageUserState userState = testPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ final PackageUserState oldUserState = oldPkgSetting01.readUserState(UserHandle.USER_SYSTEM);
+ verifyUserState(userState, oldUserState, true /*userStateChanged*/,
+ true /*notLaunched*/, true /*stopped*/);
+ }
+
+ private void verifyUserState(PackageUserState userState, PackageUserState oldUserState,
+ boolean userStateChanged) {
+ verifyUserState(userState, oldUserState, userStateChanged, false /*notLaunched*/,
+ false /*stopped*/);
+ }
+
+ private void verifyUserState(PackageUserState userState, PackageUserState oldUserState,
+ boolean userStateChanged, boolean notLaunched, boolean stopped) {
+ assertThat(userState.blockUninstall, is(false));
+ assertThat(userState.enabled, is(0));
+ assertThat(userState.hidden, is(false));
+ assertThat(userState.installed, is(true));
+ assertThat(userState.notLaunched, is(notLaunched));
+ assertThat(userState.stopped, is(stopped));
+ assertThat(userState.suspended, is(false));
+ if (oldUserState != null) {
+ assertThat(userState.equals(oldUserState), is(not(userStateChanged)));
+ }
+ }
+
+ private PackageSetting createPackageSetting(int pkgFlags) {
+ return new PackageSetting(
+ PACKAGE_NAME,
+ REAL_PACKAGE_NAME,
+ INITIAL_CODE_PATH /*codePath*/,
+ INITIAL_CODE_PATH /*resourcePath*/,
+ null /*legacyNativeLibraryPathString*/,
+ "x86_64" /*primaryCpuAbiString*/,
+ "x86" /*secondaryCpuAbiString*/,
+ null /*cpuAbiOverrideString*/,
+ INITIAL_VERSION_CODE,
+ pkgFlags,
+ 0 /*privateFlags*/,
+ null /*parentPackageName*/,
+ null /*childPackageNames*/);
+ }
+
private @NonNull List<UserInfo> createFakeUsers() {
ArrayList<UserInfo> users = new ArrayList<>();
users.add(new UserInfo(UserHandle.USER_SYSTEM, "test user", UserInfo.FLAG_INITIALIZED));
@@ -295,12 +653,19 @@ public class PackageManagerSettingsTests {
writePackagesList();
}
- private void createUserManagerServiceRef() throws ReflectiveOperationException {
+ @Before
+ public void createUserManagerServiceRef() throws ReflectiveOperationException {
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
Constructor<UserManagerService> umsc;
try {
+ // unregister the user manager from the local service
+ Method removeServiceForTest = LocalServices.class.getDeclaredMethod(
+ "removeServiceForTest", Class.class);
+ removeServiceForTest.invoke(null, UserManagerInternal.class);
+
+ // now create a new user manager [which registers again with the local service]
umsc = UserManagerService.class.getDeclaredConstructor(
Context.class,
PackageManagerService.class,
@@ -313,7 +678,7 @@ public class PackageManagerSettingsTests {
} catch (SecurityException
| ReflectiveOperationException
| IllegalArgumentException e) {
- fail("Could not create user manager service; msg=" + e.getMessage());
+ fail("Could not create user manager service; " + e);
}
}
});
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
new file mode 100644
index 000000000000..bf05f21f32d5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import android.content.pm.PackageUserState;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArraySet;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PackageUserStateTest {
+
+ @Test
+ public void testPackageUserState01() {
+ final PackageUserState testUserState = new PackageUserState();
+ PackageUserState oldUserState;
+
+ oldUserState = new PackageUserState();
+ assertThat(testUserState.equals(null), is(false));
+ assertThat(testUserState.equals(testUserState), is(true));
+ assertThat(testUserState.equals(oldUserState), is(true));
+
+ oldUserState = new PackageUserState();
+ oldUserState.appLinkGeneration = 6;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.blockUninstall = true;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.ceDataInode = 4000L;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.domainVerificationStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.enabled = COMPONENT_ENABLED_STATE_ENABLED;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.hidden = true;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.installed = false;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.notLaunched = true;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.stopped = true;
+ assertThat(testUserState.equals(oldUserState), is(false));
+
+ oldUserState = new PackageUserState();
+ oldUserState.suspended = true;
+ assertThat(testUserState.equals(oldUserState), is(false));
+ }
+
+ @Test
+ public void testPackageUserState02() {
+ final PackageUserState testUserState01 = new PackageUserState();
+ PackageUserState oldUserState;
+
+ oldUserState = new PackageUserState();
+ oldUserState.lastDisableAppCaller = "unit_test";
+ assertThat(testUserState01.equals(oldUserState), is(false));
+
+ final PackageUserState testUserState02 = new PackageUserState();
+ testUserState02.lastDisableAppCaller = "unit_test";
+ assertThat(testUserState02.equals(oldUserState), is(true));
+
+ final PackageUserState testUserState03 = new PackageUserState();
+ testUserState03.lastDisableAppCaller = "unit_test_00";
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ }
+
+ @Test
+ public void testPackageUserState03() {
+ final PackageUserState oldUserState = new PackageUserState();
+
+ // only new user state has array defined; different
+ final PackageUserState testUserState01 = new PackageUserState();
+ testUserState01.disabledComponents = new ArraySet<>();
+ assertThat(testUserState01.equals(oldUserState), is(false));
+
+ // only old user state has array defined; different
+ final PackageUserState testUserState02 = new PackageUserState();
+ oldUserState.disabledComponents = new ArraySet<>();
+ assertThat(testUserState02.equals(oldUserState), is(false));
+
+ // both states have array defined; not different
+ final PackageUserState testUserState03 = new PackageUserState();
+ testUserState03.disabledComponents = new ArraySet<>();
+ assertThat(testUserState03.equals(oldUserState), is(true));
+ // fewer elements in old user state; different
+ testUserState03.disabledComponents.add("com.android.unit_test01");
+ testUserState03.disabledComponents.add("com.android.unit_test02");
+ testUserState03.disabledComponents.add("com.android.unit_test03");
+ oldUserState.disabledComponents.add("com.android.unit_test03");
+ oldUserState.disabledComponents.add("com.android.unit_test02");
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ // same elements in old user state; not different
+ oldUserState.disabledComponents.add("com.android.unit_test01");
+ assertThat(testUserState03.equals(oldUserState), is(true));
+ // more elements in old user state; different
+ oldUserState.disabledComponents.add("com.android.unit_test04");
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ // different elements in old user state; different
+ testUserState03.disabledComponents.add("com.android.unit_test_04");
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ }
+
+ @Test
+ public void testPackageUserState04() {
+ final PackageUserState oldUserState = new PackageUserState();
+
+ // only new user state has array defined; different
+ final PackageUserState testUserState01 = new PackageUserState();
+ testUserState01.enabledComponents = new ArraySet<>();
+ assertThat(testUserState01.equals(oldUserState), is(false));
+
+ // only old user state has array defined; different
+ final PackageUserState testUserState02 = new PackageUserState();
+ oldUserState.enabledComponents = new ArraySet<>();
+ assertThat(testUserState02.equals(oldUserState), is(false));
+
+ // both states have array defined; not different
+ final PackageUserState testUserState03 = new PackageUserState();
+ testUserState03.enabledComponents = new ArraySet<>();
+ assertThat(testUserState03.equals(oldUserState), is(true));
+ // fewer elements in old user state; different
+ testUserState03.enabledComponents.add("com.android.unit_test01");
+ testUserState03.enabledComponents.add("com.android.unit_test02");
+ testUserState03.enabledComponents.add("com.android.unit_test03");
+ oldUserState.enabledComponents.add("com.android.unit_test03");
+ oldUserState.enabledComponents.add("com.android.unit_test02");
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ // same elements in old user state; not different
+ oldUserState.enabledComponents.add("com.android.unit_test01");
+ assertThat(testUserState03.equals(oldUserState), is(true));
+ // more elements in old user state; different
+ oldUserState.enabledComponents.add("com.android.unit_test04");
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ // different elements in old user state; different
+ testUserState03.enabledComponents.add("com.android.unit_test_04");
+ assertThat(testUserState03.equals(oldUserState), is(false));
+ }
+}