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

Commit 0bf76b62 authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

Apply overlay updates to widget provider info

When Runtime Resource Overlays (RROs) are applied to an application,
the ApplicationInfo of the app in package manager is updated to have
overlay paths. Widgets create the context used to inflate their
remote views using a snapshot of the ApplicationInfo of the widget
provider. This snapshot is taken when the widget RemoteView is
initially created and sent to system server.

This change updates the snapshot of the widget provider ApplicationInfo
with the new overlay paths and notifies apps hosting widgets to
re-inflate their remote views in order to have RROs apply to widgets
correctly.

Bug: 193866093
Test: Repeatedly change wallpaper & style color to a "basic" color
      and go back to launcher to observe overlay correct color is
      applied
Change-Id: I0b9b8c0d32d83a52e9ea5bc8ba1635cf99e4b921
parent b827a8ac
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.appwidget;
import android.annotation.Nullable;
import android.util.ArraySet;

import java.util.Set;

/**
 * App widget manager local system service interface.
 *
@@ -42,4 +44,16 @@ public abstract class AppWidgetManagerInternal {
     * @param userId The user that is being unlocked.
     */
    public abstract void unlockUser(int userId);

    /**
     * Updates all widgets, applying changes to Runtime Resource Overlay affecting the specified
     * target packages.
     *
     * @param packageNames The names of all target packages for which an overlay was modified
     * @param userId The user for which overlay modifications occurred.
     * @param updateFrameworkRes Whether or not an overlay affected the values of framework
     *                           resources.
     */
    public abstract void applyResourceOverlaysToWidgets(Set<String> packageNames, int userId,
            boolean updateFrameworkRes);
}
+19 −0
Original line number Diff line number Diff line
@@ -5824,6 +5824,25 @@ public class RemoteViews implements Parcelable, Filter {
        return false;
    }

    /** @hide */
    public void updateAppInfo(@NonNull ApplicationInfo info) {
        if (mApplication != null && mApplication.sourceDir.equals(info.sourceDir)) {
            // Overlay paths are generated against a particular version of an application.
            // The overlays paths of a newly upgraded application are incompatible with the
            // old version of the application.
            mApplication = info;
        }
        if (hasSizedRemoteViews()) {
            for (RemoteViews layout : mSizedRemoteViews) {
                layout.updateAppInfo(info);
            }
        }
        if (hasLandscapeAndPortraitLayouts()) {
            mLandscape.updateAppInfo(info);
            mPortrait.updateAppInfo(info);
        }
    }

    private Context getContextForResources(Context context) {
        if (mApplication != null) {
            if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
+60 −0
Original line number Diff line number Diff line
@@ -3285,6 +3285,57 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        }
    }

    private void applyResourceOverlaysToWidgetsLocked(Set<String> packageNames, int userId,
            boolean updateFrameworkRes) {
        for (int i = 0, N = mProviders.size(); i < N; i++) {
            Provider provider = mProviders.get(i);
            if (provider.getUserId() != userId) {
                continue;
            }

            final String packageName = provider.id.componentName.getPackageName();
            if (!updateFrameworkRes && !packageNames.contains(packageName)) {
                continue;
            }

            ApplicationInfo newAppInfo = null;
            try {
                newAppInfo = mPackageManager.getApplicationInfo(packageName,
                        PackageManager.GET_SHARED_LIBRARY_FILES, userId);
            } catch (RemoteException e) {
                Slog.w(TAG, "Failed to retrieve app info for " + packageName
                        + " userId=" + userId, e);
            }
            if (newAppInfo == null) {
                continue;
            }
            ApplicationInfo oldAppInfo = provider.info.providerInfo.applicationInfo;
            if (!newAppInfo.sourceDir.equals(oldAppInfo.sourceDir)) {
                // Overlay paths are generated against a particular version of an application.
                // The overlays paths of a newly upgraded application are incompatible with the
                // old version of the application.
                continue;
            }

            // Isolate the changes relating to RROs. The app info must be copied to prevent
            // affecting other parts of system server that may have cached this app info.
            oldAppInfo = new ApplicationInfo(oldAppInfo);
            oldAppInfo.overlayPaths = newAppInfo.overlayPaths.clone();
            oldAppInfo.resourceDirs = newAppInfo.resourceDirs.clone();
            provider.info.providerInfo.applicationInfo = oldAppInfo;

            for (int j = 0, M = provider.widgets.size(); j < M; j++) {
                Widget widget = provider.widgets.get(j);
                if (widget.views != null) {
                    widget.views.updateAppInfo(oldAppInfo);
                }
                if (widget.maskedViews != null) {
                    widget.maskedViews.updateAppInfo(oldAppInfo);
                }
            }
        }
    }

    /**
     * Updates all providers with the specified package names, and records any providers that were
     * pruned.
@@ -4875,5 +4926,14 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        public void unlockUser(int userId) {
            handleUserUnlocked(userId);
        }

        @Override
        public void applyResourceOverlaysToWidgets(Set<String> packageNames, int userId,
                boolean updateFrameworkRes) {
            synchronized (mLock) {
                applyResourceOverlaysToWidgetsLocked(new HashSet<>(packageNames), userId,
                        updateFrameworkRes);
            }
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@ import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetManagerInternal;
import android.content.AttributionSource;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
@@ -16588,6 +16589,13 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (updateFrameworkRes) {
            ParsingPackageUtils.readConfigUseRoundIcon(null);
        }
        AppWidgetManagerInternal widgets = LocalServices.getService(AppWidgetManagerInternal.class);
        if (widgets != null) {
            widgets.applyResourceOverlaysToWidgets(new HashSet<>(packagesToUpdate), userId,
                    updateFrameworkRes);
        }
        mProcessList.updateApplicationInfoLOSP(packagesToUpdate, userId, updateFrameworkRes);
        if (updateFrameworkRes) {