Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 92b64bb1 authored by Todd Kennedy's avatar Todd Kennedy Committed by Android (Google) Code Review
Browse files

Merge changes from topic "b_78809704" into pi-dev

* changes:
  OMS: teach the OMS about static RROs
  OMS: rebase settings when overlays update
parents 92a33973 a525e223
Loading
Loading
Loading
Loading
+41 −4
Original line number Diff line number Diff line
@@ -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:
+69 −29
Original line number Diff line number Diff line
@@ -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;
    }
+2 −1
Original line number Diff line number Diff line
@@ -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;
        }
+1 −0
Original line number Diff line number Diff line
@@ -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;