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

Commit a82b6267 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

Themes: Apply themes to system_server safely

Creates a new UI Context for UI based operations.
This UI Context is wired up the same way a normal app
Context would be, and is subject to change when overlays
are enabled/disabled.

For this reason, only UI should be using this new Context.
All other operations should be using the original system Context
so that changing themes don't impact the regular operations of
system_server.

Also added some sanity checks at key places where we show UI
(ShutdownThread, BaseErrorDialog).

Bug: 36059431
Test: $ adb shell am crash com.android.settings
Test: Observe crash and power off dialogs are blue with PixelTheme
Change-Id: I87227ee2e0be1e72dcde8f482b37725cb687260b
parent 881a623e
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -221,6 +221,7 @@ public final class ActivityThread {
    private long mNetworkBlockSeq = INVALID_PROC_STATE_SEQ;

    private ContextImpl mSystemContext;
    private ContextImpl mSystemUiContext;

    static volatile IPackageManager sPackageManager;

@@ -2178,9 +2179,19 @@ public final class ActivityThread {
        }
    }

    public ContextImpl getSystemUiContext() {
        synchronized (this) {
            if (mSystemUiContext == null) {
                mSystemUiContext = ContextImpl.createSystemUiContext(this);
            }
            return mSystemUiContext;
        }
    }

    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        synchronized (this) {
            getSystemContext().installSystemApplicationInfo(info, classLoader);
            getSystemUiContext().installSystemApplicationInfo(info, classLoader);

            // give ourselves a default profiler
            mProfiler = new Profiler();
@@ -5003,6 +5014,11 @@ public final class ActivityThread {
            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
                systemTheme.rebase();
            }

            final Theme systemUiTheme = getSystemUiContext().getTheme();
            if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
                systemUiTheme.rebase();
            }
        }

        ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
@@ -5058,9 +5074,10 @@ public final class ActivityThread {

        // Trigger a regular Configuration change event, only with a different assetsSeq number
        // so that we actually call through to all components.
        // TODO(adamlesinski): Change this to make use of ActivityManager's upcoming ability to
        // store configurations per-process.
        Configuration newConfig = new Configuration();
        newConfig.unset();
        newConfig.assetsSeq = mConfiguration.assetsSeq + 1;
        newConfig.assetsSeq = (mConfiguration != null ? mConfiguration.assetsSeq : 0) + 1;
        handleConfigurationChanged(newConfig, null);

        // Schedule all activities to reload
+2 −2
Original line number Diff line number Diff line
@@ -1352,7 +1352,7 @@ public class ApplicationPackageManager extends PackageManager {
    public Resources getResourcesForApplication(@NonNull ApplicationInfo app)
            throws NameNotFoundException {
        if (app.packageName.equals("system")) {
            return mContext.mMainThread.getSystemContext().getResources();
            return mContext.mMainThread.getSystemUiContext().getResources();
        }
        final boolean sameUid = (app.uid == Process.myUid());
        final Resources r = mContext.mMainThread.getTopLevelResources(
@@ -1383,7 +1383,7 @@ public class ApplicationPackageManager extends PackageManager {
                    "Call does not support special user #" + userId);
        }
        if ("system".equals(appPackageName)) {
            return mContext.mMainThread.getSystemContext().getResources();
            return mContext.mMainThread.getSystemUiContext().getResources();
        }
        try {
            ApplicationInfo ai = mPM.getApplicationInfo(appPackageName, sDefaultFlags, userId);
+12 −0
Original line number Diff line number Diff line
@@ -2194,6 +2194,18 @@ class ContextImpl extends Context {
        return context;
    }

    /**
     * System Context to be used for UI. This Context has resources that can be themed.
     */
    static ContextImpl createSystemUiContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(createResources(null, packageInfo, null, Display.DEFAULT_DISPLAY, null,
                packageInfo.getCompatibilityInfo()));
        return context;
    }

    static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
        if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
+1 −1
Original line number Diff line number Diff line
@@ -984,7 +984,7 @@ public class ResourcesManager {
                final ResourcesKey key = mResourceImpls.keyAt(i);
                final WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
                final ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
                if (impl != null && key.mResDir != null && key.mResDir.equals(baseCodePath)) {
                if (impl != null && (key.mResDir == null || key.mResDir.equals(baseCodePath))) {
                    updatedResourceKeys.put(impl, new ResourcesKey(
                            key.mResDir,
                            key.mSplitResDirs,
+14 −0
Original line number Diff line number Diff line
@@ -4559,4 +4559,18 @@ public abstract class Context {
    public Handler getMainThreadHandler() {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    /**
     * Throws an exception if the Context is using system resources,
     * which are non-runtime-overlay-themable and may show inconsistent UI.
     * @hide
     */
    public void assertRuntimeOverlayThemable() {
        // Resources.getSystem() is a singleton and the only Resources not managed by
        // ResourcesManager; therefore Resources.getSystem() is not themable.
        if (getResources() == Resources.getSystem()) {
            throw new IllegalArgumentException("Non-UI context used to display UI; "
                    + "get a UI context from ActivityThread#getSystemUiContext()");
        }
    }
}
Loading