Loading services/core/java/com/android/server/wm/ActivityRecord.java +0 −21 Original line number Diff line number Diff line Loading @@ -763,13 +763,6 @@ final class ActivityRecord extends WindowToken { /** Whether the IME is showing when transitioning away from this activity. */ boolean mLastImeShown; /** * When set to true, the IME insets will be frozen until the next app becomes IME input target. * @see InsetsPolicy#adjustVisibilityForIme * @see ImeInsetsSourceProvider#updateClientVisibility */ boolean mImeInsetsFrozenUntilStartInput; /** * A flag to determine if this AR is in the process of closing or entering PIP. This is needed * to help AR know that the app is in the process of closing but hasn't yet started closing on Loading Loading @@ -1175,8 +1168,6 @@ final class ActivityRecord extends WindowToken { pw.print(" launchMode="); pw.println(launchMode); pw.print(prefix); pw.print("mActivityType="); pw.println(activityTypeToString(getActivityType())); pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput="); pw.println(mImeInsetsFrozenUntilStartInput); if (requestedVrComponent != null) { pw.print(prefix); pw.print("requestedVrComponent="); Loading Loading @@ -5874,10 +5865,6 @@ final class ActivityRecord extends WindowToken { } final DisplayContent displayContent = getDisplayContent(); if (!visible) { mImeInsetsFrozenUntilStartInput = true; } if (!displayContent.mClosingApps.contains(this) && !displayContent.mOpeningApps.contains(this) && !fromTransition) { Loading Loading @@ -6953,14 +6940,6 @@ final class ActivityRecord extends WindowToken { // closing activity having to wait until idle timeout to be stopped or destroyed if the // next activity won't report idle (e.g. repeated view animation). mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded(); // If the activity is visible, but no windows are eligible to start input, unfreeze // to avoid permanently frozen IME insets. if (mImeInsetsFrozenUntilStartInput && getWindow( win -> WindowManager.LayoutParams.mayUseInputMethod(win.mAttrs.flags)) == null) { mImeInsetsFrozenUntilStartInput = false; } } } Loading services/core/java/com/android/server/wm/DisplayContent.java +0 −29 Original line number Diff line number Diff line Loading @@ -4661,35 +4661,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } /** * Callback from {@link ImeInsetsSourceProvider#updateClientVisibility} for the system to * judge whether or not to notify the IME insets provider to dispatch this reported IME client * visibility state to the app clients when needed. */ boolean onImeInsetsClientVisibilityUpdate() { boolean[] changed = new boolean[1]; // Unlike the IME layering target or the control target can be updated during the layout // change, the IME input target requires to be changed after gaining the input focus. // In case unfreezing IME insets state may too early during IME focus switching, we unfreeze // when activities going to be visible until the input target changed, or the // activity was the current input target that has to unfreeze after updating the IME // client visibility. final ActivityRecord inputTargetActivity = mImeInputTarget != null ? mImeInputTarget.getActivityRecord() : null; final boolean targetChanged = mImeInputTarget != mLastImeInputTarget; if (targetChanged || inputTargetActivity != null && inputTargetActivity.isVisibleRequested() && inputTargetActivity.mImeInsetsFrozenUntilStartInput) { forAllActivities(r -> { if (r.mImeInsetsFrozenUntilStartInput && r.isVisibleRequested()) { r.mImeInsetsFrozenUntilStartInput = false; changed[0] = true; } }); } return changed[0]; } void updateImeControlTarget() { updateImeControlTarget(false /* forceUpdateImeParent */); } Loading services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +0 −1 Original line number Diff line number Diff line Loading @@ -321,7 +321,6 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { reportImeDrawnForOrganizerIfNeeded((InsetsControlTarget) caller); } } changed |= mDisplayContent.onImeInsetsClientVisibilityUpdate(); if (Flags.refactorInsetsController()) { if (changed) { ImeTracker.forLogging().onProgress(statsToken, Loading services/core/java/com/android/server/wm/InsetsPolicy.java +0 −16 Original line number Diff line number Diff line Loading @@ -387,22 +387,6 @@ class InsetsPolicy { state.addSource(navSource); } return state; } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { // During switching tasks with gestural navigation, before the next IME input target // starts the input, we should adjust and freeze the last IME visibility of the window // in case delivering obsoleted IME insets state during transitioning. final InsetsSource originalImeSource = originalState.peekSource(ID_IME); if (originalImeSource != null) { final boolean imeVisibility = w.isRequestedVisible(Type.ime()); final InsetsState state = copyState ? new InsetsState(originalState) : originalState; final InsetsSource imeSource = new InsetsSource(originalImeSource); imeSource.setVisible(imeVisibility); state.addSource(imeSource); return state; } } else if (w.mImeInsetsConsumed) { // Set the IME source (if there is one) to be invisible if it has been consumed. final InsetsSource originalImeSource = originalState.peekSource(ID_IME); Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +0 −180 Original line number Diff line number Diff line Loading @@ -49,17 +49,13 @@ import static android.content.res.Configuration.UI_MODE_TYPE_DESK; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.Process.NOBODY_UID; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.InsetsSource.ID_IME; import static android.view.WindowInsets.Type.ime; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_PIP; Loading Loading @@ -125,7 +121,6 @@ import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.ClientTransactionItem; import android.app.servertransaction.DestroyActivityItem; import android.app.servertransaction.PauseActivityItem; import android.app.servertransaction.WindowStateResizeItem; import android.compat.testing.PlatformCompatChangeRule; import android.content.ComponentName; import android.content.Intent; Loading @@ -149,8 +144,6 @@ import android.view.DisplayInfo; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner.Stub; import android.view.IWindowManager; import android.view.InsetsSource; import android.view.InsetsState; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.Surface; Loading @@ -171,7 +164,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import java.util.ArrayList; Loading Loading @@ -3370,178 +3362,6 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse(activity.mDisplayContent.mClosingApps.contains(activity)); } @SetupWindows(addWindows = W_INPUT_METHOD) @Test public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); makeWindowVisibleAndDrawn(app, mImeWindow); mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); // Simulate app is closing and expect the last IME is shown and IME insets is frozen. mDisplayContent.mOpeningApps.clear(); app.mActivityRecord.commitVisibility(false, false); app.mActivityRecord.onWindowsGone(); assertTrue(app.mActivityRecord.mLastImeShown); assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Expect IME insets frozen state will reset when the activity has no IME focusable window. app.mActivityRecord.forAllWindows(w -> { w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM; return true; }, true); app.mActivityRecord.commitVisibility(true, false); app.mActivityRecord.onWindowsVisible(); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); } @SetupWindows(addWindows = W_INPUT_METHOD) @Test public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer( mImeWindow, null, null); mImeWindow.getControllableInsetProvider().setServerVisible(true); InsetsSource imeSource = new InsetsSource(ID_IME, ime()); app.mAboveInsetsState.addSource(imeSource); mDisplayContent.setImeLayeringTarget(app); mDisplayContent.updateImeInputAndControlTarget(app); InsetsState state = app.getInsetsState(); assertFalse(state.getOrCreateSource(imeSource.getId(), ime()).isVisible()); assertTrue(state.getOrCreateSource(imeSource.getId(), ime()).getFrame().isEmpty()); // Simulate app is closing and expect IME insets is frozen. mDisplayContent.mOpeningApps.clear(); app.mActivityRecord.commitVisibility(false, false); app.mActivityRecord.onWindowsGone(); assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen app.mActivityRecord.commitVisibility(true, false); mDisplayContent.updateImeInputAndControlTarget(app); performSurfacePlacementAndWaitForWindowAnimator(); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setVisible(true); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.mAboveInsetsState.addSource(imeSource); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); state = app.getInsetsState(); assertTrue(state.peekSource(ID_IME).isVisible()); assertEquals(state.peekSource(ID_IME).getFrame(), imeSource.getFrame()); } @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD }) @Test public void testImeInsetsFrozenFlag_noDispatchVisibleInsetsWhenAppNotRequest() throws RemoteException { final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build(); mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer( mImeWindow, null, null); mImeWindow.getControllableInsetProvider().setServerVisible(true); // Simulate app2 is closing and let app1 is visible to be IME targets. makeWindowVisibleAndDrawn(app1, mImeWindow); mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.updateImeInputAndControlTarget(app1); app2.mActivityRecord.commitVisibility(false, false); // app1 requests IME visible. app1.setRequestedVisibleTypes(ime(), ime()); mDisplayContent.getInsetsStateController().onRequestedVisibleTypesChanged(app1, null /* statsToken */); // Verify app1's IME insets is visible and app2's IME insets frozen flag set. assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible()); assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Simulate switching to app2 to make it visible to be IME targets. spyOn(app2); spyOn(app2.mClient); spyOn(app2.getProcess()); ArgumentCaptor<InsetsState> insetsStateCaptor = ArgumentCaptor.forClass(InsetsState.class); doReturn(true).when(app2).isReadyToDispatchInsetsState(); mDisplayContent.setImeLayeringTarget(app2); app2.mActivityRecord.commitVisibility(true, false); mDisplayContent.updateImeInputAndControlTarget(app2); performSurfacePlacementAndWaitForWindowAnimator(); // Verify after unfreezing app2's IME insets state, we won't dispatch visible IME insets // to client if the app didn't request IME visible. assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput); verify(app2.getProcess(), atLeastOnce()).scheduleClientTransactionItem( isA(WindowStateResizeItem.class)); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); } @Test public void testImeInsetsFrozenFlag_multiWindowActivities() { final WindowToken imeToken = createTestWindowToken(TYPE_INPUT_METHOD, mDisplayContent); final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).setWindowToken( imeToken).build(); makeWindowVisibleAndDrawn(ime); // Create a split-screen root task with activity1 and activity 2. final Task task = new TaskBuilder(mSupervisor) .setCreateParentTask(true).setCreateActivity(true).build(); task.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); final ActivityRecord activity1 = task.getTopNonFinishingActivity(); activity1.getTask().setResumedActivity(activity1, "testApp1"); final ActivityRecord activity2 = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW) .setCreateActivity(true).build().getTopMostActivity(); activity2.getTask().setResumedActivity(activity2, "testApp2"); activity2.getTask().setParent(task.getRootTask()); // Simulate activity1 and activity2 both have set mImeInsetsFrozenUntilStartInput when // invisible to user. activity1.mImeInsetsFrozenUntilStartInput = true; activity2.mImeInsetsFrozenUntilStartInput = true; final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).setWindowToken( activity1).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowToken( activity2).build(); makeWindowVisibleAndDrawn(app1, app2); final InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.getImeSourceProvider().setWindowContainer( ime, null, null); ime.getControllableInsetProvider().setServerVisible(true); // app1 starts input and expect IME insets for all activities in split-screen will be // frozen until the input started. mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.updateImeInputAndControlTarget(app1); mDisplayContent.computeImeTarget(true /* updateImeTarget */); performSurfacePlacementAndWaitForWindowAnimator(); assertEquals(app1, mDisplayContent.getImeInputTarget()); assertFalse(activity1.mImeInsetsFrozenUntilStartInput); assertFalse(activity2.mImeInsetsFrozenUntilStartInput); app1.setRequestedVisibleTypes(ime()); controller.onRequestedVisibleTypesChanged(app1, null /* statsToken */); // Expect all activities in split-screen will get IME insets visible state assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible()); assertTrue(app2.getInsetsState().peekSource(ID_IME).isVisible()); } @Test public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +0 −21 Original line number Diff line number Diff line Loading @@ -763,13 +763,6 @@ final class ActivityRecord extends WindowToken { /** Whether the IME is showing when transitioning away from this activity. */ boolean mLastImeShown; /** * When set to true, the IME insets will be frozen until the next app becomes IME input target. * @see InsetsPolicy#adjustVisibilityForIme * @see ImeInsetsSourceProvider#updateClientVisibility */ boolean mImeInsetsFrozenUntilStartInput; /** * A flag to determine if this AR is in the process of closing or entering PIP. This is needed * to help AR know that the app is in the process of closing but hasn't yet started closing on Loading Loading @@ -1175,8 +1168,6 @@ final class ActivityRecord extends WindowToken { pw.print(" launchMode="); pw.println(launchMode); pw.print(prefix); pw.print("mActivityType="); pw.println(activityTypeToString(getActivityType())); pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput="); pw.println(mImeInsetsFrozenUntilStartInput); if (requestedVrComponent != null) { pw.print(prefix); pw.print("requestedVrComponent="); Loading Loading @@ -5874,10 +5865,6 @@ final class ActivityRecord extends WindowToken { } final DisplayContent displayContent = getDisplayContent(); if (!visible) { mImeInsetsFrozenUntilStartInput = true; } if (!displayContent.mClosingApps.contains(this) && !displayContent.mOpeningApps.contains(this) && !fromTransition) { Loading Loading @@ -6953,14 +6940,6 @@ final class ActivityRecord extends WindowToken { // closing activity having to wait until idle timeout to be stopped or destroyed if the // next activity won't report idle (e.g. repeated view animation). mTaskSupervisor.scheduleProcessStoppingAndFinishingActivitiesIfNeeded(); // If the activity is visible, but no windows are eligible to start input, unfreeze // to avoid permanently frozen IME insets. if (mImeInsetsFrozenUntilStartInput && getWindow( win -> WindowManager.LayoutParams.mayUseInputMethod(win.mAttrs.flags)) == null) { mImeInsetsFrozenUntilStartInput = false; } } } Loading
services/core/java/com/android/server/wm/DisplayContent.java +0 −29 Original line number Diff line number Diff line Loading @@ -4661,35 +4661,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } } /** * Callback from {@link ImeInsetsSourceProvider#updateClientVisibility} for the system to * judge whether or not to notify the IME insets provider to dispatch this reported IME client * visibility state to the app clients when needed. */ boolean onImeInsetsClientVisibilityUpdate() { boolean[] changed = new boolean[1]; // Unlike the IME layering target or the control target can be updated during the layout // change, the IME input target requires to be changed after gaining the input focus. // In case unfreezing IME insets state may too early during IME focus switching, we unfreeze // when activities going to be visible until the input target changed, or the // activity was the current input target that has to unfreeze after updating the IME // client visibility. final ActivityRecord inputTargetActivity = mImeInputTarget != null ? mImeInputTarget.getActivityRecord() : null; final boolean targetChanged = mImeInputTarget != mLastImeInputTarget; if (targetChanged || inputTargetActivity != null && inputTargetActivity.isVisibleRequested() && inputTargetActivity.mImeInsetsFrozenUntilStartInput) { forAllActivities(r -> { if (r.mImeInsetsFrozenUntilStartInput && r.isVisibleRequested()) { r.mImeInsetsFrozenUntilStartInput = false; changed[0] = true; } }); } return changed[0]; } void updateImeControlTarget() { updateImeControlTarget(false /* forceUpdateImeParent */); } Loading
services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +0 −1 Original line number Diff line number Diff line Loading @@ -321,7 +321,6 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { reportImeDrawnForOrganizerIfNeeded((InsetsControlTarget) caller); } } changed |= mDisplayContent.onImeInsetsClientVisibilityUpdate(); if (Flags.refactorInsetsController()) { if (changed) { ImeTracker.forLogging().onProgress(statsToken, Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +0 −16 Original line number Diff line number Diff line Loading @@ -387,22 +387,6 @@ class InsetsPolicy { state.addSource(navSource); } return state; } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { // During switching tasks with gestural navigation, before the next IME input target // starts the input, we should adjust and freeze the last IME visibility of the window // in case delivering obsoleted IME insets state during transitioning. final InsetsSource originalImeSource = originalState.peekSource(ID_IME); if (originalImeSource != null) { final boolean imeVisibility = w.isRequestedVisible(Type.ime()); final InsetsState state = copyState ? new InsetsState(originalState) : originalState; final InsetsSource imeSource = new InsetsSource(originalImeSource); imeSource.setVisible(imeVisibility); state.addSource(imeSource); return state; } } else if (w.mImeInsetsConsumed) { // Set the IME source (if there is one) to be invisible if it has been consumed. final InsetsSource originalImeSource = originalState.peekSource(ID_IME); Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +0 −180 Original line number Diff line number Diff line Loading @@ -49,17 +49,13 @@ import static android.content.res.Configuration.UI_MODE_TYPE_DESK; import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS; import static android.os.Process.NOBODY_UID; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.InsetsSource.ID_IME; import static android.view.WindowInsets.Type.ime; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_PIP; Loading Loading @@ -125,7 +121,6 @@ import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.ClientTransactionItem; import android.app.servertransaction.DestroyActivityItem; import android.app.servertransaction.PauseActivityItem; import android.app.servertransaction.WindowStateResizeItem; import android.compat.testing.PlatformCompatChangeRule; import android.content.ComponentName; import android.content.Intent; Loading @@ -149,8 +144,6 @@ import android.view.DisplayInfo; import android.view.IRemoteAnimationFinishedCallback; import android.view.IRemoteAnimationRunner.Stub; import android.view.IWindowManager; import android.view.InsetsSource; import android.view.InsetsState; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.Surface; Loading @@ -171,7 +164,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.invocation.InvocationOnMock; import java.util.ArrayList; Loading Loading @@ -3370,178 +3362,6 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse(activity.mDisplayContent.mClosingApps.contains(activity)); } @SetupWindows(addWindows = W_INPUT_METHOD) @Test public void testImeInsetsFrozenFlag_resetWhenNoImeFocusableInActivity() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); makeWindowVisibleAndDrawn(app, mImeWindow); mDisplayContent.setImeLayeringTarget(app); mDisplayContent.setImeInputTarget(app); // Simulate app is closing and expect the last IME is shown and IME insets is frozen. mDisplayContent.mOpeningApps.clear(); app.mActivityRecord.commitVisibility(false, false); app.mActivityRecord.onWindowsGone(); assertTrue(app.mActivityRecord.mLastImeShown); assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Expect IME insets frozen state will reset when the activity has no IME focusable window. app.mActivityRecord.forAllWindows(w -> { w.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM; return true; }, true); app.mActivityRecord.commitVisibility(true, false); app.mActivityRecord.onWindowsVisible(); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); } @SetupWindows(addWindows = W_INPUT_METHOD) @Test public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer( mImeWindow, null, null); mImeWindow.getControllableInsetProvider().setServerVisible(true); InsetsSource imeSource = new InsetsSource(ID_IME, ime()); app.mAboveInsetsState.addSource(imeSource); mDisplayContent.setImeLayeringTarget(app); mDisplayContent.updateImeInputAndControlTarget(app); InsetsState state = app.getInsetsState(); assertFalse(state.getOrCreateSource(imeSource.getId(), ime()).isVisible()); assertTrue(state.getOrCreateSource(imeSource.getId(), ime()).getFrame().isEmpty()); // Simulate app is closing and expect IME insets is frozen. mDisplayContent.mOpeningApps.clear(); app.mActivityRecord.commitVisibility(false, false); app.mActivityRecord.onWindowsGone(); assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen app.mActivityRecord.commitVisibility(true, false); mDisplayContent.updateImeInputAndControlTarget(app); performSurfacePlacementAndWaitForWindowAnimator(); assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setVisible(true); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.mAboveInsetsState.addSource(imeSource); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); state = app.getInsetsState(); assertTrue(state.peekSource(ID_IME).isVisible()); assertEquals(state.peekSource(ID_IME).getFrame(), imeSource.getFrame()); } @SetupWindows(addWindows = { W_ACTIVITY, W_INPUT_METHOD }) @Test public void testImeInsetsFrozenFlag_noDispatchVisibleInsetsWhenAppNotRequest() throws RemoteException { final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).build(); mDisplayContent.getInsetsStateController().getImeSourceProvider().setWindowContainer( mImeWindow, null, null); mImeWindow.getControllableInsetProvider().setServerVisible(true); // Simulate app2 is closing and let app1 is visible to be IME targets. makeWindowVisibleAndDrawn(app1, mImeWindow); mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.updateImeInputAndControlTarget(app1); app2.mActivityRecord.commitVisibility(false, false); // app1 requests IME visible. app1.setRequestedVisibleTypes(ime(), ime()); mDisplayContent.getInsetsStateController().onRequestedVisibleTypesChanged(app1, null /* statsToken */); // Verify app1's IME insets is visible and app2's IME insets frozen flag set. assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible()); assertTrue(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Simulate switching to app2 to make it visible to be IME targets. spyOn(app2); spyOn(app2.mClient); spyOn(app2.getProcess()); ArgumentCaptor<InsetsState> insetsStateCaptor = ArgumentCaptor.forClass(InsetsState.class); doReturn(true).when(app2).isReadyToDispatchInsetsState(); mDisplayContent.setImeLayeringTarget(app2); app2.mActivityRecord.commitVisibility(true, false); mDisplayContent.updateImeInputAndControlTarget(app2); performSurfacePlacementAndWaitForWindowAnimator(); // Verify after unfreezing app2's IME insets state, we won't dispatch visible IME insets // to client if the app didn't request IME visible. assertFalse(app2.mActivityRecord.mImeInsetsFrozenUntilStartInput); verify(app2.getProcess(), atLeastOnce()).scheduleClientTransactionItem( isA(WindowStateResizeItem.class)); assertFalse(app2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime())); } @Test public void testImeInsetsFrozenFlag_multiWindowActivities() { final WindowToken imeToken = createTestWindowToken(TYPE_INPUT_METHOD, mDisplayContent); final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).setWindowToken( imeToken).build(); makeWindowVisibleAndDrawn(ime); // Create a split-screen root task with activity1 and activity 2. final Task task = new TaskBuilder(mSupervisor) .setCreateParentTask(true).setCreateActivity(true).build(); task.getRootTask().setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); final ActivityRecord activity1 = task.getTopNonFinishingActivity(); activity1.getTask().setResumedActivity(activity1, "testApp1"); final ActivityRecord activity2 = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_MULTI_WINDOW) .setCreateActivity(true).build().getTopMostActivity(); activity2.getTask().setResumedActivity(activity2, "testApp2"); activity2.getTask().setParent(task.getRootTask()); // Simulate activity1 and activity2 both have set mImeInsetsFrozenUntilStartInput when // invisible to user. activity1.mImeInsetsFrozenUntilStartInput = true; activity2.mImeInsetsFrozenUntilStartInput = true; final WindowState app1 = newWindowBuilder("app1", TYPE_APPLICATION).setWindowToken( activity1).build(); final WindowState app2 = newWindowBuilder("app2", TYPE_APPLICATION).setWindowToken( activity2).build(); makeWindowVisibleAndDrawn(app1, app2); final InsetsStateController controller = mDisplayContent.getInsetsStateController(); controller.getImeSourceProvider().setWindowContainer( ime, null, null); ime.getControllableInsetProvider().setServerVisible(true); // app1 starts input and expect IME insets for all activities in split-screen will be // frozen until the input started. mDisplayContent.setImeLayeringTarget(app1); mDisplayContent.updateImeInputAndControlTarget(app1); mDisplayContent.computeImeTarget(true /* updateImeTarget */); performSurfacePlacementAndWaitForWindowAnimator(); assertEquals(app1, mDisplayContent.getImeInputTarget()); assertFalse(activity1.mImeInsetsFrozenUntilStartInput); assertFalse(activity2.mImeInsetsFrozenUntilStartInput); app1.setRequestedVisibleTypes(ime()); controller.onRequestedVisibleTypesChanged(app1, null /* statsToken */); // Expect all activities in split-screen will get IME insets visible state assertTrue(app1.getInsetsState().peekSource(ID_IME).isVisible()); assertTrue(app2.getInsetsState().peekSource(ID_IME).isVisible()); } @Test public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() { final WindowState app = newWindowBuilder("app", TYPE_APPLICATION).build(); Loading