Loading core/java/android/app/ActivityThread.java +16 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading core/java/android/app/ContextImpl.java +35 −24 Original line number Diff line number Diff line Loading @@ -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). Loading Loading @@ -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 Loading @@ -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()); } /** Loading @@ -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(), Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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) { Loading core/java/android/view/IWindowManager.aidl +17 −0 Original line number Diff line number Diff line Loading @@ -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. Loading core/java/android/window/WindowContextController.java +4 −35 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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; } /** Loading @@ -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); } /** Loading Loading @@ -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(); } } } } core/java/android/window/WindowTokenClient.java +91 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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}. Loading @@ -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 Loading
core/java/android/app/ActivityThread.java +16 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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); Loading
core/java/android/app/ContextImpl.java +35 −24 Original line number Diff line number Diff line Loading @@ -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). Loading Loading @@ -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 Loading @@ -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()); } /** Loading @@ -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(), Loading @@ -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; } Loading Loading @@ -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); Loading @@ -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 Loading Loading @@ -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) { Loading
core/java/android/view/IWindowManager.aidl +17 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
core/java/android/window/WindowContextController.java +4 −35 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading @@ -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; } /** Loading @@ -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); } /** Loading Loading @@ -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(); } } } }
core/java/android/window/WindowTokenClient.java +91 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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}. Loading @@ -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