diff options
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)); + } +} |