summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Cosmin Băieș <cosminbaies@google.com> 2023-11-10 16:55:23 +0100
committer Cosmin Băieș <cosminbaies@google.com> 2023-11-16 11:24:48 +0100
commit56beb96e7000324616857971a60df5e883bee3d1 (patch)
treea43e5cc38f1c4c2d05f213a406499a350e773a77
parent02b3211ef962f80aa071c84afe69aec8d58392cf (diff)
Add unit tests for hiding the IME nav bar
This adds unit tests for the newly added IME captio bar insetsSource, and for the code paths through InsetsController for showing and hiding the IME nav bar. Bug: 310199730 Test: atest FrameworksImeTests:InputMethodServiceTest#testShowHideImeNavigationBar_doesDrawImeNavBar FrameworksImeTests:InputMethodServiceTest#testShowHideImeNavigationBar_doesNotDrawImeNavBar InsetsSourceTest#testCalculateInsets_imeCaptionBar Change-Id: I84accc9666eef2bdeaa7073acd7f364938770b65
-rw-r--r--core/java/android/inputmethodservice/AbstractInputMethodService.java5
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java11
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java17
-rw-r--r--core/java/android/view/InsetsSource.java3
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceTest.java16
-rw-r--r--services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java78
6 files changed, 128 insertions, 2 deletions
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index f16e2439f3f4..e2d215ebfed4 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -33,6 +33,8 @@ import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodSession;
import android.window.WindowProviderService;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -72,8 +74,9 @@ public abstract class AbstractInputMethodService extends WindowProviderService
* {@code null} if {@link #onCreateInputMethodInterface()} is not yet called.
* @hide
*/
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
@Nullable
- protected final InputMethod getInputMethodInternal() {
+ public final InputMethod getInputMethodInternal() {
return mInputMethod;
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ba80811e198c..18d3e5e02fbe 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -149,6 +149,7 @@ import android.window.OnBackInvokedDispatcher;
import android.window.WindowMetricsHelper;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.IInlineSuggestionsRequestCallback;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethod;
@@ -3997,6 +3998,16 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Returns whether the IME navigation bar is currently shown, for testing purposes.
+ *
+ * @hide
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public final boolean isImeNavigationBarShownForTesting() {
+ return mNavigationBarController.isShown();
+ }
+
+ /**
* Used to inject custom {@link InputMethodServiceInternal}.
*
* @return the {@link InputMethodServiceInternal} to be used.
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index 8be4c5858694..9c55b0ee0623 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -77,6 +77,10 @@ final class NavigationBarController {
default void onNavButtonFlagsChanged(@InputMethodNavButtonFlags int navButtonFlags) {
}
+ default boolean isShown() {
+ return false;
+ }
+
default String toDebugString() {
return "No-op implementation";
}
@@ -117,6 +121,13 @@ final class NavigationBarController {
mImpl.onNavButtonFlagsChanged(navButtonFlags);
}
+ /**
+ * Returns whether the IME navigation bar is currently shown.
+ */
+ boolean isShown() {
+ return mImpl.isShown();
+ }
+
String toDebugString() {
return mImpl.toDebugString();
}
@@ -561,6 +572,12 @@ final class NavigationBarController {
}
@Override
+ public boolean isShown() {
+ return mNavigationBarFrame != null
+ && mNavigationBarFrame.getVisibility() == View.VISIBLE;
+ }
+
+ @Override
public String toDebugString() {
return "{mImeDrawsImeNavBar=" + mImeDrawsImeNavBar
+ " mNavigationBarFrame=" + mNavigationBarFrame
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 1acc384b18da..cabab6c80bf5 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -49,8 +49,9 @@ public class InsetsSource implements Parcelable {
/** The insets source ID of IME */
public static final int ID_IME = createId(null, 0, ime());
+
/** The insets source ID of the IME caption bar ("fake" IME navigation bar). */
- static final int ID_IME_CAPTION_BAR =
+ public static final int ID_IME_CAPTION_BAR =
InsetsSource.createId(null /* owner */, 1 /* index */, captionBar());
/**
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 9595332afc6c..e1bcd4a0727b 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsSource.ID_IME_CAPTION_BAR;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.SIZE;
@@ -52,12 +53,15 @@ public class InsetsSourceTest {
private final InsetsSource mSource = new InsetsSource(0 /* id */, navigationBars());
private final InsetsSource mImeSource = new InsetsSource(1 /* id */, ime());
+ private final InsetsSource mImeCaptionSource = new InsetsSource(
+ ID_IME_CAPTION_BAR, captionBar());
private final InsetsSource mCaptionSource = new InsetsSource(2 /* id */, captionBar());
@Before
public void setUp() {
mSource.setVisible(true);
mImeSource.setVisible(true);
+ mImeCaptionSource.setVisible(true);
mCaptionSource.setVisible(true);
}
@@ -110,6 +114,18 @@ public class InsetsSourceTest {
}
@Test
+ public void testCalculateInsets_imeCaptionBar() {
+ mImeCaptionSource.setFrame(new Rect(0, 400, 500, 500));
+ Insets insets = mImeCaptionSource.calculateInsets(new Rect(0, 0, 500, 500), false);
+ assertEquals(Insets.of(0, 0, 0, 100), insets);
+
+ // Place caption bar at top; IME caption bar must always return bottom insets
+ mImeCaptionSource.setFrame(new Rect(0, 0, 500, 100));
+ insets = mImeCaptionSource.calculateInsets(new Rect(0, 0, 500, 500), false);
+ assertEquals(Insets.of(0, 0, 0, 100), insets);
+ }
+
+ @Test
public void testCalculateInsets_caption_resizing() {
mCaptionSource.setFrame(new Rect(0, 0, 100, 100));
Insets insets = mCaptionSource.calculateInsets(new Rect(0, 0, 200, 200), false);
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index b63a58a96b8c..21342783b79c 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -25,6 +25,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
import android.app.Instrumentation;
import android.content.Context;
@@ -48,6 +49,7 @@ import androidx.test.platform.app.InstrumentationRegistry;
import com.android.apps.inputmethod.simpleime.ims.InputMethodServiceWrapper;
import com.android.apps.inputmethod.simpleime.testing.TestActivity;
+import com.android.internal.inputmethod.InputMethodNavButtonFlags;
import org.junit.After;
import org.junit.Before;
@@ -635,6 +637,82 @@ public class InputMethodServiceTest {
.getRootWindowInsets().getInsetsIgnoringVisibility(captionBar()));
}
+ /**
+ * This checks that trying to show and hide the navigation bar takes effect
+ * when the IME does draw the IME navigation bar.
+ */
+ @Test
+ public void testShowHideImeNavigationBar_doesDrawImeNavBar() throws Exception {
+ boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ assumeTrue("Must have a navigation bar", hasNavigationBar);
+
+ setShowImeWithHardKeyboard(true /* enabled */);
+
+ // Show IME
+ verifyInputViewStatusOnMainSync(
+ () -> {
+ mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
+ InputMethodNavButtonFlags.IME_DRAWS_IME_NAV_BAR
+ | InputMethodNavButtonFlags.SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN
+ );
+ assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue();
+ },
+ true /* expected */,
+ true /* inputViewStarted */);
+ assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue();
+
+ // Try to hide IME nav bar
+ mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
+ .getInsetsController().hide(captionBar()));
+ mInstrumentation.waitForIdleSync();
+ assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+
+ // Try to show IME nav bar
+ mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
+ .getInsetsController().show(captionBar()));
+ mInstrumentation.waitForIdleSync();
+ assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isTrue();
+ }
+ /**
+ * This checks that trying to show and hide the navigation bar has no effect
+ * when the IME does not draw the IME navigation bar.
+ *
+ * Note: The IME navigation bar is *never* visible in 3 button navigation mode.
+ */
+ @Test
+ public void testShowHideImeNavigationBar_doesNotDrawImeNavBar() throws Exception {
+ boolean hasNavigationBar = WindowManagerGlobal.getWindowManagerService()
+ .hasNavigationBar(mInputMethodService.getDisplayId());
+ assumeTrue("Must have a navigation bar", hasNavigationBar);
+
+ setShowImeWithHardKeyboard(true /* enabled */);
+
+ // Show IME
+ verifyInputViewStatusOnMainSync(() -> {
+ mInputMethodService.getInputMethodInternal().onNavButtonFlagsChanged(
+ 0 /* navButtonFlags */);
+ assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue();
+ },
+ true /* expected */,
+ true /* inputViewStarted */);
+ assertThat(mInputMethodService.isInputViewShown()).isTrue();
+ assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+
+ // Try to hide IME nav bar
+ mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
+ .getInsetsController().hide(captionBar()));
+ mInstrumentation.waitForIdleSync();
+ assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+
+ // Try to show IME nav bar
+ mInstrumentation.runOnMainSync(() -> mInputMethodService.getWindow().getWindow()
+ .getInsetsController().show(captionBar()));
+ mInstrumentation.waitForIdleSync();
+ assertThat(mInputMethodService.isImeNavigationBarShownForTesting()).isFalse();
+ }
+
private void verifyInputViewStatus(
Runnable runnable, boolean expected, boolean inputViewStarted)
throws InterruptedException {