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

Commit 08240381 authored by Charles Chen's avatar Charles Chen
Browse files

[RESTRICT AUTOMERGE] Associate SystemUiContext with DisplayContent

Before this CL, SystemUiContexts were fixed to the Display metrics
when the SystemUiContexts were created. It is the same mechanism
as DisplayContext but applies to SystemUiContexts unexpectedly.
This CL makes SystemUiContexts associate with DisplayContent with
the corresponding display ID. In this way, SystemUiContext would
receive updates when there is a Display property change.

Bug: 194262507
Bug: 191064581
Bug: 205859784
Test: atest InputMethodMenuControllerTest WindowContextControllerTest
Test: atest NexusLauncherTests

Change-Id: I64a1614f32d097785915f6105b1813a929e0fe32
parent 88c6602e
Loading
Loading
Loading
Loading
+16 −11
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.window.ConfigurationHelper.diffPublicWithSizeBuckets;
import static android.window.ConfigurationHelper.diffPublicWithSizeBuckets;
import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded;
import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded;
@@ -314,7 +315,7 @@ public final class ActivityThread extends ClientTransactionHandler


    @UnsupportedAppUsage
    @UnsupportedAppUsage
    private ContextImpl mSystemContext;
    private ContextImpl mSystemContext;
    private ContextImpl mSystemUiContext;
    private final SparseArray<ContextImpl> mDisplaySystemUiContexts = new SparseArray<>();


    @UnsupportedAppUsage
    @UnsupportedAppUsage
    static volatile IPackageManager sPackageManager;
    static volatile IPackageManager sPackageManager;
@@ -2611,22 +2612,26 @@ public final class ActivityThread extends ClientTransactionHandler
    }
    }


    @Override
    @Override
    @NonNull
    public ContextImpl getSystemUiContext() {
    public ContextImpl getSystemUiContext() {
        synchronized (this) {
        return getSystemUiContext(DEFAULT_DISPLAY);
            if (mSystemUiContext == null) {
                mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
            }
            return mSystemUiContext;
        }
    }
    }


    /**
    /**
     * Create the context instance base on system resources & display information which used for UI.
     * Gets the context instance base on system resources & display information which used for UI.
     * @param displayId The ID of the display where the UI is shown.
     * @param displayId The ID of the display where the UI is shown.
     * @see ContextImpl#createSystemUiContext(ContextImpl, int)
     * @see ContextImpl#createSystemUiContext(ContextImpl, int)
     */
     */
    public ContextImpl createSystemUiContext(int displayId) {
    @NonNull
        return ContextImpl.createSystemUiContext(getSystemUiContext(), displayId);
    public ContextImpl getSystemUiContext(int displayId) {
        synchronized (this) {
            ContextImpl systemUiContext = mDisplaySystemUiContexts.get(displayId);
            if (systemUiContext == null) {
                systemUiContext = ContextImpl.createSystemUiContext(getSystemContext(), displayId);
                mDisplaySystemUiContexts.put(displayId, systemUiContext);
            }
            return systemUiContext;
        }
    }
    }


    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
