Loading core/java/android/window/WindowContextController.java +56 −9 Original line number Original line Diff line number Diff line Loading @@ -16,16 +16,22 @@ package android.window; package android.window; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; 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.os.Bundle; import android.os.Bundle; import android.os.IBinder; import android.os.IBinder; import android.util.Log; import android.view.IWindowManager; import android.view.IWindowManager; import android.view.WindowManager.LayoutParams.WindowType; import android.view.WindowManager.LayoutParams.WindowType; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; /** /** * The controller to manage {@link WindowContext}, such as attaching to a window manager node or * The controller to manage {@link WindowContext}, such as attaching to a window manager node or * detaching from the current attached node. The user must call * detaching from the current attached node. The user must call Loading @@ -35,13 +41,43 @@ import com.android.internal.annotations.VisibleForTesting; * @hide * @hide */ */ public class WindowContextController { public class WindowContextController { // TODO(220049234): Disable attach debug logging before shipping. private static final boolean DEBUG_ATTACH = true; private static final String TAG = "WindowContextController"; /** /** * {@code true} to indicate that the {@code mToken} is associated with a * {@link AttachStatus.STATUS_ATTACHED} 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 * WindowToken after this flag sets to {@code true}. * WindowToken after this flag sets to {@link AttachStatus.STATUS_ATTACHED}. */ */ @VisibleForTesting @VisibleForTesting public boolean mAttachedToDisplayArea; public int mAttachedToDisplayArea = AttachStatus.STATUS_INITIALIZED; /** * Status to indicate that the Window Context attach to a * {@link com.android.server.wm.DisplayArea}. */ @Retention(SOURCE) @IntDef({AttachStatus.STATUS_INITIALIZED, AttachStatus.STATUS_ATTACHED, AttachStatus.STATUS_DETACHED, AttachStatus.STATUS_FAILED}) public @interface AttachStatus{ /** * The Window Context haven't attached to a {@link com.android.server.wm.DisplayArea}. */ int STATUS_INITIALIZED = 0; /** * The Window Context has already attached to a {@link com.android.server.wm.DisplayArea}. */ int STATUS_ATTACHED = 1; /** * The Window Context has detached from a {@link com.android.server.wm.DisplayArea}. */ int STATUS_DETACHED = 2; /** * The Window Context fails to attach to a {@link com.android.server.wm.DisplayArea}. */ int STATUS_FAILED = 3; } @NonNull @NonNull private final WindowTokenClient mToken; private final WindowTokenClient mToken; Loading @@ -65,11 +101,19 @@ public class WindowContextController { * DisplayArea. * DisplayArea. */ */ public void attachToDisplayArea(@WindowType int type, int displayId, @Nullable Bundle options) { public void attachToDisplayArea(@WindowType int type, int displayId, @Nullable Bundle options) { if (mAttachedToDisplayArea) { if (mAttachedToDisplayArea == AttachStatus.STATUS_ATTACHED) { 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."); } } mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options); mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options) ? AttachStatus.STATUS_ATTACHED : AttachStatus.STATUS_FAILED; if (mAttachedToDisplayArea == AttachStatus.STATUS_FAILED) { Log.w(TAG, "attachToDisplayArea fail, type:" + type + ", displayId:" + displayId); } else if (DEBUG_ATTACH) { Log.d(TAG, "attachToDisplayArea success, type:" + type + ", displayId:" + displayId); } } } /** /** Loading @@ -93,18 +137,21 @@ public class WindowContextController { * @see IWindowManager#attachWindowContextToWindowToken(IBinder, IBinder) * @see IWindowManager#attachWindowContextToWindowToken(IBinder, IBinder) */ */ public void attachToWindowToken(IBinder windowToken) { public void attachToWindowToken(IBinder windowToken) { if (!mAttachedToDisplayArea) { if (mAttachedToDisplayArea != AttachStatus.STATUS_ATTACHED) { 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. AttachToDisplayArea:" + mAttachedToDisplayArea); } } mToken.attachToWindowToken(windowToken); mToken.attachToWindowToken(windowToken); } } /** 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 == AttachStatus.STATUS_ATTACHED) { mToken.detachFromWindowContainerIfNeeded(); mToken.detachFromWindowContainerIfNeeded(); mAttachedToDisplayArea = false; mAttachedToDisplayArea = AttachStatus.STATUS_DETACHED; if (DEBUG_ATTACH) { Log.d(TAG, "Detach Window Context."); } } } } } } } core/tests/coretests/src/android/window/WindowContextControllerTest.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -86,11 +86,13 @@ public class WindowContextControllerTest { mController.attachToDisplayArea(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, mController.attachToDisplayArea(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); null /* options */); assertThat(mController.mAttachedToDisplayArea).isTrue(); assertThat(mController.mAttachedToDisplayArea).isEqualTo( WindowContextController.AttachStatus.STATUS_ATTACHED); mController.detachIfNeeded(); mController.detachIfNeeded(); assertThat(mController.mAttachedToDisplayArea).isFalse(); assertThat(mController.mAttachedToDisplayArea).isEqualTo( WindowContextController.AttachStatus.STATUS_DETACHED); } } @Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class) Loading Loading
core/java/android/window/WindowContextController.java +56 −9 Original line number Original line Diff line number Diff line Loading @@ -16,16 +16,22 @@ package android.window; package android.window; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; 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.os.Bundle; import android.os.Bundle; import android.os.IBinder; import android.os.IBinder; import android.util.Log; import android.view.IWindowManager; import android.view.IWindowManager; import android.view.WindowManager.LayoutParams.WindowType; import android.view.WindowManager.LayoutParams.WindowType; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; /** /** * The controller to manage {@link WindowContext}, such as attaching to a window manager node or * The controller to manage {@link WindowContext}, such as attaching to a window manager node or * detaching from the current attached node. The user must call * detaching from the current attached node. The user must call Loading @@ -35,13 +41,43 @@ import com.android.internal.annotations.VisibleForTesting; * @hide * @hide */ */ public class WindowContextController { public class WindowContextController { // TODO(220049234): Disable attach debug logging before shipping. private static final boolean DEBUG_ATTACH = true; private static final String TAG = "WindowContextController"; /** /** * {@code true} to indicate that the {@code mToken} is associated with a * {@link AttachStatus.STATUS_ATTACHED} 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 * WindowToken after this flag sets to {@code true}. * WindowToken after this flag sets to {@link AttachStatus.STATUS_ATTACHED}. */ */ @VisibleForTesting @VisibleForTesting public boolean mAttachedToDisplayArea; public int mAttachedToDisplayArea = AttachStatus.STATUS_INITIALIZED; /** * Status to indicate that the Window Context attach to a * {@link com.android.server.wm.DisplayArea}. */ @Retention(SOURCE) @IntDef({AttachStatus.STATUS_INITIALIZED, AttachStatus.STATUS_ATTACHED, AttachStatus.STATUS_DETACHED, AttachStatus.STATUS_FAILED}) public @interface AttachStatus{ /** * The Window Context haven't attached to a {@link com.android.server.wm.DisplayArea}. */ int STATUS_INITIALIZED = 0; /** * The Window Context has already attached to a {@link com.android.server.wm.DisplayArea}. */ int STATUS_ATTACHED = 1; /** * The Window Context has detached from a {@link com.android.server.wm.DisplayArea}. */ int STATUS_DETACHED = 2; /** * The Window Context fails to attach to a {@link com.android.server.wm.DisplayArea}. */ int STATUS_FAILED = 3; } @NonNull @NonNull private final WindowTokenClient mToken; private final WindowTokenClient mToken; Loading @@ -65,11 +101,19 @@ public class WindowContextController { * DisplayArea. * DisplayArea. */ */ public void attachToDisplayArea(@WindowType int type, int displayId, @Nullable Bundle options) { public void attachToDisplayArea(@WindowType int type, int displayId, @Nullable Bundle options) { if (mAttachedToDisplayArea) { if (mAttachedToDisplayArea == AttachStatus.STATUS_ATTACHED) { 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."); } } mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options); mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options) ? AttachStatus.STATUS_ATTACHED : AttachStatus.STATUS_FAILED; if (mAttachedToDisplayArea == AttachStatus.STATUS_FAILED) { Log.w(TAG, "attachToDisplayArea fail, type:" + type + ", displayId:" + displayId); } else if (DEBUG_ATTACH) { Log.d(TAG, "attachToDisplayArea success, type:" + type + ", displayId:" + displayId); } } } /** /** Loading @@ -93,18 +137,21 @@ public class WindowContextController { * @see IWindowManager#attachWindowContextToWindowToken(IBinder, IBinder) * @see IWindowManager#attachWindowContextToWindowToken(IBinder, IBinder) */ */ public void attachToWindowToken(IBinder windowToken) { public void attachToWindowToken(IBinder windowToken) { if (!mAttachedToDisplayArea) { if (mAttachedToDisplayArea != AttachStatus.STATUS_ATTACHED) { 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. AttachToDisplayArea:" + mAttachedToDisplayArea); } } mToken.attachToWindowToken(windowToken); mToken.attachToWindowToken(windowToken); } } /** 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 == AttachStatus.STATUS_ATTACHED) { mToken.detachFromWindowContainerIfNeeded(); mToken.detachFromWindowContainerIfNeeded(); mAttachedToDisplayArea = false; mAttachedToDisplayArea = AttachStatus.STATUS_DETACHED; if (DEBUG_ATTACH) { Log.d(TAG, "Detach Window Context."); } } } } } } }
core/tests/coretests/src/android/window/WindowContextControllerTest.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -86,11 +86,13 @@ public class WindowContextControllerTest { mController.attachToDisplayArea(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, mController.attachToDisplayArea(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); null /* options */); assertThat(mController.mAttachedToDisplayArea).isTrue(); assertThat(mController.mAttachedToDisplayArea).isEqualTo( WindowContextController.AttachStatus.STATUS_ATTACHED); mController.detachIfNeeded(); mController.detachIfNeeded(); assertThat(mController.mAttachedToDisplayArea).isFalse(); assertThat(mController.mAttachedToDisplayArea).isEqualTo( WindowContextController.AttachStatus.STATUS_DETACHED); } } @Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class) Loading