Merge changes from topic "b_78809704" into pi-dev
* changes: OMS: teach the OMS about static RROs OMS: rebase settings when overlays update
This commit is contained in:
@@ -18,7 +18,6 @@ package android.content.om;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@@ -39,6 +38,7 @@ public final class OverlayInfo implements Parcelable {
|
||||
STATE_NO_IDMAP,
|
||||
STATE_DISABLED,
|
||||
STATE_ENABLED,
|
||||
STATE_ENABLED_STATIC,
|
||||
STATE_TARGET_UPGRADING,
|
||||
STATE_OVERLAY_UPGRADING,
|
||||
})
|
||||
@@ -91,7 +91,16 @@ public final class OverlayInfo implements Parcelable {
|
||||
public static final int STATE_OVERLAY_UPGRADING = 5;
|
||||
|
||||
/**
|
||||
* Category for theme overlays.
|
||||
* The overlay package is currently enabled because it is marked as
|
||||
* 'static'. It cannot be disabled but will change state if for instance
|
||||
* its target is uninstalled.
|
||||
*/
|
||||
public static final int STATE_ENABLED_STATIC = 6;
|
||||
|
||||
/**
|
||||
* Overlay category: theme.
|
||||
* <p>
|
||||
* Change how Android (including the status bar, dialogs, ...) looks.
|
||||
*/
|
||||
public static final String CATEGORY_THEME = "android.theme";
|
||||
|
||||
@@ -125,6 +134,23 @@ public final class OverlayInfo implements Parcelable {
|
||||
*/
|
||||
public final int userId;
|
||||
|
||||
/**
|
||||
* Priority as read from the manifest. Used if isStatic is true. Not
|
||||
* intended to be exposed to 3rd party.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final int priority;
|
||||
|
||||
/**
|
||||
* isStatic as read from the manifest. If true, the overlay is
|
||||
* unconditionally loaded and cannot be unloaded. Not intended to be
|
||||
* exposed to 3rd party.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final boolean isStatic;
|
||||
|
||||
/**
|
||||
* Create a new OverlayInfo based on source with an updated state.
|
||||
*
|
||||
@@ -133,17 +159,20 @@ public final class OverlayInfo implements Parcelable {
|
||||
*/
|
||||
public OverlayInfo(@NonNull OverlayInfo source, @State int state) {
|
||||
this(source.packageName, source.targetPackageName, source.category, source.baseCodePath,
|
||||
state, source.userId);
|
||||
state, source.userId, source.priority, source.isStatic);
|
||||
}
|
||||
|
||||
public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
|
||||
@Nullable String category, @NonNull String baseCodePath, int state, int userId) {
|
||||
@NonNull String category, @NonNull String baseCodePath, int state, int userId,
|
||||
int priority, boolean isStatic) {
|
||||
this.packageName = packageName;
|
||||
this.targetPackageName = targetPackageName;
|
||||
this.category = category;
|
||||
this.baseCodePath = baseCodePath;
|
||||
this.state = state;
|
||||
this.userId = userId;
|
||||
this.priority = priority;
|
||||
this.isStatic = isStatic;
|
||||
ensureValidState();
|
||||
}
|
||||
|
||||
@@ -154,6 +183,8 @@ public final class OverlayInfo implements Parcelable {
|
||||
baseCodePath = source.readString();
|
||||
state = source.readInt();
|
||||
userId = source.readInt();
|
||||
priority = source.readInt();
|
||||
isStatic = source.readBoolean();
|
||||
ensureValidState();
|
||||
}
|
||||
|
||||
@@ -173,6 +204,7 @@ public final class OverlayInfo implements Parcelable {
|
||||
case STATE_NO_IDMAP:
|
||||
case STATE_DISABLED:
|
||||
case STATE_ENABLED:
|
||||
case STATE_ENABLED_STATIC:
|
||||
case STATE_TARGET_UPGRADING:
|
||||
case STATE_OVERLAY_UPGRADING:
|
||||
break;
|
||||
@@ -194,6 +226,8 @@ public final class OverlayInfo implements Parcelable {
|
||||
dest.writeString(baseCodePath);
|
||||
dest.writeInt(state);
|
||||
dest.writeInt(userId);
|
||||
dest.writeInt(priority);
|
||||
dest.writeBoolean(isStatic);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<OverlayInfo> CREATOR =
|
||||
@@ -220,6 +254,7 @@ public final class OverlayInfo implements Parcelable {
|
||||
public boolean isEnabled() {
|
||||
switch (state) {
|
||||
case STATE_ENABLED:
|
||||
case STATE_ENABLED_STATIC:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -244,6 +279,8 @@ public final class OverlayInfo implements Parcelable {
|
||||
return "STATE_DISABLED";
|
||||
case STATE_ENABLED:
|
||||
return "STATE_ENABLED";
|
||||
case STATE_ENABLED_STATIC:
|
||||
return "STATE_ENABLED_STATIC";
|
||||
case STATE_TARGET_UPGRADING:
|
||||
return "STATE_TARGET_UPGRADING";
|
||||
case STATE_OVERLAY_UPGRADING:
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.om;
|
||||
|
||||
import static android.content.om.OverlayInfo.STATE_DISABLED;
|
||||
import static android.content.om.OverlayInfo.STATE_ENABLED;
|
||||
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;
|
||||
@@ -63,6 +64,38 @@ final class OverlayManagerServiceImpl {
|
||||
private final String[] mDefaultOverlays;
|
||||
private final OverlayChangeListener mListener;
|
||||
|
||||
/**
|
||||
* Helper method to merge the overlay manager's (as read from overlays.xml)
|
||||
* and package manager's (as parsed from AndroidManifest.xml files) views
|
||||
* on overlays.
|
||||
*
|
||||
* Both managers are usually in agreement, but especially after an OTA things
|
||||
* may differ. The package manager is always providing the truth; the overlay
|
||||
* manager has to adapt. Depending on what has changed about an overlay, we
|
||||
* should either scrap the overlay manager's previous settings or merge the old
|
||||
* settings with the new.
|
||||
*/
|
||||
private static boolean mustReinitializeOverlay(@NonNull final PackageInfo theTruth,
|
||||
@Nullable final OverlayInfo oldSettings) {
|
||||
if (oldSettings == null) {
|
||||
return true;
|
||||
}
|
||||
if (!Objects.equals(theTruth.overlayTarget, oldSettings.targetPackageName)) {
|
||||
return true;
|
||||
}
|
||||
if (theTruth.isStaticOverlayPackage() != oldSettings.isStatic) {
|
||||
return true;
|
||||
}
|
||||
// a change in priority is only relevant for static RROs: specifically,
|
||||
// a regular RRO should not have its state reset only because a change
|
||||
// in priority
|
||||
if (theTruth.isStaticOverlayPackage() &&
|
||||
theTruth.overlayPriority != oldSettings.priority) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
|
||||
@NonNull final IdmapManager idmapManager,
|
||||
@NonNull final OverlayManagerSettings settings,
|
||||
@@ -99,42 +132,29 @@ final class OverlayManagerServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
// Reset overlays if something critical like the target package name
|
||||
// has changed
|
||||
List<PackageInfo> overlayPackages = mPackageManager.getOverlayPackages(newUserId);
|
||||
final int overlayPackagesSize = overlayPackages.size();
|
||||
for (int i = 0; i < overlayPackagesSize; i++) {
|
||||
final PackageInfo overlayPackage = overlayPackages.get(i);
|
||||
final OverlayInfo oi = storedOverlayInfos.get(overlayPackage.packageName);
|
||||
if (oi == null || !oi.targetPackageName.equals(overlayPackage.overlayTarget)) {
|
||||
// Reset the overlay if it didn't exist or had the wrong target package.
|
||||
|
||||
if (mustReinitializeOverlay(overlayPackage, oi)) {
|
||||
// if targetPackageName has changed the package that *used* to
|
||||
// be the target must also update its assets
|
||||
if (oi != null) {
|
||||
packagesToUpdateAssets.add(oi.targetPackageName);
|
||||
}
|
||||
|
||||
mSettings.init(overlayPackage.packageName, newUserId,
|
||||
overlayPackage.overlayTarget,
|
||||
overlayPackage.applicationInfo.getBaseCodePath(),
|
||||
overlayPackage.isStaticOverlayPackage(),
|
||||
overlayPackage.overlayPriority,
|
||||
overlayPackage.overlayCategory);
|
||||
|
||||
if (oi != null) {
|
||||
// The targetPackageName we have stored doesn't match the overlay's target.
|
||||
// Queue the old target for an update as well.
|
||||
packagesToUpdateAssets.add(oi.targetPackageName);
|
||||
}
|
||||
} else {
|
||||
// Update all other components of an overlay that don't require a hard reset.
|
||||
if (!Objects.equals(oi.category, overlayPackage.overlayCategory)) {
|
||||
// When changing categories, it is ok just to update our internal state.
|
||||
mSettings.setCategory(overlayPackage.packageName, newUserId,
|
||||
overlayPackage.overlayCategory);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
updateState(overlayPackage.overlayTarget, overlayPackage.packageName, newUserId, 0);
|
||||
} catch (OverlayManagerSettings.BadKeyException e) {
|
||||
Slog.e(TAG, "failed to update settings", e);
|
||||
mSettings.remove(overlayPackage.packageName, newUserId);
|
||||
}
|
||||
|
||||
packagesToUpdateAssets.add(overlayPackage.overlayTarget);
|
||||
storedOverlayInfos.remove(overlayPackage.packageName);
|
||||
}
|
||||
|
||||
@@ -148,6 +168,22 @@ final class OverlayManagerServiceImpl {
|
||||
packagesToUpdateAssets.add(oi.targetPackageName);
|
||||
}
|
||||
|
||||
// make sure every overlay's state is up-to-date; this needs to happen
|
||||
// after old overlays have been removed, or we risk removing a
|
||||
// legitimate idmap file if a new overlay package has the same apk path
|
||||
// as the removed overlay package used to have
|
||||
for (int i = 0; i < overlayPackagesSize; i++) {
|
||||
final PackageInfo overlayPackage = overlayPackages.get(i);
|
||||
try {
|
||||
updateState(overlayPackage.overlayTarget, overlayPackage.packageName,
|
||||
newUserId, 0);
|
||||
} catch (OverlayManagerSettings.BadKeyException e) {
|
||||
Slog.e(TAG, "failed to update settings", e);
|
||||
mSettings.remove(overlayPackage.packageName, newUserId);
|
||||
}
|
||||
packagesToUpdateAssets.add(overlayPackage.overlayTarget);
|
||||
}
|
||||
|
||||
// remove target packages that are not installed
|
||||
final Iterator<String> iter = packagesToUpdateAssets.iterator();
|
||||
while (iter.hasNext()) {
|
||||
@@ -355,15 +391,13 @@ final class OverlayManagerServiceImpl {
|
||||
|
||||
try {
|
||||
final OverlayInfo oldOi = mSettings.getOverlayInfo(packageName, userId);
|
||||
if (!oldOi.targetPackageName.equals(pkg.overlayTarget)) {
|
||||
if (mustReinitializeOverlay(pkg, oldOi)) {
|
||||
if (oldOi != null && !oldOi.targetPackageName.equals(pkg.overlayTarget)) {
|
||||
mListener.onOverlaysChanged(pkg.overlayTarget, userId);
|
||||
}
|
||||
mSettings.init(packageName, userId, pkg.overlayTarget,
|
||||
pkg.applicationInfo.getBaseCodePath(), pkg.isStaticOverlayPackage(),
|
||||
pkg.overlayPriority, pkg.overlayCategory);
|
||||
} else {
|
||||
if (!Objects.equals(oldOi.category, pkg.overlayCategory)) {
|
||||
// Update the category in-place.
|
||||
mSettings.setCategory(packageName, userId, pkg.overlayCategory);
|
||||
}
|
||||
}
|
||||
|
||||
if (updateState(pkg.overlayTarget, packageName, userId, 0)) {
|
||||
@@ -608,6 +642,8 @@ final class OverlayManagerServiceImpl {
|
||||
if (overlayPackage != null) {
|
||||
modified |= mSettings.setBaseCodePath(overlayPackageName, userId,
|
||||
overlayPackage.applicationInfo.getBaseCodePath());
|
||||
modified |= mSettings.setCategory(overlayPackageName, userId,
|
||||
overlayPackage.overlayCategory);
|
||||
}
|
||||
|
||||
final @OverlayInfo.State int currentState = mSettings.getState(overlayPackageName, userId);
|
||||
@@ -650,6 +686,10 @@ final class OverlayManagerServiceImpl {
|
||||
return STATE_NO_IDMAP;
|
||||
}
|
||||
|
||||
if (overlayPackage.isStaticOverlayPackage()) {
|
||||
return STATE_ENABLED_STATIC;
|
||||
}
|
||||
|
||||
final boolean enabled = mSettings.getEnabled(overlayPackage.packageName, userId);
|
||||
return enabled ? STATE_ENABLED : STATE_DISABLED;
|
||||
}
|
||||
|
||||
@@ -309,6 +309,7 @@ final class OverlayManagerSettings {
|
||||
pw.print("mState.............: "); pw.println(OverlayInfo.stateToString(item.getState()));
|
||||
pw.print("mIsEnabled.........: "); pw.println(item.isEnabled());
|
||||
pw.print("mIsStatic..........: "); pw.println(item.isStatic());
|
||||
pw.print("mPriority..........: "); pw.println(item.mPriority);
|
||||
pw.print("mCategory..........: "); pw.println(item.mCategory);
|
||||
|
||||
pw.decreaseIndent();
|
||||
@@ -528,7 +529,7 @@ final class OverlayManagerSettings {
|
||||
private OverlayInfo getOverlayInfo() {
|
||||
if (mCache == null) {
|
||||
mCache = new OverlayInfo(mPackageName, mTargetPackageName, mCategory, mBaseCodePath,
|
||||
mState, mUserId);
|
||||
mState, mUserId, mPriority, mIsStatic);
|
||||
}
|
||||
return mCache;
|
||||
}
|
||||
|
||||
@@ -126,6 +126,7 @@ final class OverlayManagerShellCommand extends ShellCommand {
|
||||
final OverlayInfo oi = overlaysForTarget.get(i);
|
||||
String status;
|
||||
switch (oi.state) {
|
||||
case OverlayInfo.STATE_ENABLED_STATIC:
|
||||
case OverlayInfo.STATE_ENABLED:
|
||||
status = "[x]";
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user