@@ -3745,7 +3750,7 @@ public final class ActivityThread extends ClientTransactionHandler
        if (pkgName != null && !pkgName.isEmpty()
        if (pkgName != null && !pkgName.isEmpty()
                && r.packageInfo.mPackageName.contains(pkgName)) {
                && r.packageInfo.mPackageName.contains(pkgName)) {
            for (int id : dm.getDisplayIds()) {
            for (int id : dm.getDisplayIds()) {
                if (id != Display.DEFAULT_DISPLAY) {
                if (id != DEFAULT_DISPLAY) {
                    Display display =
                    Display display =
                            dm.getCompatibleDisplay(id, appContext.getResources());
                            dm.getCompatibleDisplay(id, appContext.getResources());
                    appContext = (ContextImpl) appContext.createDisplayContext(display);
                    appContext = (ContextImpl) appContext.createDisplayContext(display);
+35 −24
Original line number Original line Diff line number Diff line
@@ -2618,7 +2618,10 @@ class ContextImpl extends Context {
                overrideConfig, display.getDisplayAdjustments().getCompatibilityInfo(),
                overrideConfig, display.getDisplayAdjustments().getCompatibilityInfo(),
                mResources.getLoaders()));
                mResources.getLoaders()));
        context.mDisplay = display;
        context.mDisplay = display;
        context.mContextType = CONTEXT_TYPE_DISPLAY_CONTEXT;
        // Inherit context type if the container is from System or System UI context to bypass
        // UI context check.
        context.mContextType = mContextType == CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
                ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI : CONTEXT_TYPE_DISPLAY_CONTEXT;
        // Display contexts and any context derived from a display context should always override
        // Display contexts and any context derived from a display context should always override
        // the display that would otherwise be inherited from mToken (or the global configuration if
        // the display that would otherwise be inherited from mToken (or the global configuration if
        // mToken is null).
        // mToken is null).
@@ -2671,7 +2674,8 @@ class ContextImpl extends Context {


        // Step 2. Create the base context of the window context, it will also create a Resources
        // Step 2. Create the base context of the window context, it will also create a Resources
        //         associated with the WindowTokenClient and set the token to the base context.
        //         associated with the WindowTokenClient and set the token to the base context.
        final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient, display);
        final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient,
                display.getDisplayId());


        // Step 3. Create a WindowContext instance and set it as the outer context of the base
        // Step 3. Create a WindowContext instance and set it as the outer context of the base
        //         context to make the service obtained by #getSystemService(String) able to query
        //         context to make the service obtained by #getSystemService(String) able to query
@@ -2696,9 +2700,7 @@ class ContextImpl extends Context {
        if (display == null) {
        if (display == null) {
            throw new IllegalArgumentException("Display must not be null");
            throw new IllegalArgumentException("Display must not be null");
        }
        }
        final ContextImpl tokenContext = createWindowContextBase(token, display);
        return createWindowContextBase(token, display.getDisplayId());
        tokenContext.setResources(createWindowContextResources(tokenContext));
        return tokenContext;
    }
    }


    /**
    /**
@@ -2706,13 +2708,13 @@ class ContextImpl extends Context {
     * window.
     * window.
     *
     *
     * @param token The token to associate with {@link Resources}
     * @param token The token to associate with {@link Resources}
     * @param display The {@link Display} to associate with.
     * @param displayId The ID of {@link Display} to associate with.
     *
     *
     * @see #createWindowContext(Display, int, Bundle)
     * @see #createWindowContext(Display, int, Bundle)
     * @see #createTokenContext(IBinder, Display)
     * @see #createTokenContext(IBinder, Display)
     */
     */
    @UiContext
    @UiContext
    ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) {
    ContextImpl createWindowContextBase(@NonNull IBinder token, int displayId) {
        ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
        ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
                mAttributionSource.getAttributionTag(),
                mAttributionSource.getAttributionTag(),
                mAttributionSource.getNext(),
                mAttributionSource.getNext(),
@@ -2726,8 +2728,8 @@ class ContextImpl extends Context {
        baseContext.setResources(windowContextResources);
        baseContext.setResources(windowContextResources);
        // Associate the display with window context resources so that configuration update from
        // Associate the display with window context resources so that configuration update from
        // the server side will also apply to the display's metrics.
        // the server side will also apply to the display's metrics.
        baseContext.mDisplay = ResourcesManager.getInstance()
        baseContext.mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
                .getAdjustedDisplay(display.getDisplayId(), windowContextResources);
                windowContextResources);


        return baseContext;
        return baseContext;
    }
    }
@@ -2963,6 +2965,18 @@ class ContextImpl extends Context {
        mContentCaptureOptions = options;
        mContentCaptureOptions = options;
    }
    }


    @Override
    protected void finalize() throws Throwable {
        // If mToken is a WindowTokenClient, the Context is usually associated with a
        // WindowContainer. We should detach from WindowContainer when the Context is finalized
        // if this Context is not a WindowContext. WindowContext finalization is handled in
        // WindowContext class.
        if (mToken instanceof WindowTokenClient && mContextType != CONTEXT_TYPE_WINDOW_CONTEXT) {
            ((WindowTokenClient) mToken).detachFromWindowContainerIfNeeded();
        }
        super.finalize();
    }

    @UnsupportedAppUsage
    @UnsupportedAppUsage
    static ContextImpl createSystemContext(ActivityThread mainThread) {
    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        LoadedApk packageInfo = new LoadedApk(mainThread);
@@ -2983,22 +2997,13 @@ class ContextImpl extends Context {
     * @param displayId The ID of the display where the UI is shown.
     * @param displayId The ID of the display where the UI is shown.
     */
     */
    static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
    static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
        final LoadedApk packageInfo = systemContext.mPackageInfo;
        final WindowTokenClient token = new WindowTokenClient();
        ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
        final ContextImpl context = systemContext.createWindowContextBase(token, displayId);
                ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
        token.attachContext(context);
        context.setResources(createResources(null, packageInfo, null, displayId, null,
        token.attachToDisplayContent(displayId);
                packageInfo.getCompatibilityInfo(), null));
        context.updateDisplay(displayId);
        context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI;
        context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI;
        return context;
    }


    /**
        return context;
     * The overloaded method of {@link #createSystemUiContext(ContextImpl, int)}.
     * Uses {@Code Display.DEFAULT_DISPLAY} as the target display.
     */
    static ContextImpl createSystemUiContext(ContextImpl systemContext) {
        return createSystemUiContext(systemContext, Display.DEFAULT_DISPLAY);
    }
    }


    @UnsupportedAppUsage
    @UnsupportedAppUsage
