Loading core/java/android/view/WindowManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ClipData; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; Loading Loading @@ -2843,6 +2844,16 @@ public interface WindowManager extends ViewManager { */ public IBinder token = null; /** * The token of {@link android.app.WindowContext}. It is usually a * {@link android.app.WindowTokenClient} and is used for updating * {@link android.content.res.Resources} from {@link Configuration} propagated from the * server side. * * @hide */ public IBinder mWindowContextToken = null; /** * Name of the package owning this window. */ Loading Loading @@ -3552,6 +3563,7 @@ public interface WindowManager extends ViewManager { out.writeFloat(buttonBrightness); out.writeInt(rotationAnimation); out.writeStrongBinder(token); out.writeStrongBinder(mWindowContextToken); out.writeString(packageName); TextUtils.writeToParcel(mTitle, out, parcelableFlags); out.writeInt(screenOrientation); Loading Loading @@ -3620,6 +3632,7 @@ public interface WindowManager extends ViewManager { buttonBrightness = in.readFloat(); rotationAnimation = in.readInt(); token = in.readStrongBinder(); mWindowContextToken = in.readStrongBinder(); packageName = in.readString(); mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); screenOrientation = in.readInt(); Loading Loading @@ -3781,6 +3794,11 @@ public interface WindowManager extends ViewManager { // already have one. token = o.token; } if (mWindowContextToken == null) { // NOTE: token only copied if the recipient doesn't // already have one. mWindowContextToken = o.mWindowContextToken; } if (packageName == null) { // NOTE: packageName only copied if the recipient doesn't // already have one. Loading core/java/android/view/WindowManagerImpl.java +35 −18 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiContext; import android.app.ResourcesManager; import android.compat.annotation.UnsupportedAppUsage; Loading Loading @@ -74,23 +75,42 @@ public final class WindowManagerImpl implements WindowManager { public final Context mContext; private final Window mParentWindow; /** * If {@link LayoutParams#token} is {@code null} and no parent window is specified, the value * of {@link LayoutParams#token} will be overridden to {@code mDefaultToken}. */ private IBinder mDefaultToken; /** * This token will be set to {@link LayoutParams#mWindowContextToken} and used to receive * configuration changes from the server side. */ @Nullable private final IBinder mWindowContextToken; public WindowManagerImpl(Context context) { this(context, null); this(context, null /* parentWindow */, null /* clientToken */); } private WindowManagerImpl(Context context, Window parentWindow) { private WindowManagerImpl(Context context, Window parentWindow, @Nullable IBinder windowContextToken) { mContext = context; mParentWindow = parentWindow; mWindowContextToken = windowContextToken; } public WindowManagerImpl createLocalWindowManager(Window parentWindow) { return new WindowManagerImpl(mContext, parentWindow); return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken); } public WindowManagerImpl createPresentationWindowManager(Context displayContext) { return new WindowManagerImpl(displayContext, mParentWindow); return new WindowManagerImpl(displayContext, mParentWindow, mWindowContextToken); } /** Creates a {@link WindowManager} for a {@link android.app.WindowContext}. */ public static WindowManager createWindowContextWindowManager(Context context) { final IBinder clientToken = context.getWindowContextToken(); return new WindowManagerImpl(context, null /* parentWindow */, clientToken); } /** Loading @@ -105,30 +125,27 @@ public final class WindowManagerImpl implements WindowManager { @Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); applyTokens(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); } @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); applyTokens(params); mGlobal.updateViewLayout(view, params); } private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) { // Only use the default token if we don't have a parent window. if (mDefaultToken != null && mParentWindow == null) { private void applyTokens(@NonNull ViewGroup.LayoutParams params) { if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } // Only use the default token if we don't already have a token. final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (wparams.token == null) { // Only use the default token if we don't have a parent window and a token. if (mDefaultToken != null && mParentWindow == null && wparams.token == null) { wparams.token = mDefaultToken; } } wparams.mWindowContextToken = mWindowContextToken; } @Override Loading core/tests/coretests/src/android/app/WindowContextTest.java +33 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.app; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading @@ -28,7 +29,10 @@ import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.view.Display; import android.view.IWindowManager; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerImpl; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; Loading @@ -50,23 +54,41 @@ import org.junit.runner.RunWith; @SmallTest @Presubmit public class WindowContextTest { private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); private final WindowContext mWindowContext = createWindowContext(); @Test public void testWindowContextRelease_doRemoveWindowToken() throws Throwable { final Context instContext = InstrumentationRegistry.getInstrumentation() .getTargetContext(); final Display display = instContext.getSystemService(DisplayManager.class) .getDisplay(DEFAULT_DISPLAY); final Context context = instContext.createDisplayContext(display); final WindowContext windowContext = new WindowContext(context, TYPE_APPLICATION_OVERLAY, null /* options */); final IBinder token = windowContext.getWindowContextToken(); final IBinder token = mWindowContext.getWindowContextToken(); final IWindowManager wms = WindowManagerGlobal.getWindowManagerService(); assertTrue("Token must be registered to WMS", wms.isWindowToken(token)); windowContext.release(); mWindowContext.release(); assertFalse("Token must be unregistered to WMS", wms.isWindowToken(token)); } @Test public void testCreateWindowContextWindowManagerAttachClientToken() { final WindowManager windowContextWm = WindowManagerImpl .createWindowContextWindowManager(mWindowContext); final WindowManager.LayoutParams params = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY); mInstrumentation.runOnMainSync(() -> { final View view = new View(mWindowContext); windowContextWm.addView(view, params); }); assertEquals(mWindowContext.getWindowContextToken(), params.mWindowContextToken); } private WindowContext createWindowContext() { final Context instContext = mInstrumentation.getTargetContext(); final Display display = instContext.getSystemService(DisplayManager.class) .getDisplay(DEFAULT_DISPLAY); final Context context = instContext.createDisplayContext(display); return new WindowContext(context, TYPE_APPLICATION_OVERLAY, null /* options */); } } services/core/java/com/android/server/wm/WindowContextListenerController.java +1 −2 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; import android.view.View; import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; Loading @@ -46,7 +45,7 @@ import java.util.Objects; * {@link WindowManagerService#registerWindowContextListener(IBinder, int, int, Bundle)} * automatically.</li> * <li>When the {@link android.app.WindowContext} adds the first window to the screen via * {@link android.view.WindowManager#addView(View, ViewGroup.LayoutParams)}, * {@link android.view.WindowManager#addView(View, android.view.ViewGroup.LayoutParams)}, * {@link WindowManagerService} then updates the {@link WindowContextListenerImpl} to listen * to corresponding {@link WindowToken} via this controller.</li> * <li>When the {@link android.app.WindowContext} is GCed, it unregisters the previously Loading Loading
core/java/android/view/WindowManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -93,6 +93,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ClipData; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; Loading Loading @@ -2843,6 +2844,16 @@ public interface WindowManager extends ViewManager { */ public IBinder token = null; /** * The token of {@link android.app.WindowContext}. It is usually a * {@link android.app.WindowTokenClient} and is used for updating * {@link android.content.res.Resources} from {@link Configuration} propagated from the * server side. * * @hide */ public IBinder mWindowContextToken = null; /** * Name of the package owning this window. */ Loading Loading @@ -3552,6 +3563,7 @@ public interface WindowManager extends ViewManager { out.writeFloat(buttonBrightness); out.writeInt(rotationAnimation); out.writeStrongBinder(token); out.writeStrongBinder(mWindowContextToken); out.writeString(packageName); TextUtils.writeToParcel(mTitle, out, parcelableFlags); out.writeInt(screenOrientation); Loading Loading @@ -3620,6 +3632,7 @@ public interface WindowManager extends ViewManager { buttonBrightness = in.readFloat(); rotationAnimation = in.readInt(); token = in.readStrongBinder(); mWindowContextToken = in.readStrongBinder(); packageName = in.readString(); mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); screenOrientation = in.readInt(); Loading Loading @@ -3781,6 +3794,11 @@ public interface WindowManager extends ViewManager { // already have one. token = o.token; } if (mWindowContextToken == null) { // NOTE: token only copied if the recipient doesn't // already have one. mWindowContextToken = o.mWindowContextToken; } if (packageName == null) { // NOTE: packageName only copied if the recipient doesn't // already have one. Loading
core/java/android/view/WindowManagerImpl.java +35 −18 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UiContext; import android.app.ResourcesManager; import android.compat.annotation.UnsupportedAppUsage; Loading Loading @@ -74,23 +75,42 @@ public final class WindowManagerImpl implements WindowManager { public final Context mContext; private final Window mParentWindow; /** * If {@link LayoutParams#token} is {@code null} and no parent window is specified, the value * of {@link LayoutParams#token} will be overridden to {@code mDefaultToken}. */ private IBinder mDefaultToken; /** * This token will be set to {@link LayoutParams#mWindowContextToken} and used to receive * configuration changes from the server side. */ @Nullable private final IBinder mWindowContextToken; public WindowManagerImpl(Context context) { this(context, null); this(context, null /* parentWindow */, null /* clientToken */); } private WindowManagerImpl(Context context, Window parentWindow) { private WindowManagerImpl(Context context, Window parentWindow, @Nullable IBinder windowContextToken) { mContext = context; mParentWindow = parentWindow; mWindowContextToken = windowContextToken; } public WindowManagerImpl createLocalWindowManager(Window parentWindow) { return new WindowManagerImpl(mContext, parentWindow); return new WindowManagerImpl(mContext, parentWindow, mWindowContextToken); } public WindowManagerImpl createPresentationWindowManager(Context displayContext) { return new WindowManagerImpl(displayContext, mParentWindow); return new WindowManagerImpl(displayContext, mParentWindow, mWindowContextToken); } /** Creates a {@link WindowManager} for a {@link android.app.WindowContext}. */ public static WindowManager createWindowContextWindowManager(Context context) { final IBinder clientToken = context.getWindowContextToken(); return new WindowManagerImpl(context, null /* parentWindow */, clientToken); } /** Loading @@ -105,30 +125,27 @@ public final class WindowManagerImpl implements WindowManager { @Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); applyTokens(params); mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow, mContext.getUserId()); } @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); applyTokens(params); mGlobal.updateViewLayout(view, params); } private void applyDefaultToken(@NonNull ViewGroup.LayoutParams params) { // Only use the default token if we don't have a parent window. if (mDefaultToken != null && mParentWindow == null) { private void applyTokens(@NonNull ViewGroup.LayoutParams params) { if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } // Only use the default token if we don't already have a token. final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params; if (wparams.token == null) { // Only use the default token if we don't have a parent window and a token. if (mDefaultToken != null && mParentWindow == null && wparams.token == null) { wparams.token = mDefaultToken; } } wparams.mWindowContextToken = mWindowContextToken; } @Override Loading
core/tests/coretests/src/android/app/WindowContextTest.java +33 −11 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.app; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; Loading @@ -28,7 +29,10 @@ import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.view.Display; import android.view.IWindowManager; import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.WindowManagerImpl; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; Loading @@ -50,23 +54,41 @@ import org.junit.runner.RunWith; @SmallTest @Presubmit public class WindowContextTest { private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation(); private final WindowContext mWindowContext = createWindowContext(); @Test public void testWindowContextRelease_doRemoveWindowToken() throws Throwable { final Context instContext = InstrumentationRegistry.getInstrumentation() .getTargetContext(); final Display display = instContext.getSystemService(DisplayManager.class) .getDisplay(DEFAULT_DISPLAY); final Context context = instContext.createDisplayContext(display); final WindowContext windowContext = new WindowContext(context, TYPE_APPLICATION_OVERLAY, null /* options */); final IBinder token = windowContext.getWindowContextToken(); final IBinder token = mWindowContext.getWindowContextToken(); final IWindowManager wms = WindowManagerGlobal.getWindowManagerService(); assertTrue("Token must be registered to WMS", wms.isWindowToken(token)); windowContext.release(); mWindowContext.release(); assertFalse("Token must be unregistered to WMS", wms.isWindowToken(token)); } @Test public void testCreateWindowContextWindowManagerAttachClientToken() { final WindowManager windowContextWm = WindowManagerImpl .createWindowContextWindowManager(mWindowContext); final WindowManager.LayoutParams params = new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY); mInstrumentation.runOnMainSync(() -> { final View view = new View(mWindowContext); windowContextWm.addView(view, params); }); assertEquals(mWindowContext.getWindowContextToken(), params.mWindowContextToken); } private WindowContext createWindowContext() { final Context instContext = mInstrumentation.getTargetContext(); final Display display = instContext.getSystemService(DisplayManager.class) .getDisplay(DEFAULT_DISPLAY); final Context context = instContext.createDisplayContext(display); return new WindowContext(context, TYPE_APPLICATION_OVERLAY, null /* options */); } }
services/core/java/com/android/server/wm/WindowContextListenerController.java +1 −2 Original line number Diff line number Diff line Loading @@ -29,7 +29,6 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; import android.view.View; import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; Loading @@ -46,7 +45,7 @@ import java.util.Objects; * {@link WindowManagerService#registerWindowContextListener(IBinder, int, int, Bundle)} * automatically.</li> * <li>When the {@link android.app.WindowContext} adds the first window to the screen via * {@link android.view.WindowManager#addView(View, ViewGroup.LayoutParams)}, * {@link android.view.WindowManager#addView(View, android.view.ViewGroup.LayoutParams)}, * {@link WindowManagerService} then updates the {@link WindowContextListenerImpl} to listen * to corresponding {@link WindowToken} via this controller.</li> * <li>When the {@link android.app.WindowContext} is GCed, it unregisters the previously Loading