Loading services/core/java/com/android/server/wm/DisplayContent.java +28 −11 Original line number Diff line number Diff line Loading @@ -4321,6 +4321,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mImeTarget; } @VisibleForTesting SurfaceControl getImeScreenshotSurface() { return mImeSurface; } private SurfaceControl createImeSurface(ScreenCapture.ScreenshotHardwareBuffer b, Transaction t) { final HardwareBuffer buffer = b.getHardwareBuffer(); Loading Loading @@ -4430,33 +4435,45 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } private void attachAndShowImeScreenshotOnTarget() { private void attachImeScreenshotOnTargetIfNeeded() { // No need to attach screenshot if the IME target not exists or screen is off. if (!shouldImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) { return; } final SurfaceControl.Transaction t = getPendingTransaction(); // Prepare IME screenshot for the target if it allows to attach into. if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) { attachImeScreenshotOnTarget(mImeLayeringTarget); } } private void attachImeScreenshotOnTarget(WindowState imeTarget) { final SurfaceControl.Transaction t = getPendingTransaction(); // Remove the obsoleted IME snapshot first in case the new snapshot happens to // override the current one before the transition finish and the surface never be // removed on the task. removeImeSurfaceImmediately(); mImeScreenshot = new ImeScreenshot( mWmService.mSurfaceControlFactory.apply(null), mImeLayeringTarget); mWmService.mSurfaceControlFactory.apply(null), imeTarget); mImeScreenshot.attachAndShow(t); } } /** * Shows the IME screenshot and attach to the IME target window. * Shows the IME screenshot and attach to the IME layering target window. * * Used when the IME target window with IME visible is transitioning to the next target. * e.g. App transitioning or swiping this the task of the IME target window to recents app. */ void showImeScreenshot() { attachAndShowImeScreenshotOnTarget(); attachImeScreenshotOnTargetIfNeeded(); } /** * Shows the IME screenshot and attach it to the given IME target window. */ @VisibleForTesting void showImeScreenshot(WindowState imeTarget) { attachImeScreenshotOnTarget(imeTarget); } /** Loading services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import android.os.IBinder; /** * A class for {@link com.android.server.inputmethod.InputMethodManagerService} to * control IME visibility operations in {@link WindowManagerService}. */ public abstract class ImeTargetVisibilityPolicy { /** * Shows the IME screenshot and attach it to the given IME target window. * * @param imeTarget The target window to show the IME screenshot. * @param displayId A unique id to identify the display. * @return {@code true} if success, {@code false} otherwise. */ public abstract boolean showImeScreenShot(IBinder imeTarget, int displayId); /** * Updates the IME parent for target window. * * @param imeTarget The target window to update the IME parent. * @param displayId A unique id to identify the display. * @return {@code true} if success, {@code false} otherwise. */ public abstract boolean updateImeParent(IBinder imeTarget, int displayId); } services/core/java/com/android/server/wm/WindowManagerService.java +43 −0 Original line number Diff line number Diff line Loading @@ -1338,6 +1338,8 @@ public class WindowManagerService extends IWindowManager.Stub mConstants.start(new HandlerExecutor(mH)); LocalServices.addService(WindowManagerInternal.class, new LocalService()); LocalServices.addService( ImeTargetVisibilityPolicy.class, new ImeTargetVisibilityPolicyImpl()); mEmbeddedWindowController = new EmbeddedWindowController(mAtmService); mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources( Loading Loading @@ -8387,6 +8389,47 @@ public class WindowManagerService extends IWindowManager.Stub } } private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy { // TODO(b/258048231): Track IME visibility change in bugreport when invocations. @Override public boolean showImeScreenShot(@NonNull IBinder imeTarget, int displayId) { synchronized (mGlobalLock) { final WindowState imeTargetWindow = mWindowMap.get(imeTarget); if (imeTargetWindow == null) { return false; } final DisplayContent dc = mRoot.getDisplayContent(displayId); if (dc == null) { Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to show ime screenshot"); return false; } dc.showImeScreenshot(imeTargetWindow); return true; } } // TODO(b/258048231): Track IME visibility change in bugreport when invocations. @Override public boolean updateImeParent(@NonNull IBinder imeTarget, int displayId) { synchronized (mGlobalLock) { final WindowState imeTargetWindow = mWindowMap.get(imeTarget); if (imeTargetWindow == null) { return false; } final DisplayContent dc = mRoot.getDisplayContent(displayId); if (dc == null) { Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to update ime parent"); return false; } dc.updateImeParent(); return true; } } } void registerAppFreezeListener(AppFreezeListener listener) { if (!mAppFreezeListeners.contains(listener)) { mAppFreezeListeners.add(listener); Loading services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +1 −0 Original line number Diff line number Diff line Loading @@ -420,6 +420,7 @@ public class SystemServicesTestRule implements TestRule { LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); LocalServices.removeServiceForTest(UserManagerInternal.class); LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy.class); } Description getDescription() { Loading services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -45,16 +45,21 @@ import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.util.SparseBooleanArray; import android.view.IRecentsAnimationRunner; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.ScreenCapture; import androidx.test.filters.SmallTest; Loading Loading @@ -569,4 +574,26 @@ public class ZOrderingTests extends WindowTestsBase { assertZOrderGreaterThan(mTransaction, systemDialogWindow.getSurfaceControl(), mDisplayContent.getImeContainer().getSurfaceControl()); } @Test public void testImeScreenshotLayer() { final Task task = createTask(mDisplayContent); final WindowState imeAppTarget = createAppWindow(task, TYPE_APPLICATION, "imeAppTarget"); final Rect bounds = mImeWindow.getParentFrame(); final ScreenCapture.ScreenshotHardwareBuffer imeBuffer = ScreenCapture.captureLayersExcluding(mImeWindow.getSurfaceControl(), bounds, 1.0f, PixelFormat.RGB_565, null); spyOn(mDisplayContent.mWmService.mTaskSnapshotController); doReturn(imeBuffer).when(mDisplayContent.mWmService.mTaskSnapshotController) .snapshotImeFromAttachedTask(task); mDisplayContent.showImeScreenshot(imeAppTarget); assertEquals(imeAppTarget, mDisplayContent.mImeScreenshot.getImeTarget()); assertNotNull(mDisplayContent.mImeScreenshot); assertZOrderGreaterThan(mTransaction, mDisplayContent.mImeScreenshot.getImeScreenshotSurface(), imeAppTarget.mSurfaceControl); } } Loading
services/core/java/com/android/server/wm/DisplayContent.java +28 −11 Original line number Diff line number Diff line Loading @@ -4321,6 +4321,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mImeTarget; } @VisibleForTesting SurfaceControl getImeScreenshotSurface() { return mImeSurface; } private SurfaceControl createImeSurface(ScreenCapture.ScreenshotHardwareBuffer b, Transaction t) { final HardwareBuffer buffer = b.getHardwareBuffer(); Loading Loading @@ -4430,33 +4435,45 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } private void attachAndShowImeScreenshotOnTarget() { private void attachImeScreenshotOnTargetIfNeeded() { // No need to attach screenshot if the IME target not exists or screen is off. if (!shouldImeAttachedToApp() || !mWmService.mPolicy.isScreenOn()) { return; } final SurfaceControl.Transaction t = getPendingTransaction(); // Prepare IME screenshot for the target if it allows to attach into. if (mInputMethodWindow != null && mInputMethodWindow.isVisible()) { attachImeScreenshotOnTarget(mImeLayeringTarget); } } private void attachImeScreenshotOnTarget(WindowState imeTarget) { final SurfaceControl.Transaction t = getPendingTransaction(); // Remove the obsoleted IME snapshot first in case the new snapshot happens to // override the current one before the transition finish and the surface never be // removed on the task. removeImeSurfaceImmediately(); mImeScreenshot = new ImeScreenshot( mWmService.mSurfaceControlFactory.apply(null), mImeLayeringTarget); mWmService.mSurfaceControlFactory.apply(null), imeTarget); mImeScreenshot.attachAndShow(t); } } /** * Shows the IME screenshot and attach to the IME target window. * Shows the IME screenshot and attach to the IME layering target window. * * Used when the IME target window with IME visible is transitioning to the next target. * e.g. App transitioning or swiping this the task of the IME target window to recents app. */ void showImeScreenshot() { attachAndShowImeScreenshotOnTarget(); attachImeScreenshotOnTargetIfNeeded(); } /** * Shows the IME screenshot and attach it to the given IME target window. */ @VisibleForTesting void showImeScreenshot(WindowState imeTarget) { attachImeScreenshotOnTarget(imeTarget); } /** Loading
services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import android.os.IBinder; /** * A class for {@link com.android.server.inputmethod.InputMethodManagerService} to * control IME visibility operations in {@link WindowManagerService}. */ public abstract class ImeTargetVisibilityPolicy { /** * Shows the IME screenshot and attach it to the given IME target window. * * @param imeTarget The target window to show the IME screenshot. * @param displayId A unique id to identify the display. * @return {@code true} if success, {@code false} otherwise. */ public abstract boolean showImeScreenShot(IBinder imeTarget, int displayId); /** * Updates the IME parent for target window. * * @param imeTarget The target window to update the IME parent. * @param displayId A unique id to identify the display. * @return {@code true} if success, {@code false} otherwise. */ public abstract boolean updateImeParent(IBinder imeTarget, int displayId); }
services/core/java/com/android/server/wm/WindowManagerService.java +43 −0 Original line number Diff line number Diff line Loading @@ -1338,6 +1338,8 @@ public class WindowManagerService extends IWindowManager.Stub mConstants.start(new HandlerExecutor(mH)); LocalServices.addService(WindowManagerInternal.class, new LocalService()); LocalServices.addService( ImeTargetVisibilityPolicy.class, new ImeTargetVisibilityPolicyImpl()); mEmbeddedWindowController = new EmbeddedWindowController(mAtmService); mDisplayAreaPolicyProvider = DisplayAreaPolicy.Provider.fromResources( Loading Loading @@ -8387,6 +8389,47 @@ public class WindowManagerService extends IWindowManager.Stub } } private final class ImeTargetVisibilityPolicyImpl extends ImeTargetVisibilityPolicy { // TODO(b/258048231): Track IME visibility change in bugreport when invocations. @Override public boolean showImeScreenShot(@NonNull IBinder imeTarget, int displayId) { synchronized (mGlobalLock) { final WindowState imeTargetWindow = mWindowMap.get(imeTarget); if (imeTargetWindow == null) { return false; } final DisplayContent dc = mRoot.getDisplayContent(displayId); if (dc == null) { Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to show ime screenshot"); return false; } dc.showImeScreenshot(imeTargetWindow); return true; } } // TODO(b/258048231): Track IME visibility change in bugreport when invocations. @Override public boolean updateImeParent(@NonNull IBinder imeTarget, int displayId) { synchronized (mGlobalLock) { final WindowState imeTargetWindow = mWindowMap.get(imeTarget); if (imeTargetWindow == null) { return false; } final DisplayContent dc = mRoot.getDisplayContent(displayId); if (dc == null) { Slog.w(TAG, "Invalid displayId:" + displayId + ", fail to update ime parent"); return false; } dc.updateImeParent(); return true; } } } void registerAppFreezeListener(AppFreezeListener listener) { if (!mAppFreezeListeners.contains(listener)) { mAppFreezeListeners.add(listener); Loading
services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +1 −0 Original line number Diff line number Diff line Loading @@ -420,6 +420,7 @@ public class SystemServicesTestRule implements TestRule { LocalServices.removeServiceForTest(UsageStatsManagerInternal.class); LocalServices.removeServiceForTest(StatusBarManagerInternal.class); LocalServices.removeServiceForTest(UserManagerInternal.class); LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy.class); } Description getDescription() { Loading
services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +27 −0 Original line number Diff line number Diff line Loading @@ -45,16 +45,21 @@ import static com.android.server.wm.WindowStateAnimator.PRESERVED_SURFACE_LAYER; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.util.SparseBooleanArray; import android.view.IRecentsAnimationRunner; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.window.ScreenCapture; import androidx.test.filters.SmallTest; Loading Loading @@ -569,4 +574,26 @@ public class ZOrderingTests extends WindowTestsBase { assertZOrderGreaterThan(mTransaction, systemDialogWindow.getSurfaceControl(), mDisplayContent.getImeContainer().getSurfaceControl()); } @Test public void testImeScreenshotLayer() { final Task task = createTask(mDisplayContent); final WindowState imeAppTarget = createAppWindow(task, TYPE_APPLICATION, "imeAppTarget"); final Rect bounds = mImeWindow.getParentFrame(); final ScreenCapture.ScreenshotHardwareBuffer imeBuffer = ScreenCapture.captureLayersExcluding(mImeWindow.getSurfaceControl(), bounds, 1.0f, PixelFormat.RGB_565, null); spyOn(mDisplayContent.mWmService.mTaskSnapshotController); doReturn(imeBuffer).when(mDisplayContent.mWmService.mTaskSnapshotController) .snapshotImeFromAttachedTask(task); mDisplayContent.showImeScreenshot(imeAppTarget); assertEquals(imeAppTarget, mDisplayContent.mImeScreenshot.getImeTarget()); assertNotNull(mDisplayContent.mImeScreenshot); assertZOrderGreaterThan(mTransaction, mDisplayContent.mImeScreenshot.getImeScreenshotSurface(), imeAppTarget.mSurfaceControl); } }