diff options
4 files changed, 59 insertions, 16 deletions
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index 31143a559060..81cecf1b3642 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -341,7 +341,7 @@ public class DreamService extends Service implements Window.Callback { */ public interface WakefulHandler { /** Posts a {@link Runnable} to be ran on the underlying {@link Handler}. */ - void post(Runnable r); + void postIfNeeded(Runnable r); /** * Returns the underlying {@link Handler}. Should only be used for passing the handler into @@ -386,8 +386,10 @@ public class DreamService extends Service implements Window.Callback { } @Override - public void post(Runnable r) { - if (mWakeLock != null) { + public void postIfNeeded(Runnable r) { + if (mHandler.getLooper().isCurrentThread()) { + r.run(); + } else if (mWakeLock != null) { mHandler.post(mWakeLock.wrap(r)); } else { mHandler.post(r); @@ -995,17 +997,17 @@ public class DreamService extends Service implements Window.Callback { } } - private void post(Runnable runnable) { + private void postIfNeeded(Runnable runnable) { // The handler is based on the populated context is not ready at construction time. // therefore we fetch on demand. - mInjector.getWakefulHandler().post(runnable); + mInjector.getWakefulHandler().postIfNeeded(runnable); } /** * Updates doze state. Note that this must be called on the mHandler. */ private void updateDoze() { - post(() -> { + postIfNeeded(() -> { if (mDreamToken == null) { Slog.w(mTag, "Updating doze without a dream token."); return; @@ -1047,7 +1049,7 @@ public class DreamService extends Service implements Window.Callback { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public void stopDozing() { - post(() -> { + postIfNeeded(() -> { if (mDreamToken == null) { return; } @@ -1290,7 +1292,7 @@ public class DreamService extends Service implements Window.Callback { final long token = Binder.clearCallingIdentity(); try { // Simply finish dream when exit is requested. - post(() -> finishInternal()); + postIfNeeded(() -> finishInternal()); } finally { Binder.restoreCallingIdentity(token); } @@ -1396,7 +1398,7 @@ public class DreamService extends Service implements Window.Callback { * </p> */ public final void finish() { - post(this::finishInternal); + postIfNeeded(this::finishInternal); } private void finishInternal() { @@ -1458,7 +1460,7 @@ public class DreamService extends Service implements Window.Callback { * </p> */ public final void wakeUp() { - post(()-> wakeUp(false)); + postIfNeeded(()-> wakeUp(false)); } /** @@ -1964,7 +1966,7 @@ public class DreamService extends Service implements Window.Callback { return; } - service.post(() -> consumer.accept(service)); + service.postIfNeeded(() -> consumer.accept(service)); } @Override diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index f2bc909bd64b..c87c2501d3b1 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -326,9 +326,12 @@ final class ImeInsetsSourceProvider extends InsetsSourceProvider { // IME input target to update IME request state. For example, switch from a task // with showing IME to a split-screen task without showing IME. InputTarget imeInputTarget = mDisplayContent.getImeInputTarget(); - if (imeInputTarget != target && imeInputTarget != null) { - // The controlTarget should be updated with the visibility of the - // current IME input target. + if (imeInputTarget != target && imeInputTarget != null + && imeInputTarget.isRequestedVisible(WindowInsets.Type.ime()) + != target.isRequestedVisible(WindowInsets.Type.ime())) { + // Only update the controlTarget, if it has a different requested visibility + // than the imeInputTarget. Otherwise, updateClientVisibility won't invoke + // the listener, as nothing changed. reportImeInputTargetStateToControlTarget(imeInputTarget, target, statsToken); } else { diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java index a16d463cae71..03d4ab8e4982 100644 --- a/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java +++ b/services/tests/dreamservicetests/src/com/android/server/dreams/TestDreamEnvironment.java @@ -201,7 +201,7 @@ public class TestDreamEnvironment { doAnswer(invocation -> { ((Runnable) invocation.getArgument(0)).run(); return null; - }).when(mWakefulHandler).post(any()); + }).when(mWakefulHandler).postIfNeeded(any()); } @Override public void init(Context context) { diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java index aa794b2d071d..bc172c120283 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java @@ -25,6 +25,7 @@ import static com.android.server.wm.WindowStateAnimator.NO_SURFACE; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; @@ -245,13 +246,50 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase { assertTrue(inputTarget.isRequestedVisible(WindowInsets.Type.ime())); assertFalse(controlTarget.isRequestedVisible(WindowInsets.Type.ime())); - mImeProvider.updateControlForTarget(controlTarget, true /* force */, null /* statsToken */); + mImeProvider.updateControlForTarget(controlTarget, true /* force */, + ImeTracker.Token.empty()); verify(displayWindowInsetsController, times(1)).setImeInputTargetRequestedVisibility( eq(true), any()); } @Test @RequiresFlagsEnabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER) + public void testUpdateControlForTarget_remoteInsetsControlTargetUnchanged() + throws RemoteException { + final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).build(); + mImeProvider.setWindowContainer(ime, null, null); + final WindowState inputTarget = newWindowBuilder("app", TYPE_APPLICATION).build(); + final var displayWindowInsetsController = spy(createDisplayWindowInsetsController()); + mDisplayContent.setRemoteInsetsController(displayWindowInsetsController); + final var controlTarget = mDisplayContent.mRemoteInsetsControlTarget; + mDisplayContent.setImeInputTarget(inputTarget); + mDisplayContent.setImeControlTarget(controlTarget); + + // Test for visible + inputTarget.setRequestedVisibleTypes(WindowInsets.Type.ime()); + controlTarget.updateRequestedVisibleTypes(WindowInsets.Type.ime(), WindowInsets.Type.ime()); + clearInvocations(mDisplayContent); + assertTrue(inputTarget.isRequestedVisible(WindowInsets.Type.ime())); + assertTrue((controlTarget.isRequestedVisible(WindowInsets.Type.ime()))); + mImeProvider.updateControlForTarget(controlTarget, true /* force */, + ImeTracker.Token.empty()); + verify(displayWindowInsetsController, never()).setImeInputTargetRequestedVisibility( + anyBoolean(), any()); + + // Test for not visible + inputTarget.setRequestedVisibleTypes(0); + controlTarget.updateRequestedVisibleTypes(0 /* visibleTypes */, WindowInsets.Type.ime()); + clearInvocations(mDisplayContent); + assertFalse(inputTarget.isRequestedVisible(WindowInsets.Type.ime())); + assertFalse((controlTarget.isRequestedVisible(WindowInsets.Type.ime()))); + mImeProvider.updateControlForTarget(controlTarget, true /* force */, + ImeTracker.Token.empty()); + verify(displayWindowInsetsController, never()).setImeInputTargetRequestedVisibility( + anyBoolean(), any()); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_REFACTOR_INSETS_CONTROLLER) public void testOnPostLayout_resetServerVisibilityWhenImeIsNotDrawn() { final WindowState ime = newWindowBuilder("ime", TYPE_INPUT_METHOD).build(); final WindowState inputTarget = newWindowBuilder("app", TYPE_APPLICATION).build(); |