Merge "UserSystemPackageInstaller only (un)installs when appropriate" into rvc-dev am: 9968525afb
Change-Id: I1c38607cf0d9a8654ec8d13bb872d296deef4c50
This commit is contained in:
@@ -1031,6 +1031,27 @@ public abstract class PackageManager {
|
||||
*/
|
||||
public static final int INSTALL_REASON_ROLLBACK = 5;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "UNINSTALL_REASON_" }, value = {
|
||||
UNINSTALL_REASON_UNKNOWN,
|
||||
UNINSTALL_REASON_USER_TYPE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface UninstallReason {}
|
||||
|
||||
/**
|
||||
* Code indicating that the reason for uninstalling this package is unknown.
|
||||
* @hide
|
||||
*/
|
||||
public static final int UNINSTALL_REASON_UNKNOWN = 0;
|
||||
|
||||
/**
|
||||
* Code indicating that this package was uninstalled due to the type of user.
|
||||
* See UserSystemPackageInstaller
|
||||
* @hide
|
||||
*/
|
||||
public static final int UNINSTALL_REASON_USER_TYPE = 1;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -74,6 +74,7 @@ public class PackageUserState {
|
||||
public int appLinkGeneration;
|
||||
public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
|
||||
public int installReason;
|
||||
public @PackageManager.UninstallReason int uninstallReason;
|
||||
public String harmfulAppWarning;
|
||||
|
||||
public ArraySet<String> disabledComponents;
|
||||
@@ -92,6 +93,7 @@ public class PackageUserState {
|
||||
domainVerificationStatus =
|
||||
PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
|
||||
installReason = PackageManager.INSTALL_REASON_UNKNOWN;
|
||||
uninstallReason = PackageManager.UNINSTALL_REASON_UNKNOWN;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -112,6 +114,7 @@ public class PackageUserState {
|
||||
appLinkGeneration = o.appLinkGeneration;
|
||||
categoryHint = o.categoryHint;
|
||||
installReason = o.installReason;
|
||||
uninstallReason = o.uninstallReason;
|
||||
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
|
||||
enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
|
||||
overlayPaths =
|
||||
@@ -353,6 +356,9 @@ public class PackageUserState {
|
||||
if (installReason != oldState.installReason) {
|
||||
return false;
|
||||
}
|
||||
if (uninstallReason != oldState.uninstallReason) {
|
||||
return false;
|
||||
}
|
||||
if ((disabledComponents == null && oldState.disabledComponents != null)
|
||||
|| (disabledComponents != null && oldState.disabledComponents == null)) {
|
||||
return false;
|
||||
@@ -407,6 +413,7 @@ public class PackageUserState {
|
||||
hashCode = 31 * hashCode + appLinkGeneration;
|
||||
hashCode = 31 * hashCode + categoryHint;
|
||||
hashCode = 31 * hashCode + installReason;
|
||||
hashCode = 31 * hashCode + uninstallReason;
|
||||
hashCode = 31 * hashCode + Objects.hashCode(disabledComponents);
|
||||
hashCode = 31 * hashCode + Objects.hashCode(enabledComponents);
|
||||
hashCode = 31 * hashCode + Objects.hashCode(harmfulAppWarning);
|
||||
|
||||
@@ -2406,8 +2406,7 @@
|
||||
- to henceforth disable feature and try to undo its previous effects: 0
|
||||
Note: This list must be kept current with PACKAGE_WHITELIST_MODE_PROP in
|
||||
frameworks/base/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java -->
|
||||
<integer name="config_userTypePackageWhitelistMode">29</integer> <!-- 1+4+8+16 -->
|
||||
<!-- TODO(b/143200798): Change to value 13, i.e. 1+4+8, when b/143200798 is resolved. -->
|
||||
<integer name="config_userTypePackageWhitelistMode">13</integer> <!-- 1+4+8 -->
|
||||
|
||||
<!-- Whether UI for multi user should be shown -->
|
||||
<bool name="config_enableMultiUserUI">false</bool>
|
||||
|
||||
@@ -97,8 +97,8 @@ The way that a device treats system packages that do not have any entry (for any
|
||||
is determined by the config resource value config_userTypePackageWhitelistMode.
|
||||
See frameworks/base/core/res/res/values/config.xml#config_userTypePackageWhitelistMode.
|
||||
|
||||
Changes to the whitelist during system updates can result in installing new system packages
|
||||
to pre-existing users, but cannot uninstall system packages from pre-existing users.
|
||||
Changes to the whitelist during system updates can result in installing additional system packages
|
||||
to pre-existing users, but cannot uninstall pre-existing system packages from pre-existing users.
|
||||
-->
|
||||
<config>
|
||||
<install-in-user-type package="com.android.providers.settings">
|
||||
|
||||
@@ -426,17 +426,6 @@ public abstract class PackageManagerInternal {
|
||||
*/
|
||||
public abstract String getNameForUid(int uid);
|
||||
|
||||
/**
|
||||
* Marks a package as installed (or not installed) for a given user.
|
||||
*
|
||||
* @param pkg the package whose installation is to be set
|
||||
* @param userId the user for whom to set it
|
||||
* @param installed the new installed state
|
||||
* @return true if the installed state changed as a result
|
||||
*/
|
||||
public abstract boolean setInstalled(AndroidPackage pkg,
|
||||
@UserIdInt int userId, boolean installed);
|
||||
|
||||
/**
|
||||
* Request to perform the second phase of ephemeral resolution.
|
||||
* @param responseObj The response of the first phase of ephemeral resolution
|
||||
@@ -521,12 +510,6 @@ public abstract class PackageManagerInternal {
|
||||
*/
|
||||
public abstract boolean isPackagePersistent(String packageName);
|
||||
|
||||
/**
|
||||
* Returns whether or not the given package represents a legacy system application released
|
||||
* prior to runtime permissions.
|
||||
*/
|
||||
public abstract boolean isLegacySystemApp(AndroidPackage pkg);
|
||||
|
||||
/**
|
||||
* Get all overlay packages for a user.
|
||||
* @param userId The user for which to get the overlays.
|
||||
|
||||
@@ -93,6 +93,7 @@ import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
|
||||
import static android.content.pm.PackageManager.PERMISSION_DENIED;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.content.pm.PackageManager.RESTRICTION_NONE;
|
||||
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
|
||||
import static android.content.pm.PackageParser.isApkFile;
|
||||
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
|
||||
import static android.os.incremental.IncrementalManager.isIncrementalPath;
|
||||
@@ -736,9 +737,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
|
||||
|
||||
/**
|
||||
* Tracks existing system packages prior to receiving an OTA. Keys are package name.
|
||||
* Tracks existing packages prior to receiving an OTA. Keys are package name.
|
||||
* Only non-null during an OTA, and even then it is nulled again once systemReady().
|
||||
*/
|
||||
final private ArraySet<String> mExistingSystemPackages = new ArraySet<>();
|
||||
private @Nullable ArraySet<String> mExistingPackages = null;
|
||||
/**
|
||||
* Whether or not system app permissions should be promoted from install to runtime.
|
||||
*/
|
||||
@@ -2569,9 +2571,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
private void installWhitelistedSystemPackages() {
|
||||
synchronized (mLock) {
|
||||
final boolean scheduleWrite = mUserManager.installWhitelistedSystemPackages(
|
||||
isFirstBoot(), isDeviceUpgrading());
|
||||
isFirstBoot(), isDeviceUpgrading(), mExistingPackages);
|
||||
if (scheduleWrite) {
|
||||
scheduleWritePackageRestrictionsLocked(UserHandle.USER_ALL);
|
||||
scheduleWriteSettingsLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2881,13 +2884,12 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
|
||||
mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
|
||||
|
||||
// save off the names of pre-existing system packages prior to scanning; we don't
|
||||
// want to automatically grant runtime permissions for new system apps
|
||||
if (mPromoteSystemApps) {
|
||||
// Save the names of pre-existing packages prior to scanning, so we can determine
|
||||
// which system packages are completely new due to an upgrade.
|
||||
if (isDeviceUpgrading()) {
|
||||
mExistingPackages = new ArraySet<>(mSettings.mPackages.size());
|
||||
for (PackageSetting ps : mSettings.mPackages.values()) {
|
||||
if (isSystemApp(ps)) {
|
||||
mExistingSystemPackages.add(ps.name);
|
||||
}
|
||||
mExistingPackages.add(ps.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3348,7 +3350,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
// clear only after permissions and other defaults have been updated
|
||||
mExistingSystemPackages.clear();
|
||||
mPromoteSystemApps = false;
|
||||
|
||||
// All the changes are done during package scanning.
|
||||
@@ -12775,6 +12776,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
pkgSetting.setInstalled(true, userId);
|
||||
pkgSetting.setHidden(false, userId);
|
||||
pkgSetting.setInstallReason(installReason, userId);
|
||||
pkgSetting.setUninstallReason(PackageManager.UNINSTALL_REASON_UNKNOWN, userId);
|
||||
mSettings.writePackageRestrictionsLPr(userId);
|
||||
mSettings.writeKernelMappingLPr(pkgSetting);
|
||||
installed = true;
|
||||
@@ -15607,7 +15609,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
// It's implied that when a user requests installation, they want the app to be
|
||||
// installed and enabled.
|
||||
// installed and enabled. (This does not apply to USER_ALL, which here means only
|
||||
// install on users for which the app is already installed).
|
||||
if (userId != UserHandle.USER_ALL) {
|
||||
ps.setInstalled(true, userId);
|
||||
ps.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, userId, installerPackageName);
|
||||
@@ -15625,7 +15628,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mSettings.addInstallerPackageNames(installSource);
|
||||
|
||||
// When replacing an existing package, preserve the original install reason for all
|
||||
// users that had the package installed before.
|
||||
// users that had the package installed before. Similarly for uninstall reasons.
|
||||
final Set<Integer> previousUserIds = new ArraySet<>();
|
||||
if (res.removedInfo != null && res.removedInfo.installReasons != null) {
|
||||
final int installReasonCount = res.removedInfo.installReasons.size();
|
||||
@@ -15636,10 +15639,20 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
previousUserIds.add(previousUserId);
|
||||
}
|
||||
}
|
||||
if (res.removedInfo != null && res.removedInfo.uninstallReasons != null) {
|
||||
for (int i = 0; i < res.removedInfo.uninstallReasons.size(); i++) {
|
||||
final int previousUserId = res.removedInfo.uninstallReasons.keyAt(i);
|
||||
final int previousReason = res.removedInfo.uninstallReasons.valueAt(i);
|
||||
ps.setUninstallReason(previousReason, previousUserId);
|
||||
}
|
||||
}
|
||||
|
||||
// Set install reason for users that are having the package newly installed.
|
||||
final int[] allUsersList = mUserManager.getUserIds();
|
||||
if (userId == UserHandle.USER_ALL) {
|
||||
for (int currentUserId : mUserManager.getUserIds()) {
|
||||
// TODO(b/152629990): It appears that the package doesn't actually get newly
|
||||
// installed in this case, so the installReason shouldn't get modified?
|
||||
for (int currentUserId : allUsersList) {
|
||||
if (!previousUserIds.contains(currentUserId)) {
|
||||
ps.setInstallReason(installReason, currentUserId);
|
||||
}
|
||||
@@ -15647,6 +15660,12 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
} else if (!previousUserIds.contains(userId)) {
|
||||
ps.setInstallReason(installReason, userId);
|
||||
}
|
||||
// Ensure that the uninstall reason is UNKNOWN for users with the package installed.
|
||||
for (int currentUserId : allUsersList) {
|
||||
if (ps.getInstalled(currentUserId)) {
|
||||
ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, currentUserId);
|
||||
}
|
||||
}
|
||||
mSettings.writeKernelMappingLPr(ps);
|
||||
}
|
||||
res.name = pkgName;
|
||||
@@ -17010,6 +17029,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final String pkgName11 = parsedPackage.getPackageName();
|
||||
final int[] allUsers;
|
||||
final int[] installedUsers;
|
||||
final int[] uninstalledUsers;
|
||||
|
||||
synchronized (mLock) {
|
||||
oldPackage = mPackages.get(pkgName11);
|
||||
@@ -17084,6 +17104,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// In case of rollback, remember per-user/profile install state
|
||||
allUsers = mUserManager.getUserIds();
|
||||
installedUsers = ps.queryInstalledUsers(allUsers, true);
|
||||
uninstalledUsers = ps.queryInstalledUsers(allUsers, false);
|
||||
|
||||
|
||||
// don't allow an upgrade from full to ephemeral
|
||||
@@ -17122,6 +17143,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final int userId = installedUsers[i];
|
||||
res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
|
||||
}
|
||||
res.removedInfo.uninstallReasons = new SparseArray<>(uninstalledUsers.length);
|
||||
for (int i = 0; i < uninstalledUsers.length; i++) {
|
||||
final int userId = uninstalledUsers[i];
|
||||
res.removedInfo.uninstallReasons.put(userId, ps.getUninstallReason(userId));
|
||||
}
|
||||
|
||||
sysPkg = oldPackage.isSystem();
|
||||
if (sysPkg) {
|
||||
@@ -17954,6 +17980,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
int[] broadcastUsers = null;
|
||||
int[] instantUserIds = null;
|
||||
SparseArray<Integer> installReasons;
|
||||
SparseArray<Integer> uninstallReasons;
|
||||
boolean isRemovedPackageSystemUpdate = false;
|
||||
boolean isUpdate;
|
||||
boolean dataRemoved;
|
||||
@@ -18176,6 +18203,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
installedStateChanged = true;
|
||||
}
|
||||
deletedPs.setInstalled(installed, userId);
|
||||
if (installed) {
|
||||
deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18358,6 +18388,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
installedStateChanged = true;
|
||||
}
|
||||
ps.setInstalled(installed, userId);
|
||||
if (installed) {
|
||||
ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
|
||||
}
|
||||
|
||||
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
|
||||
}
|
||||
@@ -18630,7 +18663,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
null /*enabledComponents*/,
|
||||
null /*disabledComponents*/,
|
||||
ps.readUserState(nextUserId).domainVerificationStatus,
|
||||
0, PackageManager.INSTALL_REASON_UNKNOWN,
|
||||
0 /*linkGeneration*/,
|
||||
PackageManager.INSTALL_REASON_UNKNOWN,
|
||||
PackageManager.UNINSTALL_REASON_UNKNOWN,
|
||||
null /*harmfulAppWarning*/);
|
||||
}
|
||||
mSettings.writeKernelMappingLPr(ps);
|
||||
@@ -20781,6 +20816,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// installation on reboot. Make sure this is the last component to be call since the
|
||||
// installation might require other components to be ready.
|
||||
mInstallerService.restoreAndApplyStagedSessionIfNeeded();
|
||||
|
||||
mExistingPackages = null;
|
||||
}
|
||||
|
||||
public void waitForAppDataPrepared() {
|
||||
@@ -22733,16 +22770,17 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
/**
|
||||
* Called by UserManagerService.
|
||||
*
|
||||
* @param installablePackages system packages that should be initially installed for this user,
|
||||
* or {@code null} if all system packages should be installed
|
||||
* @param userTypeInstallablePackages system packages that should be initially installed for
|
||||
* this type of user, or {@code null} if all system packages
|
||||
* should be installed
|
||||
* @param disallowedPackages packages that should not be initially installed. Takes precedence
|
||||
* over installablePackages.
|
||||
*/
|
||||
void createNewUser(int userId, @Nullable Set<String> installablePackages,
|
||||
void createNewUser(int userId, @Nullable Set<String> userTypeInstallablePackages,
|
||||
String[] disallowedPackages) {
|
||||
synchronized (mInstallLock) {
|
||||
mSettings.createNewUserLI(this, mInstaller, userId,
|
||||
installablePackages, disallowedPackages);
|
||||
userTypeInstallablePackages, disallowedPackages);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
scheduleWritePackageRestrictionsLocked(userId);
|
||||
@@ -23755,19 +23793,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
return PackageManagerService.this.getNameForUid(uid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setInstalled(AndroidPackage pkg, @UserIdInt int userId,
|
||||
boolean installed) {
|
||||
synchronized (mLock) {
|
||||
final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName());
|
||||
if (ps.getInstalled(userId) != installed) {
|
||||
ps.setInstalled(installed, userId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
|
||||
Intent origIntent, String resolvedType, String callingPackage,
|
||||
@@ -23837,16 +23862,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegacySystemApp(AndroidPackage pkg) {
|
||||
synchronized (mLock) {
|
||||
final PackageSetting ps = getPackageSetting(pkg.getPackageName());
|
||||
return mPromoteSystemApps
|
||||
&& ps.isSystem()
|
||||
&& mExistingSystemPackages.contains(ps.name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PackageInfo> getOverlayPackages(int userId) {
|
||||
final ArrayList<PackageInfo> overlayPackages = new ArrayList<PackageInfo>();
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IntentFilterVerificationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.UninstallReason;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageUserState;
|
||||
import android.content.pm.Signature;
|
||||
@@ -315,6 +316,14 @@ public abstract class PackageSettingBase extends SettingBase {
|
||||
modifyUserState(userId).installReason = installReason;
|
||||
}
|
||||
|
||||
int getUninstallReason(int userId) {
|
||||
return readUserState(userId).uninstallReason;
|
||||
}
|
||||
|
||||
void setUninstallReason(@UninstallReason int uninstallReason, int userId) {
|
||||
modifyUserState(userId).uninstallReason = uninstallReason;
|
||||
}
|
||||
|
||||
void setOverlayPaths(List<String> overlayPaths, int userId) {
|
||||
modifyUserState(userId).setOverlayPaths(overlayPaths == null ? null :
|
||||
overlayPaths.toArray(new String[overlayPaths.size()]));
|
||||
@@ -471,7 +480,7 @@ public abstract class PackageSettingBase extends SettingBase {
|
||||
ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp,
|
||||
boolean virtualPreload, String lastDisableAppCaller,
|
||||
ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
|
||||
int domainVerifState, int linkGeneration, int installReason,
|
||||
int domainVerifState, int linkGeneration, int installReason, int uninstallReason,
|
||||
String harmfulAppWarning) {
|
||||
PackageUserState state = modifyUserState(userId);
|
||||
state.ceDataInode = ceDataInode;
|
||||
@@ -489,6 +498,7 @@ public abstract class PackageSettingBase extends SettingBase {
|
||||
state.domainVerificationStatus = domainVerifState;
|
||||
state.appLinkGeneration = linkGeneration;
|
||||
state.installReason = installReason;
|
||||
state.uninstallReason = uninstallReason;
|
||||
state.instantApp = instantApp;
|
||||
state.virtualPreload = virtualPreload;
|
||||
state.harmfulAppWarning = harmfulAppWarning;
|
||||
@@ -502,7 +512,7 @@ public abstract class PackageSettingBase extends SettingBase {
|
||||
otherState.virtualPreload, otherState.lastDisableAppCaller,
|
||||
otherState.enabledComponents, otherState.disabledComponents,
|
||||
otherState.domainVerificationStatus, otherState.appLinkGeneration,
|
||||
otherState.installReason, otherState.harmfulAppWarning);
|
||||
otherState.installReason, otherState.uninstallReason, otherState.harmfulAppWarning);
|
||||
}
|
||||
|
||||
ArraySet<String> getEnabledComponents(int userId) {
|
||||
|
||||
@@ -24,6 +24,8 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOM
|
||||
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;
|
||||
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
|
||||
import static android.content.pm.PackageManager.UNINSTALL_REASON_USER_TYPE;
|
||||
import static android.os.Process.PACKAGE_INFO_GID;
|
||||
import static android.os.Process.SYSTEM_UID;
|
||||
|
||||
@@ -266,6 +268,7 @@ public final class Settings {
|
||||
private static final String ATTR_DOMAIN_VERIFICATON_STATE = "domainVerificationStatus";
|
||||
private static final String ATTR_APP_LINK_GENERATION = "app-link-generation";
|
||||
private static final String ATTR_INSTALL_REASON = "install-reason";
|
||||
private static final String ATTR_UNINSTALL_REASON = "uninstall-reason";
|
||||
private static final String ATTR_INSTANT_APP = "instant-app";
|
||||
private static final String ATTR_VIRTUAL_PRELOAD = "virtual-preload";
|
||||
private static final String ATTR_HARMFUL_APP_WARNING = "harmful-app-warning";
|
||||
@@ -684,7 +687,9 @@ public final class Settings {
|
||||
null /*enabledComponents*/,
|
||||
null /*disabledComponents*/,
|
||||
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
|
||||
0, PackageManager.INSTALL_REASON_UNKNOWN,
|
||||
0 /*linkGeneration*/,
|
||||
PackageManager.INSTALL_REASON_UNKNOWN,
|
||||
PackageManager.UNINSTALL_REASON_UNKNOWN,
|
||||
null /*harmfulAppWarning*/);
|
||||
}
|
||||
}
|
||||
@@ -768,6 +773,7 @@ public final class Settings {
|
||||
if (allUserInfos != null) {
|
||||
for (UserInfo userInfo : allUserInfos) {
|
||||
pkgSetting.setInstalled(true, userInfo.id);
|
||||
pkgSetting.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userInfo.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1580,7 +1586,9 @@ public final class Settings {
|
||||
null /*enabledComponents*/,
|
||||
null /*disabledComponents*/,
|
||||
INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
|
||||
0, PackageManager.INSTALL_REASON_UNKNOWN,
|
||||
0 /*linkGeneration*/,
|
||||
PackageManager.INSTALL_REASON_UNKNOWN,
|
||||
PackageManager.UNINSTALL_REASON_UNKNOWN,
|
||||
null /*harmfulAppWarning*/);
|
||||
}
|
||||
return;
|
||||
@@ -1678,6 +1686,8 @@ public final class Settings {
|
||||
}
|
||||
final int installReason = XmlUtils.readIntAttribute(parser,
|
||||
ATTR_INSTALL_REASON, PackageManager.INSTALL_REASON_UNKNOWN);
|
||||
final int uninstallReason = XmlUtils.readIntAttribute(parser,
|
||||
ATTR_UNINSTALL_REASON, PackageManager.UNINSTALL_REASON_UNKNOWN);
|
||||
|
||||
ArraySet<String> enabledComponents = null;
|
||||
ArraySet<String> disabledComponents = null;
|
||||
@@ -1751,7 +1761,7 @@ public final class Settings {
|
||||
hidden, distractionFlags, suspended, suspendParamsMap,
|
||||
instantApp, virtualPreload,
|
||||
enabledCaller, enabledComponents, disabledComponents, verifState,
|
||||
linkGeneration, installReason, harmfulAppWarning);
|
||||
linkGeneration, installReason, uninstallReason, harmfulAppWarning);
|
||||
} else if (tagName.equals("preferred-activities")) {
|
||||
readPreferredActivitiesLPw(parser, userId);
|
||||
} else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
|
||||
@@ -2079,6 +2089,10 @@ public final class Settings {
|
||||
serializer.attribute(null, ATTR_INSTALL_REASON,
|
||||
Integer.toString(ustate.installReason));
|
||||
}
|
||||
if (ustate.uninstallReason != PackageManager.UNINSTALL_REASON_UNKNOWN) {
|
||||
serializer.attribute(null, ATTR_UNINSTALL_REASON,
|
||||
Integer.toString(ustate.uninstallReason));
|
||||
}
|
||||
if (ustate.harmfulAppWarning != null) {
|
||||
serializer.attribute(null, ATTR_HARMFUL_APP_WARNING,
|
||||
ustate.harmfulAppWarning);
|
||||
@@ -4126,7 +4140,7 @@ public final class Settings {
|
||||
}
|
||||
|
||||
void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer,
|
||||
@UserIdInt int userHandle, @Nullable Set<String> installablePackages,
|
||||
@UserIdInt int userHandle, @Nullable Set<String> userTypeInstallablePackages,
|
||||
String[] disallowedPackages) {
|
||||
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
|
||||
Trace.TRACE_TAG_PACKAGE_MANAGER);
|
||||
@@ -4137,7 +4151,7 @@ public final class Settings {
|
||||
String[] seinfos;
|
||||
int[] targetSdkVersions;
|
||||
int packagesCount;
|
||||
final boolean skipPackageWhitelist = installablePackages == null;
|
||||
final boolean skipPackageWhitelist = userTypeInstallablePackages == null;
|
||||
synchronized (mLock) {
|
||||
Collection<PackageSetting> packages = mPackages.values();
|
||||
packagesCount = packages.size();
|
||||
@@ -4152,13 +4166,20 @@ public final class Settings {
|
||||
if (ps.pkg == null) {
|
||||
continue;
|
||||
}
|
||||
final boolean shouldInstall = ps.isSystem() &&
|
||||
(skipPackageWhitelist || installablePackages.contains(ps.name)) &&
|
||||
final boolean shouldMaybeInstall = ps.isSystem() &&
|
||||
!ArrayUtils.contains(disallowedPackages, ps.name) &&
|
||||
!ps.getPkgState().isHiddenUntilInstalled();
|
||||
final boolean shouldReallyInstall = shouldMaybeInstall &&
|
||||
(skipPackageWhitelist || userTypeInstallablePackages.contains(ps.name));
|
||||
// Only system apps are initially installed.
|
||||
ps.setInstalled(shouldInstall, userHandle);
|
||||
if (!shouldInstall) {
|
||||
ps.setInstalled(shouldReallyInstall, userHandle);
|
||||
// If userTypeInstallablePackages is the *only* reason why we're not installing,
|
||||
// then uninstallReason is USER_TYPE. If there's a different reason, or if we
|
||||
// actually are installing, put UNKNOWN.
|
||||
final int uninstallReason = (shouldMaybeInstall && !shouldReallyInstall) ?
|
||||
UNINSTALL_REASON_USER_TYPE : UNINSTALL_REASON_UNKNOWN;
|
||||
ps.setUninstallReason(uninstallReason, userHandle);
|
||||
if (!shouldReallyInstall) {
|
||||
writeKernelMappingLPr(ps);
|
||||
}
|
||||
// Need to create a data directory for all apps under this user. Accumulate all
|
||||
|
||||
@@ -3438,10 +3438,10 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
|
||||
t.traceEnd();
|
||||
|
||||
final Set<String> installablePackages =
|
||||
final Set<String> userTypeInstallablePackages =
|
||||
mSystemPackageInstaller.getInstallablePackagesForUserType(userType);
|
||||
t.traceBegin("PM.createNewUser");
|
||||
mPm.createNewUser(userId, installablePackages, disallowedPackages);
|
||||
mPm.createNewUser(userId, userTypeInstallablePackages, disallowedPackages);
|
||||
t.traceEnd();
|
||||
|
||||
userInfo.partial = false;
|
||||
@@ -3562,8 +3562,10 @@ public class UserManagerService extends IUserManager.Stub {
|
||||
}
|
||||
|
||||
/** Install/uninstall system packages for all users based on their user-type, as applicable. */
|
||||
boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
|
||||
return mSystemPackageInstaller.installWhitelistedSystemPackages(isFirstBoot, isUpgrade);
|
||||
boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade,
|
||||
@Nullable ArraySet<String> existingPackages) {
|
||||
return mSystemPackageInstaller.installWhitelistedSystemPackages(
|
||||
isFirstBoot, isUpgrade, existingPackages);
|
||||
}
|
||||
|
||||
private long getCreationTime() {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.res.Resources;
|
||||
@@ -74,6 +75,14 @@ import java.util.Set;
|
||||
* <li>Otherwise, the package is implicitly treated as blacklisted for all users</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>Packages are only installed/uninstalled by this mechanism when a new user is created or during
|
||||
* an update. In the case of updates:<ul>
|
||||
* <li>new packages are (un)installed per the whitelist/blacklist</li>
|
||||
* <li>pre-existing installed blacklisted packages are never uninstalled</li>
|
||||
* <li>pre-existing not-installed whitelisted packages are only installed if the reason why they
|
||||
* had been previously uninstalled was due to UserSystemPackageInstaller</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>NOTE:</b> the {@code SystemConfig} state is only updated on first boot or after a system
|
||||
* update. So, to verify changes during development, you can emulate the latter by calling:
|
||||
* <pre><code>
|
||||
@@ -171,8 +180,12 @@ class UserSystemPackageInstaller {
|
||||
*
|
||||
* This is responsible for enforcing the whitelist for pre-existing users (i.e. USER_SYSTEM);
|
||||
* enforcement for new users is done when they are created in UserManagerService.createUser().
|
||||
*
|
||||
* @param preExistingPackages list of packages on the device prior to the upgrade. Cannot be
|
||||
* null if isUpgrade is true.
|
||||
*/
|
||||
boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade) {
|
||||
boolean installWhitelistedSystemPackages(boolean isFirstBoot, boolean isUpgrade,
|
||||
@Nullable ArraySet<String> preExistingPackages) {
|
||||
final int mode = getWhitelistMode();
|
||||
checkWhitelistedSystemPackages(mode);
|
||||
final boolean isConsideredUpgrade = isUpgrade && !isIgnoreOtaMode(mode);
|
||||
@@ -198,19 +211,50 @@ class UserSystemPackageInstaller {
|
||||
final boolean install =
|
||||
(userWhitelist == null || userWhitelist.contains(pkg.getPackageName()))
|
||||
&& !pkgSetting.getPkgState().isHiddenUntilInstalled();
|
||||
if (isConsideredUpgrade && !isFirstBoot && !install) {
|
||||
return; // To be careful, we don’t uninstall apps during OTAs
|
||||
}
|
||||
final boolean changed = pmInt.setInstalled(pkg, userId, install);
|
||||
if (changed) {
|
||||
Slog.i(TAG, (install ? "Installed " : "Uninstalled ")
|
||||
+ pkg.getPackageName() + " for user " + userId);
|
||||
if (pkgSetting.getInstalled(userId) == install
|
||||
|| !shouldChangeInstallationState(pkgSetting, install, userId, isFirstBoot,
|
||||
isConsideredUpgrade, preExistingPackages)) {
|
||||
return;
|
||||
}
|
||||
pkgSetting.setInstalled(install, userId);
|
||||
pkgSetting.setUninstallReason(
|
||||
install ? PackageManager.UNINSTALL_REASON_UNKNOWN :
|
||||
PackageManager.UNINSTALL_REASON_USER_TYPE,
|
||||
userId);
|
||||
Slog.i(TAG, (install ? "Installed " : "Uninstalled ")
|
||||
+ pkg.getPackageName() + " for user " + userId);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether to proceed with install/uninstall for the given package.
|
||||
* In particular, do not install a package unless it was only uninstalled due to the user type;
|
||||
* and do not uninstall a package if it previously was installed (prior to the OTA).
|
||||
*
|
||||
* Should be called only within PackageManagerInternal.forEachPackageSetting() since it
|
||||
* requires the LP lock.
|
||||
*
|
||||
* @param preOtaPkgs list of packages on the device prior to the upgrade.
|
||||
* Cannot be null if isUpgrade is true.
|
||||
*/
|
||||
private static boolean shouldChangeInstallationState(PackageSetting pkgSetting,
|
||||
boolean install,
|
||||
@UserIdInt int userId,
|
||||
boolean isFirstBoot,
|
||||
boolean isUpgrade,
|
||||
@Nullable ArraySet<String> preOtaPkgs) {
|
||||
if (install) {
|
||||
// Only proceed with install if we are the only reason why it had been uninstalled.
|
||||
return pkgSetting.getUninstallReason(userId)
|
||||
== PackageManager.UNINSTALL_REASON_USER_TYPE;
|
||||
} else {
|
||||
// Only proceed with uninstall if the package is new to the device.
|
||||
return isFirstBoot || (isUpgrade && !preOtaPkgs.contains(pkgSetting.name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the system packages and the mWhitelistedPackagesForUserTypes whitelist are
|
||||
* in 1-to-1 correspondence.
|
||||
|
||||
@@ -84,6 +84,10 @@ public class PackageUserStateTest {
|
||||
oldUserState = new PackageUserState();
|
||||
oldUserState.suspended = true;
|
||||
assertThat(testUserState.equals(oldUserState), is(false));
|
||||
|
||||
oldUserState = new PackageUserState();
|
||||
oldUserState.uninstallReason = PackageManager.UNINSTALL_REASON_USER_TYPE;
|
||||
assertThat(testUserState.equals(oldUserState), is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user