summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Todd Kennedy <toddke@google.com> 2016-08-01 13:38:57 -0700
committer Todd Kennedy <toddke@google.com> 2016-08-04 10:38:39 -0700
commit13715d521f340d24f1de6e06ceaaf2a945910c0d (patch)
tree4a03129ffdc5da28d05549aafc697a60db734a89
parent347117f556afe91e943d1139867c33d964d94b43 (diff)
Break out static update method
Simply getting package settings could changes stored state. Break out the majority of the method to modify local variables and not change any stored state. The top-level getPackageLPw() method will still mutate stored state. This will be changed in a future CL. Also add a set of tests to verify the behaviour of updatePackageSetting() Bug: 30219944 Change-Id: I3360a36ce238e816246ee8ca7ecabfbbcdf0b89d
-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));
+ }
+}