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

Commit 83d64906 authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "[RESTRICT AUTOMERGE] Associate SystemUiContext with DisplayContent" into sc-v2-dev

parents eaaeb2f6 08240381
Loading
Loading
Loading
Loading
+16 −11
Original line number 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.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
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.window.ConfigurationHelper.diffPublicWithSizeBuckets;
import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded;
@@ -320,7 +321,7 @@ public final class ActivityThread extends ClientTransactionHandler

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

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

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

    /**
     * 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.
     * @see ContextImpl#createSystemUiContext(ContextImpl, int)
     */
    public ContextImpl createSystemUiContext(int displayId) {
        return ContextImpl.createSystemUiContext(getSystemUiContext(), displayId);
    @NonNull
    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) {
@@ -3767,7 +3772,7 @@ public final class ActivityThread extends ClientTransactionHandler
        if (pkgName != null && !pkgName.isEmpty()
                && r.packageInfo.mPackageName.contains(pkgName)) {
            for (int id : dm.getDisplayIds()) {
                if (id != Display.DEFAULT_DISPLAY) {
                if (id != DEFAULT_DISPLAY) {
                    Display display =
                            dm.getCompatibleDisplay(id, appContext.getResources());
                    appContext = (ContextImpl) appContext.createDisplayContext(display);
+35 −24
Original line number Diff line number Diff line
@@ -2618,7 +2618,10 @@ class ContextImpl extends Context {
                overrideConfig, display.getDisplayAdjustments().getCompatibilityInfo(),
                mResources.getLoaders()));
        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
        // the display that would otherwise be inherited from mToken (or the global configuration if
        // 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
        //         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
        //         context to make the service obtained by #getSystemService(String) able to query
@@ -2696,9 +2700,7 @@ class ContextImpl extends Context {
        if (display == null) {
            throw new IllegalArgumentException("Display must not be null");
        }
        final ContextImpl tokenContext = createWindowContextBase(token, display);
        tokenContext.setResources(createWindowContextResources(tokenContext));
        return tokenContext;
        return createWindowContextBase(token, display.getDisplayId());
    }

    /**
@@ -2706,13 +2708,13 @@ class ContextImpl extends Context {
     * window.
     *
     * @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 #createTokenContext(IBinder, Display)
     */
    @UiContext
    ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) {
    ContextImpl createWindowContextBase(@NonNull IBinder token, int displayId) {
        ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
                mAttributionSource.getAttributionTag(),
                mAttributionSource.getNext(),
@@ -2726,8 +2728,8 @@ class ContextImpl extends Context {
        baseContext.setResources(windowContextResources);
        // Associate the display with window context resources so that configuration update from
        // the server side will also apply to the display's metrics.
        baseContext.mDisplay = ResourcesManager.getInstance()
                .getAdjustedDisplay(display.getDisplayId(), windowContextResources);
        baseContext.mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
                windowContextResources);

        return baseContext;
    }
@@ -2963,6 +2965,18 @@ class ContextImpl extends Context {
        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
    static ContextImpl createSystemContext(ActivityThread 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.
     */
    static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
        final LoadedApk packageInfo = systemContext.mPackageInfo;
        ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
                ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
        context.setResources(createResources(null, packageInfo, null, displayId, null,
                packageInfo.getCompatibilityInfo(), null));
        context.updateDisplay(displayId);
        final WindowTokenClient token = new WindowTokenClient();
        final ContextImpl context = systemContext.createWindowContextBase(token, displayId);
        token.attachContext(context);
        token.attachToDisplayContent(displayId);
        context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI;
        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);
        return context;
    }

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

    @Override
    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) {
+17 −0
Original line number Diff line number Diff line
@@ -865,6 +865,23 @@ interface IWindowManager
     */
    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
     * attached to. It is no-op if the WindowContext is not attached to a window manager node.
+4 −35
Original line number Diff line number Diff line
@@ -19,13 +19,10 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.IWindowManager;
import android.view.WindowManager.LayoutParams.WindowType;
import android.view.WindowManagerGlobal;

import com.android.internal.annotations.VisibleForTesting;

@@ -38,7 +35,6 @@ import com.android.internal.annotations.VisibleForTesting;
 * @hide
 */
public class WindowContextController {
    private final IWindowManager mWms;
    /**
     * {@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
@@ -56,14 +52,7 @@ public class WindowContextController {
     *              {@link Context#getWindowContextToken()}.
     */
    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;
        mWms = mockWms;
    }

    /**
@@ -80,19 +69,7 @@ public class WindowContextController {
            throw new IllegalStateException("A Window Context can be only attached to "
                    + "a DisplayArea once.");
        }
        try {
            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();
        }
        mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options);
    }

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

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

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

import com.android.internal.annotations.VisibleForTesting;

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

    private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();

    private IWindowManager mWms;

    private final Configuration mConfiguration = new Configuration();

    private boolean mShouldDumpConfigForIme;

    private boolean mAttachToWindowContainer;

    /**
     * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient}
     * can only attach one {@link Context}.
@@ -83,6 +92,88 @@ public class WindowTokenClient extends IWindowToken.Stub {
                && 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.
     *
Loading