Introduce ImeTargetVisibilityPolicy

This class provides ime target visibility
utility functions from IMMS to WM as:
-. update ime screenshot
-. update ime parent

This change only build the class and no module
rely on it so it shouldn't have behavior changes.

Bug: 258048231
Test: atest WmTests:ZOrderingTests#testImeScreenshotLayer
Change-Id: Ie567ba578dca65be0a9a11d9a4aa27a13fe69900
This commit is contained in:
Wilson Wu
2023-01-07 16:47:44 +08:00
parent 760242334c
commit e124ea5351
5 changed files with 144 additions and 11 deletions

View File

@@ -4320,6 +4320,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();
@@ -4429,33 +4434,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()) {
// 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);
mImeScreenshot.attachAndShow(t);
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), 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);
}
/**

View File

@@ -0,0 +1,45 @@
/*
* 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);
}

View File

@@ -1333,6 +1333,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(
@@ -8333,6 +8335,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);

View File

@@ -419,6 +419,7 @@ public class SystemServicesTestRule implements TestRule {
LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
LocalServices.removeServiceForTest(UserManagerInternal.class);
LocalServices.removeServiceForTest(ImeTargetVisibilityPolicy.class);
}
Description getDescription() {

View File

@@ -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;
@@ -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);
}
}