Loading services/core/java/com/android/server/wm/DisplayContent.java +17 −2 Original line number Diff line number Diff line Loading @@ -1588,9 +1588,24 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the // same display. Or even when the current IME/target are not on the same screen as the next // IME/target. For now only look for input windows on the main screen. mUpdateImeTarget = updateImeTarget; WindowState target = getWindow(mComputeImeTargetPredicate); // The target candidate provided by the IME tells us which window token, but not which // window within the token (e.g. child windows...). So, we use the token to look-up the // best target window. // TODO: Have the input method service report the right window with the token vs. just the // base window of the token. final WindowState baseWin = mService.getWindow(mService.mInputMethodTargetCandidate); final WindowToken targetToken = baseWin != null ? baseWin.mToken : null; WindowState target = targetToken != null ? targetToken.getWindow(mComputeImeTargetPredicate) : null; // If there isn't a better candidate in the token (maybe because they are not visible), then // fall back to targeting the base window of the token, so the IME can still maintain the // right z-order based on the last person that set it vs. changing its z-order to the very // up since there if target is null. // TODO: Consider z-ordering IME to bottom instead of top if there is no visible target. // Also, consider tying the visible the visibility of the IME to the current target. I.e if // target isn't visible, then IME shouldn't be visible. target = target == null ? baseWin : target; // Yet more tricksyness! If this window is a "starting" window, we do actually want // to be on top of it, but it is not -really- where input will go. So look down below Loading services/core/java/com/android/server/wm/WindowManagerService.java +36 −14 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.wm; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.MANAGE_APP_TOKENS; import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS; import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; Loading @@ -30,7 +29,6 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.EXTRA_UID; import static android.content.Intent.EXTRA_USER_HANDLE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_NULL; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.DOCKED_INVALID; Loading Loading @@ -69,8 +67,6 @@ import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.AppTransition.TRANSIT_UNSET; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; Loading Loading @@ -112,7 +108,6 @@ import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; Loading Loading @@ -626,9 +621,14 @@ public class WindowManagerService extends IWindowManager.Stub WindowState mCurrentFocus = null; WindowState mLastFocus = null; /** This just indicates the window the input method is on top of, not * necessarily the window its input is going to. */ // TODO: All the IME window tracking should be moved to DisplayContent and tracked per display. // This just indicates the window the input method is on top of, not necessarily the window its // input is going to. WindowState mInputMethodTarget = null; // The binder token currently using the IME as determined by the input method service. // Window manager uses this to determine the final input method target // (almost always this candidate) for z-ordering. IBinder mInputMethodTargetCandidate = null; /** If true hold off on modifying the animation layer of mInputMethodTarget */ boolean mInputMethodTargetWaitingAnim; Loading Loading @@ -6951,8 +6951,9 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mLastFocus="); pw.println(mLastFocus); } pw.print(" mFocusedApp="); pw.println(mFocusedApp); if (mInputMethodTarget != null) { pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); if (mInputMethodTarget != null || mInputMethodTargetCandidate != null) { pw.println(" mInputMethodTarget=" + mInputMethodTarget + " mInputMethodTargetCandidate=" + getWindow(mInputMethodTargetCandidate)); } pw.print(" mInTouchMode="); pw.print(mInTouchMode); pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); Loading Loading @@ -7819,11 +7820,28 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void updateInputMethodWindowStatus(@NonNull IBinder imeToken, boolean imeWindowVisible, @Nullable IBinder targetWindowToken) { // TODO (b/34628091): Use this method to address the window animation issue. if (DEBUG_INPUT_METHOD) { Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken + " imeWindowVisible=" + imeWindowVisible + " targetWindowToken=" + targetWindowToken); synchronized (mWindowMap) { final WindowState newTargetWin = getWindow(targetWindowToken); final WindowState currentTargetWin = getWindow(mInputMethodTargetCandidate); if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken + " imeWindowVisible=" + imeWindowVisible + " targetWindowToken=" + targetWindowToken + " newTargetWin=" + newTargetWin + " currentTargetWin=" + currentTargetWin); if (newTargetWin == currentTargetWin) { return; } final DisplayContent dc = newTargetWin != null ? newTargetWin.getDisplayContent() : currentTargetWin.getDisplayContent(); // It is possible the window for the target candidate isn't added yet, so we // remember the token instead and use it to look-up the window each time we compute // the ime target. mInputMethodTargetCandidate = targetWindowToken; dc.computeImeTarget(true /* updateImeTarget */); } } Loading Loading @@ -7869,6 +7887,10 @@ public class WindowManagerService extends IWindowManager.Stub } } WindowState getWindow(IBinder binder) { return binder == null ? null : mWindowMap.get(binder); } void registerAppFreezeListener(AppFreezeListener listener) { if (!mAppFreezeListeners.contains(listener)) { mAppFreezeListeners.add(listener); Loading services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +16 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; Loading Loading @@ -146,6 +147,7 @@ public class DisplayContentTests extends WindowTestsBase { final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin"); appWin.setHasSurface(true); assertTrue(appWin.canBeImeTarget()); sWm.mInputMethodTargetCandidate = appWin.mClient.asBinder(); WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(appWin, imeTarget); Loading @@ -156,6 +158,20 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(childWin.canBeImeTarget()); imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(childWin, imeTarget); final WindowState appWin2 = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin2"); appWin2.setHasSurface(true); assertTrue(appWin2.canBeImeTarget()); // Verify that the IME target isn't adjusted since mInputMethodTargetCandidate didn't change // to the new app. imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertNotEquals(appWin2, imeTarget); sWm.mInputMethodTargetCandidate = appWin2.mClient.asBinder(); // Verify app is not IME target since its token is set as a candidate. imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(appWin2, imeTarget); } /** Loading services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +6 −4 Original line number Diff line number Diff line Loading @@ -69,7 +69,6 @@ import java.util.LinkedList; class WindowTestsBase { static WindowManagerService sWm = null; static TestWindowManagerPolicy sPolicy = null; private final static IWindow sIWindow = new TestIWindow(); private final static Session sMockSession = mock(Session.class); private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1; static int sNextStackId = FIRST_DYNAMIC_STACK_ID; Loading Loading @@ -148,6 +147,7 @@ class WindowTestsBase { } sWm.mInputMethodTarget = null; sWm.mInputMethodTargetCandidate = null; } private static WindowState createCommonWindow(WindowState parent, int type, String name) { Loading Loading @@ -237,11 +237,12 @@ class WindowTestsBase { final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type); attrs.setTitle(name); final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow); final WindowState w = new WindowState(sWm, sMockSession, new TestIWindow(), token, parent, OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow); // TODO: Probably better to make this call in the WindowState ctor to avoid errors with // adding it to the token... token.addWindow(w); sWm.mWindowMap.put(w.mClient.asBinder(), w); return w; } Loading Loading @@ -463,8 +464,9 @@ class WindowTestsBase { boolean resizeReported; TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) { super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0, super(sWm, sMockSession, new TestIWindow(), token, null, OP_NONE, 0, attrs, 0, 0, false /* ownerCanAddInternalSystemWindow */); sWm.mWindowMap.put(mClient.asBinder(), this); } @Override Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +17 −2 Original line number Diff line number Diff line Loading @@ -1588,9 +1588,24 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the // same display. Or even when the current IME/target are not on the same screen as the next // IME/target. For now only look for input windows on the main screen. mUpdateImeTarget = updateImeTarget; WindowState target = getWindow(mComputeImeTargetPredicate); // The target candidate provided by the IME tells us which window token, but not which // window within the token (e.g. child windows...). So, we use the token to look-up the // best target window. // TODO: Have the input method service report the right window with the token vs. just the // base window of the token. final WindowState baseWin = mService.getWindow(mService.mInputMethodTargetCandidate); final WindowToken targetToken = baseWin != null ? baseWin.mToken : null; WindowState target = targetToken != null ? targetToken.getWindow(mComputeImeTargetPredicate) : null; // If there isn't a better candidate in the token (maybe because they are not visible), then // fall back to targeting the base window of the token, so the IME can still maintain the // right z-order based on the last person that set it vs. changing its z-order to the very // up since there if target is null. // TODO: Consider z-ordering IME to bottom instead of top if there is no visible target. // Also, consider tying the visible the visibility of the IME to the current target. I.e if // target isn't visible, then IME shouldn't be visible. target = target == null ? baseWin : target; // Yet more tricksyness! If this window is a "starting" window, we do actually want // to be on top of it, but it is not -really- where input will go. So look down below Loading
services/core/java/com/android/server/wm/WindowManagerService.java +36 −14 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.server.wm; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.MANAGE_APP_TOKENS; import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS; import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; Loading @@ -30,7 +29,6 @@ import static android.content.Intent.EXTRA_PACKAGE_NAME; import static android.content.Intent.EXTRA_UID; import static android.content.Intent.EXTRA_USER_HANDLE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_NULL; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.DOCKED_INVALID; Loading Loading @@ -69,8 +67,6 @@ import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.AppTransition.TRANSIT_UNSET; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.KeyguardDisableHandler.KEYGUARD_POLICY_CHANGED; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; Loading Loading @@ -112,7 +108,6 @@ import android.app.ActivityManager.TaskSnapshot; import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; Loading Loading @@ -626,9 +621,14 @@ public class WindowManagerService extends IWindowManager.Stub WindowState mCurrentFocus = null; WindowState mLastFocus = null; /** This just indicates the window the input method is on top of, not * necessarily the window its input is going to. */ // TODO: All the IME window tracking should be moved to DisplayContent and tracked per display. // This just indicates the window the input method is on top of, not necessarily the window its // input is going to. WindowState mInputMethodTarget = null; // The binder token currently using the IME as determined by the input method service. // Window manager uses this to determine the final input method target // (almost always this candidate) for z-ordering. IBinder mInputMethodTargetCandidate = null; /** If true hold off on modifying the animation layer of mInputMethodTarget */ boolean mInputMethodTargetWaitingAnim; Loading Loading @@ -6951,8 +6951,9 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" mLastFocus="); pw.println(mLastFocus); } pw.print(" mFocusedApp="); pw.println(mFocusedApp); if (mInputMethodTarget != null) { pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget); if (mInputMethodTarget != null || mInputMethodTargetCandidate != null) { pw.println(" mInputMethodTarget=" + mInputMethodTarget + " mInputMethodTargetCandidate=" + getWindow(mInputMethodTargetCandidate)); } pw.print(" mInTouchMode="); pw.print(mInTouchMode); pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); Loading Loading @@ -7819,11 +7820,28 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void updateInputMethodWindowStatus(@NonNull IBinder imeToken, boolean imeWindowVisible, @Nullable IBinder targetWindowToken) { // TODO (b/34628091): Use this method to address the window animation issue. if (DEBUG_INPUT_METHOD) { Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken + " imeWindowVisible=" + imeWindowVisible + " targetWindowToken=" + targetWindowToken); synchronized (mWindowMap) { final WindowState newTargetWin = getWindow(targetWindowToken); final WindowState currentTargetWin = getWindow(mInputMethodTargetCandidate); if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "updateInputMethodWindowStatus: imeToken=" + imeToken + " imeWindowVisible=" + imeWindowVisible + " targetWindowToken=" + targetWindowToken + " newTargetWin=" + newTargetWin + " currentTargetWin=" + currentTargetWin); if (newTargetWin == currentTargetWin) { return; } final DisplayContent dc = newTargetWin != null ? newTargetWin.getDisplayContent() : currentTargetWin.getDisplayContent(); // It is possible the window for the target candidate isn't added yet, so we // remember the token instead and use it to look-up the window each time we compute // the ime target. mInputMethodTargetCandidate = targetWindowToken; dc.computeImeTarget(true /* updateImeTarget */); } } Loading Loading @@ -7869,6 +7887,10 @@ public class WindowManagerService extends IWindowManager.Stub } } WindowState getWindow(IBinder binder) { return binder == null ? null : mWindowMap.get(binder); } void registerAppFreezeListener(AppFreezeListener listener) { if (!mAppFreezeListeners.contains(listener)) { mAppFreezeListeners.add(listener); Loading
services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +16 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import org.junit.Test; Loading Loading @@ -146,6 +147,7 @@ public class DisplayContentTests extends WindowTestsBase { final WindowState appWin = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin"); appWin.setHasSurface(true); assertTrue(appWin.canBeImeTarget()); sWm.mInputMethodTargetCandidate = appWin.mClient.asBinder(); WindowState imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(appWin, imeTarget); Loading @@ -156,6 +158,20 @@ public class DisplayContentTests extends WindowTestsBase { assertTrue(childWin.canBeImeTarget()); imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(childWin, imeTarget); final WindowState appWin2 = createWindow(null, TYPE_APPLICATION, sDisplayContent, "appWin2"); appWin2.setHasSurface(true); assertTrue(appWin2.canBeImeTarget()); // Verify that the IME target isn't adjusted since mInputMethodTargetCandidate didn't change // to the new app. imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertNotEquals(appWin2, imeTarget); sWm.mInputMethodTargetCandidate = appWin2.mClient.asBinder(); // Verify app is not IME target since its token is set as a candidate. imeTarget = sDisplayContent.computeImeTarget(false /* updateImeTarget */); assertEquals(appWin2, imeTarget); } /** Loading
services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java +6 −4 Original line number Diff line number Diff line Loading @@ -69,7 +69,6 @@ import java.util.LinkedList; class WindowTestsBase { static WindowManagerService sWm = null; static TestWindowManagerPolicy sPolicy = null; private final static IWindow sIWindow = new TestIWindow(); private final static Session sMockSession = mock(Session.class); private static int sNextDisplayId = Display.DEFAULT_DISPLAY + 1; static int sNextStackId = FIRST_DYNAMIC_STACK_ID; Loading Loading @@ -148,6 +147,7 @@ class WindowTestsBase { } sWm.mInputMethodTarget = null; sWm.mInputMethodTargetCandidate = null; } private static WindowState createCommonWindow(WindowState parent, int type, String name) { Loading Loading @@ -237,11 +237,12 @@ class WindowTestsBase { final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(type); attrs.setTitle(name); final WindowState w = new WindowState(sWm, sMockSession, sIWindow, token, parent, OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow); final WindowState w = new WindowState(sWm, sMockSession, new TestIWindow(), token, parent, OP_NONE, 0, attrs, 0, 0, ownerCanAddInternalSystemWindow); // TODO: Probably better to make this call in the WindowState ctor to avoid errors with // adding it to the token... token.addWindow(w); sWm.mWindowMap.put(w.mClient.asBinder(), w); return w; } Loading Loading @@ -463,8 +464,9 @@ class WindowTestsBase { boolean resizeReported; TestWindowState(WindowManager.LayoutParams attrs, WindowToken token) { super(sWm, sMockSession, sIWindow, token, null, OP_NONE, 0, attrs, 0, 0, super(sWm, sMockSession, new TestIWindow(), token, null, OP_NONE, 0, attrs, 0, 0, false /* ownerCanAddInternalSystemWindow */); sWm.mWindowMap.put(mClient.asBinder(), this); } @Override Loading