@@ -3206,7 +3211,13 @@ class ContextImpl extends Context {


    @Override
    @Override
    public IBinder getWindowContextToken() {
    public IBinder getWindowContextToken() {
        return mContextType == CONTEXT_TYPE_WINDOW_CONTEXT ? mToken : null;
        switch (mContextType) {
            case CONTEXT_TYPE_WINDOW_CONTEXT:
            case CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI:
                return mToken;
            default:
                return null;
        }
    }
    }


    private void checkMode(int mode) {
    private void checkMode(int mode) {
+17 −0
Original line number Original line Diff line number Diff line
@@ -865,6 +865,23 @@ interface IWindowManager
     */
     */
    void attachWindowContextToWindowToken(IBinder clientToken, IBinder token);
    void attachWindowContextToWindowToken(IBinder clientToken, IBinder token);


    /**
     * Attaches a {@code clientToken} to associate with DisplayContent.
     * <p>
     * Note that this API should be invoked after calling
     * {@link android.window.WindowTokenClient#attachContext(Context)}
     * </p>
     *
     * @param clientToken {@link android.window.WindowContext#getWindowContextToken()
     * the WindowContext's token}
     * @param displayId The display associated with the window context
     *
     * @return the DisplayContent's {@link android.app.res.Configuration} if the Context is
     * attached to the DisplayContent successfully. {@code null}, otherwise.
     * @throws android.view.WindowManager.InvalidDisplayException if the display ID is invalid
     */
    Configuration attachToDisplayContent(IBinder clientToken, int displayId);

    /**
    /**
     * Detaches {@link android.window.WindowContext} from the window manager node it's currently
     * Detaches {@link android.window.WindowContext} from the window manager node it's currently
     * attached to. It is no-op if the WindowContext is not attached to a window manager node.
     * attached to. It is no-op if the WindowContext is not attached to a window manager node.
+4 −35
Original line number Original line Diff line number Diff line
@@ -19,13 +19,10 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.IWindowManager;
import android.view.IWindowManager;
import android.view.WindowManager.LayoutParams.WindowType;
import android.view.WindowManager.LayoutParams.WindowType;
import android.view.WindowManagerGlobal;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;


@@ -38,7 +35,6 @@ import com.android.internal.annotations.VisibleForTesting;
 * @hide
 * @hide
 */
 */
public class WindowContextController {
public class WindowContextController {
    private final IWindowManager mWms;
    /**
    /**
     * {@code true} to indicate that the {@code mToken} is associated with a
     * {@code true} to indicate that the {@code mToken} is associated with a
     * {@link com.android.server.wm.DisplayArea}. Note that {@code mToken} is able to attach a
     * {@link com.android.server.wm.DisplayArea}. Note that {@code mToken} is able to attach a
@@ -56,14 +52,7 @@ public class WindowContextController {
     *              {@link Context#getWindowContextToken()}.
     *              {@link Context#getWindowContextToken()}.
     */
     */
    public WindowContextController(@NonNull WindowTokenClient token) {
    public WindowContextController(@NonNull WindowTokenClient token) {
        this(token, WindowManagerGlobal.getWindowManagerService());
    }

    /** Used for test only. DO NOT USE it in production code. */
    @VisibleForTesting
    public WindowContextController(@NonNull WindowTokenClient token, IWindowManager mockWms) {
        mToken = token;
        mToken = token;
        mWms = mockWms;
    }
    }


    /**
    /**
@@ -80,19 +69,7 @@ public class WindowContextController {
            throw new IllegalStateException("A Window Context can be only attached to "
            throw new IllegalStateException("A Window Context can be only attached to "
                    + "a DisplayArea once.");
                    + "a DisplayArea once.");
        }
        }
        try {
        mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options);
            final Configuration configuration = mWms.attachWindowContextToDisplayArea(mToken, type,
                    displayId, options);
            if (configuration != null) {
                mAttachedToDisplayArea = true;
                // Send the DisplayArea's configuration to WindowContext directly instead of
                // waiting for dispatching from WMS.
                mToken.onConfigurationChanged(configuration, displayId,
                        false /* shouldReportConfigChange */);
            }
        }  catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    }


    /**
    /**
@@ -120,22 +97,14 @@ public class WindowContextController {
            throw new IllegalStateException("The Window Context should have been attached"
            throw new IllegalStateException("The Window Context should have been attached"
                    + " to a DisplayArea.");
                    + " to a DisplayArea.");
        }
        }
        try {
        mToken.attachToWindowToken(windowToken);
            mWms.attachWindowContextToWindowToken(mToken, windowToken);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    }


    /** Detaches the window context from the node it's currently associated with. */
    /** Detaches the window context from the node it's currently associated with. */
    public void detachIfNeeded() {
    public void detachIfNeeded() {
        if (mAttachedToDisplayArea) {
        if (mAttachedToDisplayArea) {
            try {
            mToken.detachFromWindowContainerIfNeeded();
                mWms.detachWindowContextFromWindowContainer(mToken);
            mAttachedToDisplayArea = false;
            mAttachedToDisplayArea = false;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        }
    }
    }
}
}
+91 −0
Original line number Original line Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.window.ConfigurationHelper.isDifferentDisplay;
import static android.window.ConfigurationHelper.shouldUpdateResources;
import static android.window.ConfigurationHelper.shouldUpdateResources;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.app.ActivityThread;
import android.app.IWindowToken;
import android.app.IWindowToken;
import android.app.ResourcesManager;
import android.app.ResourcesManager;
@@ -31,7 +32,11 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Bundle;
import android.os.Debug;
import android.os.Debug;
import android.os.IBinder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManager.LayoutParams.WindowType;
import android.view.WindowManagerGlobal;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;


@@ -59,10 +64,14 @@ public class WindowTokenClient extends IWindowToken.Stub {


    private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();
    private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();


    private IWindowManager mWms;

    private final Configuration mConfiguration = new Configuration();
    private final Configuration mConfiguration = new Configuration();


    private boolean mShouldDumpConfigForIme;
    private boolean mShouldDumpConfigForIme;


    private boolean mAttachToWindowContainer;

    /**
    /**
     * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient}
     * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient}
     * can only attach one {@link Context}.
     * can only attach one {@link Context}.
@@ -83,6 +92,88 @@ public class WindowTokenClient extends IWindowToken.Stub {
                && context instanceof AbstractInputMethodService;
                && context instanceof AbstractInputMethodService;
    }
    }


    /**
     * Attaches this {@link WindowTokenClient} to a {@link com.android.server.wm.DisplayArea}.
     *
     * @param type The window type of the {@link WindowContext}
     * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
     * @param options The window context launched option
     * @return {@code true} if attaching successfully.
     */
    public boolean attachToDisplayArea(@WindowType int type, int displayId,
            @Nullable Bundle options) {
        try {
            final Configuration configuration = getWindowManagerService()
                    .attachWindowContextToDisplayArea(this, type, displayId, options);
            if (configuration == null) {
                return false;
            }
            onConfigurationChanged(configuration, displayId, false /* shouldReportConfigChange */);
            mAttachToWindowContainer = true;
            return true;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Attaches this {@link WindowTokenClient} to a {@code DisplayContent}.
     *
     * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
     * @return {@code true} if attaching successfully.
     */
    public boolean attachToDisplayContent(int displayId) {
        final IWindowManager wms = getWindowManagerService();
        // #createSystemUiContext may call this method before WindowManagerService is initialized.
        if (wms == null) {
            return false;
        }
        try {
            final Configuration configuration = wms.attachToDisplayContent(this, displayId);
            if (configuration == null) {
                return false;
            }
            onConfigurationChanged(configuration, displayId, false /* shouldReportConfigChange */);
            mAttachToWindowContainer = true;
            return true;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Attaches this {@link WindowTokenClient} to a {@code windowToken}.
     *
     * @param windowToken the window token to associated with
     */
    public void attachToWindowToken(IBinder windowToken) {
        try {
            getWindowManagerService().attachWindowContextToWindowToken(this, windowToken);
            mAttachToWindowContainer = true;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** Detaches this {@link WindowTokenClient} from associated WindowContainer if there's one. */
    public void detachFromWindowContainerIfNeeded() {
        if (!mAttachToWindowContainer) {
            return;
        }
        try {
            getWindowManagerService().detachWindowContextFromWindowContainer(this);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private IWindowManager getWindowManagerService() {
        if (mWms == null) {
            mWms = WindowManagerGlobal.getWindowManagerService();
        }
        return mWms;
    }

    /**
    /**
     * Called when {@link Configuration} updates from the server side receive.
     * Called when {@link Configuration} updates from the server side receive.
     *
     *
Loading