Merge "Support system app update leaving shared UID then getting uninstalled"
This commit is contained in:
@@ -458,10 +458,8 @@ final class DeletePackageHelper {
|
||||
mAppDataHelper.destroyAppProfilesLIF(pkg);
|
||||
|
||||
final SharedUserSetting sus = ps.getSharedUser();
|
||||
List<AndroidPackage> sharedUserPkgs = sus != null ? sus.getPackages() : null;
|
||||
if (sharedUserPkgs == null) {
|
||||
sharedUserPkgs = Collections.emptyList();
|
||||
}
|
||||
final List<AndroidPackage> sharedUserPkgs =
|
||||
sus != null ? sus.getPackages() : Collections.emptyList();
|
||||
final int[] userIds = (userId == UserHandle.USER_ALL) ? mUserManagerInternal.getUserIds()
|
||||
: new int[] {userId};
|
||||
for (int nextUserId : userIds) {
|
||||
|
||||
@@ -220,9 +220,8 @@ final class RemovePackageHelper {
|
||||
outInfo.mInstallerPackageName = deletedPs.getInstallSource().installerPackageName;
|
||||
outInfo.mIsStaticSharedLib = deletedPkg != null
|
||||
&& deletedPkg.getStaticSharedLibName() != null;
|
||||
outInfo.populateUsers(
|
||||
deletedPs == null ? null : deletedPs.queryInstalledUsers(
|
||||
mUserManagerInternal.getUserIds(), true), deletedPs);
|
||||
outInfo.populateUsers(deletedPs.queryInstalledUsers(
|
||||
mUserManagerInternal.getUserIds(), true), deletedPs);
|
||||
}
|
||||
|
||||
removePackageLI(deletedPs.getPackageName(), (flags & PackageManager.DELETE_CHATTY) != 0);
|
||||
@@ -249,58 +248,53 @@ final class RemovePackageHelper {
|
||||
|
||||
// writer
|
||||
boolean installedStateChanged = false;
|
||||
if (deletedPs != null) {
|
||||
if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
|
||||
final SparseBooleanArray changedUsers = new SparseBooleanArray();
|
||||
synchronized (mPm.mLock) {
|
||||
mPm.mDomainVerificationManager.clearPackage(deletedPs.getPackageName());
|
||||
mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
|
||||
mPm.mAppsFilter.removePackage(mPm.getPackageSetting(packageName),
|
||||
false /* isReplace */);
|
||||
removedAppId = mPm.mSettings.removePackageLPw(packageName);
|
||||
if (outInfo != null) {
|
||||
outInfo.mRemovedAppId = removedAppId;
|
||||
}
|
||||
if (!mPm.mSettings.isDisabledSystemPackageLPr(packageName)) {
|
||||
// If we don't have a disabled system package to reinstall, the package is
|
||||
// really gone and its permission state should be removed.
|
||||
final SharedUserSetting sus = deletedPs.getSharedUser();
|
||||
List<AndroidPackage> sharedUserPkgs = sus != null ? sus.getPackages()
|
||||
: null;
|
||||
if (sharedUserPkgs == null) {
|
||||
sharedUserPkgs = Collections.emptyList();
|
||||
}
|
||||
mPermissionManager.onPackageUninstalled(packageName, deletedPs.getAppId(),
|
||||
deletedPs.getPkg(), sharedUserPkgs, UserHandle.USER_ALL);
|
||||
}
|
||||
mPm.clearPackagePreferredActivitiesLPw(
|
||||
deletedPs.getPackageName(), changedUsers, UserHandle.USER_ALL);
|
||||
if ((flags & PackageManager.DELETE_KEEP_DATA) == 0) {
|
||||
final SparseBooleanArray changedUsers = new SparseBooleanArray();
|
||||
synchronized (mPm.mLock) {
|
||||
mPm.mDomainVerificationManager.clearPackage(deletedPs.getPackageName());
|
||||
mPm.mSettings.getKeySetManagerService().removeAppKeySetDataLPw(packageName);
|
||||
mPm.mAppsFilter.removePackage(mPm.getPackageSetting(packageName),
|
||||
false /* isReplace */);
|
||||
removedAppId = mPm.mSettings.removePackageLPw(packageName);
|
||||
if (outInfo != null) {
|
||||
outInfo.mRemovedAppId = removedAppId;
|
||||
}
|
||||
if (!mPm.mSettings.isDisabledSystemPackageLPr(packageName)) {
|
||||
// If we don't have a disabled system package to reinstall, the package is
|
||||
// really gone and its permission state should be removed.
|
||||
final SharedUserSetting sus = deletedPs.getSharedUser();
|
||||
List<AndroidPackage> sharedUserPkgs =
|
||||
sus != null ? sus.getPackages() : Collections.emptyList();
|
||||
mPermissionManager.onPackageUninstalled(packageName, deletedPs.getAppId(),
|
||||
deletedPs.getPkg(), sharedUserPkgs, UserHandle.USER_ALL);
|
||||
}
|
||||
mPm.clearPackagePreferredActivitiesLPw(
|
||||
deletedPs.getPackageName(), changedUsers, UserHandle.USER_ALL);
|
||||
|
||||
mPm.mSettings.removeRenamedPackageLPw(deletedPs.getRealName());
|
||||
}
|
||||
if (changedUsers.size() > 0) {
|
||||
mPm.updateDefaultHomeNotLocked(changedUsers);
|
||||
mPm.postPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
|
||||
}
|
||||
mPm.mSettings.removeRenamedPackageLPw(deletedPs.getRealName());
|
||||
}
|
||||
// make sure to preserve per-user disabled state if this removal was just
|
||||
// a downgrade of a system app to the factory package
|
||||
if (outInfo != null && outInfo.mOrigUsers != null) {
|
||||
if (changedUsers.size() > 0) {
|
||||
mPm.updateDefaultHomeNotLocked(changedUsers);
|
||||
mPm.postPreferredActivityChangedBroadcast(UserHandle.USER_ALL);
|
||||
}
|
||||
}
|
||||
// make sure to preserve per-user disabled state if this removal was just
|
||||
// a downgrade of a system app to the factory package
|
||||
if (outInfo != null && outInfo.mOrigUsers != null) {
|
||||
if (DEBUG_REMOVE) {
|
||||
Slog.d(TAG, "Propagating install state across downgrade");
|
||||
}
|
||||
for (int userId : allUserHandles) {
|
||||
final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId);
|
||||
if (DEBUG_REMOVE) {
|
||||
Slog.d(TAG, "Propagating install state across downgrade");
|
||||
Slog.d(TAG, " user " + userId + " => " + installed);
|
||||
}
|
||||
for (int userId : allUserHandles) {
|
||||
final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId);
|
||||
if (DEBUG_REMOVE) {
|
||||
Slog.d(TAG, " user " + userId + " => " + installed);
|
||||
}
|
||||
if (installed != deletedPs.getInstalled(userId)) {
|
||||
installedStateChanged = true;
|
||||
}
|
||||
deletedPs.setInstalled(installed, userId);
|
||||
if (installed) {
|
||||
deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
|
||||
}
|
||||
if (installed != deletedPs.getInstalled(userId)) {
|
||||
installedStateChanged = true;
|
||||
}
|
||||
deletedPs.setInstalled(installed, userId);
|
||||
if (installed) {
|
||||
deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,7 +802,9 @@ public final class Settings implements Watchable, Snappable {
|
||||
disabled = p;
|
||||
}
|
||||
mDisabledSysPackages.put(name, disabled);
|
||||
|
||||
if (disabled.getSharedUser() != null) {
|
||||
disabled.getSharedUser().mDisabledPackages.add(disabled);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -814,6 +816,9 @@ public final class Settings implements Watchable, Snappable {
|
||||
Log.w(PackageManagerService.TAG, "Package " + name + " is not disabled");
|
||||
return null;
|
||||
}
|
||||
if (p.getSharedUser() != null) {
|
||||
p.getSharedUser().mDisabledPackages.remove(p);
|
||||
}
|
||||
p.getPkgState().setUpdatedSystemApp(false);
|
||||
PackageSetting ret = addPackageLPw(name, p.getRealName(), p.getPath(),
|
||||
p.getLegacyNativeLibraryPath(), p.getPrimaryCpuAbi(),
|
||||
@@ -833,7 +838,11 @@ public final class Settings implements Watchable, Snappable {
|
||||
}
|
||||
|
||||
void removeDisabledSystemPackageLPw(String name) {
|
||||
mDisabledSysPackages.remove(name);
|
||||
final PackageSetting p = mDisabledSysPackages.remove(name);
|
||||
if (p != null && p.getSharedUser() != null) {
|
||||
p.getSharedUser().mDisabledPackages.remove(p);
|
||||
checkAndPruneSharedUserLPw(p.getSharedUser(), false);
|
||||
}
|
||||
}
|
||||
|
||||
PackageSetting addPackageLPw(String name, String realName, File codePath,
|
||||
@@ -883,27 +892,24 @@ public final class Settings implements Watchable, Snappable {
|
||||
}
|
||||
|
||||
void pruneSharedUsersLPw() {
|
||||
ArrayList<String> removeStage = new ArrayList<String>();
|
||||
for (Map.Entry<String,SharedUserSetting> entry : mSharedUsers.entrySet()) {
|
||||
List<String> removeKeys = new ArrayList<>();
|
||||
List<SharedUserSetting> removeValues = new ArrayList<>();
|
||||
for (Map.Entry<String, SharedUserSetting> entry : mSharedUsers.entrySet()) {
|
||||
final SharedUserSetting sus = entry.getValue();
|
||||
if (sus == null) {
|
||||
removeStage.add(entry.getKey());
|
||||
removeKeys.add(entry.getKey());
|
||||
continue;
|
||||
}
|
||||
// remove packages that are no longer installed
|
||||
for (Iterator<PackageSetting> iter = sus.packages.iterator(); iter.hasNext();) {
|
||||
PackageSetting ps = iter.next();
|
||||
if (mPackages.get(ps.getPackageName()) == null) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
if (sus.packages.size() == 0) {
|
||||
removeStage.add(entry.getKey());
|
||||
sus.packages.removeIf(ps -> mPackages.get(ps.getPackageName()) == null);
|
||||
sus.mDisabledPackages.removeIf(
|
||||
ps -> mDisabledSysPackages.get(ps.getPackageName()) == null);
|
||||
if (sus.packages.isEmpty() && sus.mDisabledPackages.isEmpty()) {
|
||||
removeValues.add(sus);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < removeStage.size(); i++) {
|
||||
mSharedUsers.remove(removeStage.get(i));
|
||||
}
|
||||
removeKeys.forEach(mSharedUsers::remove);
|
||||
removeValues.forEach(sus -> checkAndPruneSharedUserLPw(sus, true));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1233,18 +1239,20 @@ public final class Settings implements Watchable, Snappable {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAndPruneSharedUserLPw(SharedUserSetting s, boolean skipCheck) {
|
||||
if (skipCheck || (s.packages.isEmpty() && s.mDisabledPackages.isEmpty())) {
|
||||
mSharedUsers.remove(s.name);
|
||||
removeAppIdLPw(s.userId);
|
||||
}
|
||||
}
|
||||
|
||||
int removePackageLPw(String name) {
|
||||
final PackageSetting p = mPackages.get(name);
|
||||
final PackageSetting p = mPackages.remove(name);
|
||||
if (p != null) {
|
||||
mPackages.remove(name);
|
||||
removeInstallerPackageStatus(name);
|
||||
if (p.getSharedUser() != null) {
|
||||
p.getSharedUser().removePackage(p);
|
||||
if (p.getSharedUser().packages.size() == 0) {
|
||||
mSharedUsers.remove(p.getSharedUser().name);
|
||||
removeAppIdLPw(p.getSharedUser().userId);
|
||||
return p.getSharedUser().userId;
|
||||
}
|
||||
checkAndPruneSharedUserLPw(p.getSharedUser(), false);
|
||||
} else {
|
||||
removeAppIdLPw(p.getAppId());
|
||||
return p.getAppId();
|
||||
@@ -3052,17 +3060,16 @@ public final class Settings implements Watchable, Snappable {
|
||||
* Make sure all the updated system packages have their shared users
|
||||
* associated with them.
|
||||
*/
|
||||
final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
|
||||
while (disabledIt.hasNext()) {
|
||||
final PackageSetting disabledPs = disabledIt.next();
|
||||
for (PackageSetting disabledPs : mDisabledSysPackages.values()) {
|
||||
final Object id = getSettingLPr(disabledPs.getAppId());
|
||||
if (id != null && id instanceof SharedUserSetting) {
|
||||
if (id instanceof SharedUserSetting) {
|
||||
disabledPs.setSharedUser((SharedUserSetting) id);
|
||||
disabledPs.getSharedUser().mDisabledPackages.add(disabledPs);
|
||||
}
|
||||
}
|
||||
|
||||
mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
|
||||
+ mSharedUsers.size() + " shared uids\n");
|
||||
mReadMessages.append("Read completed successfully: ").append(mPackages.size())
|
||||
.append(" packages, ").append(mSharedUsers.size()).append(" shared uids\n");
|
||||
|
||||
writeKernelMappingLPr();
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.parsing.component.ParsedProcess;
|
||||
import android.service.pm.PackageServiceDumpProto;
|
||||
@@ -31,6 +31,7 @@ import com.android.server.utils.SnapshotCache;
|
||||
import libcore.util.EmptyArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -52,6 +53,11 @@ public final class SharedUserSetting extends SettingBase {
|
||||
|
||||
final ArraySet<PackageSetting> packages;
|
||||
|
||||
// It is possible for a system app to leave shared user ID by an update.
|
||||
// We need to keep track of the shadowed PackageSettings so that it is possible to uninstall
|
||||
// the update and revert the system app back into the original shared user ID.
|
||||
final ArraySet<PackageSetting> mDisabledPackages;
|
||||
|
||||
final PackageSignatures signatures = new PackageSignatures();
|
||||
Boolean signaturesChanged;
|
||||
|
||||
@@ -77,6 +83,7 @@ public final class SharedUserSetting extends SettingBase {
|
||||
name = _name;
|
||||
seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
|
||||
packages = new ArraySet<>();
|
||||
mDisabledPackages = new ArraySet<>();
|
||||
processes = new ArrayMap<>();
|
||||
mSnapshot = makeCache();
|
||||
}
|
||||
@@ -87,13 +94,14 @@ public final class SharedUserSetting extends SettingBase {
|
||||
name = orig.name;
|
||||
uidFlags = orig.uidFlags;
|
||||
uidPrivateFlags = orig.uidPrivateFlags;
|
||||
packages = new ArraySet(orig.packages);
|
||||
packages = new ArraySet<>(orig.packages);
|
||||
mDisabledPackages = new ArraySet<>(orig.mDisabledPackages);
|
||||
// A SigningDetails seems to consist solely of final attributes, so
|
||||
// it is safe to copy the reference.
|
||||
signatures.mSigningDetails = orig.signatures.mSigningDetails;
|
||||
signaturesChanged = orig.signaturesChanged;
|
||||
processes = new ArrayMap(orig.processes);
|
||||
mSnapshot = new SnapshotCache.Sealed();
|
||||
processes = new ArrayMap<>(orig.processes);
|
||||
mSnapshot = new SnapshotCache.Sealed<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,9 +182,12 @@ public final class SharedUserSetting extends SettingBase {
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable List<AndroidPackage> getPackages() {
|
||||
/**
|
||||
* @return the list of packages that uses this shared UID
|
||||
*/
|
||||
public @NonNull List<AndroidPackage> getPackages() {
|
||||
if (packages == null || packages.size() == 0) {
|
||||
return null;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final ArrayList<AndroidPackage> pkgList = new ArrayList<>(packages.size());
|
||||
for (PackageSetting ps : packages) {
|
||||
|
||||
Reference in New Issue
Block a user