Diff overlays between PackageManagerService and OverlayManagerService

When uninstalling an update to a system app, PMS re-creates the
PackageSetting object, and OMS doesn't get notified of the change.

This makes OMS diff the known valid overlays with the resourceDirs
in the target's ApplicationInfo and forces a reload when they
disagree.

Bug: 124363683

Test: manual ran Wellbeing reproduction steps in bug

Change-Id: Ib080d8593d12596ae8f8a729cc9740462c4b9b69
This commit is contained in:
Winson
2019-02-13 16:20:33 -08:00
parent d605e2d665
commit e0b984e805
3 changed files with 60 additions and 35 deletions

View File

@@ -44,7 +44,7 @@ public final class OverlayInfo implements Parcelable {
STATE_DISABLED,
STATE_ENABLED,
STATE_ENABLED_STATIC,
STATE_TARGET_UPGRADING,
// @Deprecated STATE_TARGET_UPGRADING,
STATE_OVERLAY_UPGRADING,
})
/** @hide */
@@ -96,7 +96,14 @@ public final class OverlayInfo implements Parcelable {
* The target package is currently being upgraded; the state will change
* once the package installation has finished.
* @hide
*
* @deprecated No longer used. Caused invalid transitions from enabled -> upgrading -> enabled,
* where an update is propagated when nothing has changed. Can occur during --dont-kill
* installs when code and resources are hot swapped and the Activity should not be relaunched.
* In all other cases, the process and therefore Activity is killed, so the state loop is
* irrelevant.
*/
@Deprecated
public static final int STATE_TARGET_UPGRADING = 4;
/**

View File

@@ -422,8 +422,6 @@ public final class OverlayManagerService extends SystemService {
final OverlayInfo oi = mImpl.getOverlayInfo(packageName, userId);
if (oi != null) {
mImpl.onOverlayPackageUpgrading(packageName, userId);
} else {
mImpl.onTargetPackageUpgrading(packageName, userId);
}
}
}

View File

@@ -22,7 +22,6 @@ import static android.content.om.OverlayInfo.STATE_ENABLED_STATIC;
import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
import static android.content.om.OverlayInfo.STATE_NO_IDMAP;
import static android.content.om.OverlayInfo.STATE_OVERLAY_UPGRADING;
import static android.content.om.OverlayInfo.STATE_TARGET_UPGRADING;
import static com.android.server.om.OverlayManagerService.DEBUG;
import static com.android.server.om.OverlayManagerService.TAG;
@@ -30,12 +29,15 @@ import static com.android.server.om.OverlayManagerService.TAG;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
@@ -54,8 +56,14 @@ import java.util.Set;
* @see OverlayManagerService
*/
final class OverlayManagerServiceImpl {
// Flags to use in conjunction with updateState.
/**
* @deprecated Not used. See {@link android.content.om.OverlayInfo#STATE_TARGET_UPGRADING}.
*/
@Deprecated
private static final int FLAG_TARGET_IS_UPGRADING = 1 << 0;
// Flags to use in conjunction with updateState.
private static final int FLAG_OVERLAY_IS_UPGRADING = 1 << 1;
private final PackageManagerHelper mPackageManager;
@@ -247,9 +255,7 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageAdded packageName=" + packageName + " userId=" + userId);
}
if (updateAllOverlaysForTarget(packageName, userId, 0)) {
mListener.onOverlaysChanged(packageName, userId);
}
updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
@@ -257,16 +263,7 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageChanged packageName=" + packageName + " userId=" + userId);
}
updateAllOverlaysForTarget(packageName, userId, 0);
}
void onTargetPackageUpgrading(@NonNull final String packageName, final int userId) {
if (DEBUG) {
Slog.d(TAG, "onTargetPackageUpgrading packageName=" + packageName + " userId="
+ userId);
}
updateAllOverlaysForTarget(packageName, userId, FLAG_TARGET_IS_UPGRADING);
updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
void onTargetPackageUpgraded(@NonNull final String packageName, final int userId) {
@@ -274,7 +271,7 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
}
updateAllOverlaysForTarget(packageName, userId, 0);
updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
@@ -282,22 +279,27 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
}
if (updateAllOverlaysForTarget(packageName, userId, 0)) {
mListener.onOverlaysChanged(packageName, userId);
}
updateAndRefreshOverlaysForTarget(packageName, userId, 0);
}
/**
* Update the state of any overlays for this target.
*
* Returns true if the system should refresh the app's overlay paths (i.e.
* if the settings were modified for this target, or there is at least one
* enabled framework overlay).
*/
private boolean updateAllOverlaysForTarget(@NonNull final String targetPackageName,
private void updateAndRefreshOverlaysForTarget(@NonNull final String targetPackageName,
final int userId, final int flags) {
final List<OverlayInfo> ois = new ArrayList<>();
// Framework overlays added first because order matters when resolving a resource
if (!"android".equals(targetPackageName)) {
ois.addAll(mSettings.getOverlaysForTarget("android", userId));
}
// Then add the targeted, non-framework overlays which have higher priority
ois.addAll(mSettings.getOverlaysForTarget(targetPackageName, userId));
final List<String> enabledBaseCodePaths = new ArrayList<>(ois.size());
boolean modified = false;
final List<OverlayInfo> ois = mSettings.getOverlaysForTarget(targetPackageName, userId);
final int n = ois.size();
for (int i = 0; i < n; i++) {
final OverlayInfo oi = ois.get(i);
@@ -313,13 +315,35 @@ final class OverlayManagerServiceImpl {
Slog.e(TAG, "failed to update settings", e);
modified |= mSettings.remove(oi.packageName, userId);
}
if (oi.isEnabled() && overlayPackage.applicationInfo != null) {
enabledBaseCodePaths.add(overlayPackage.applicationInfo.getBaseCodePath());
}
}
}
// check for enabled framework overlays
modified = modified || !getEnabledOverlayPackageNames("android", userId).isEmpty();
if (!modified) {
PackageInfo packageInfo = mPackageManager.getPackageInfo(targetPackageName, userId);
ApplicationInfo appInfo = packageInfo == null ? null : packageInfo.applicationInfo;
String[] resourceDirs = appInfo == null ? null : appInfo.resourceDirs;
return modified;
// If the lists aren't the same length, the enabled overlays have changed
if (ArrayUtils.size(resourceDirs) != enabledBaseCodePaths.size()) {
modified = true;
} else if (resourceDirs != null) {
// If any element isn't equal, an overlay or the order of overlays has changed
for (int index = 0; index < resourceDirs.length; index++) {
if (!resourceDirs[index].equals(enabledBaseCodePaths.get(index))) {
modified = true;
break;
}
}
}
}
if (modified) {
mListener.onOverlaysChanged(targetPackageName, userId);
}
}
void onOverlayPackageAdded(@NonNull final String packageName, final int userId) {
@@ -670,10 +694,6 @@ final class OverlayManagerServiceImpl {
@Nullable final PackageInfo overlayPackage, final int userId, final int flags)
throws OverlayManagerSettings.BadKeyException {
if ((flags & FLAG_TARGET_IS_UPGRADING) != 0) {
return STATE_TARGET_UPGRADING;
}
if ((flags & FLAG_OVERLAY_IS_UPGRADING) != 0) {
return STATE_OVERLAY_UPGRADING;
}