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

Commit e0b984e8 authored by Winson's avatar Winson
Browse files

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
parent d605e2d6
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -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;

    /**
+0 −2
Original line number Diff line number Diff line
@@ -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);
                        }
                    }
                }
+52 −32
Original line number Diff line number Diff line
@@ -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;
        }