Initial commit of InputMethodStressTest.

This CL added a simple test of showing and hiding IME for 100 times.

TODOs:
1. Add more complicated flows (such as notification).
2. Check IME visibility in several points (WindowManager dump,
   SurfaceFlinger dump, etc), not just the inset that the app received.

Bug: 195468725
Test: atest InputMethodStressTest
Change-Id: I1959225a7396d17750d799e11c42eb1899fe5bb9
This commit is contained in:
Kohsuke Yatoh
2021-08-03 17:32:20 -07:00
parent 6018fff1e3
commit 08603e695f
6 changed files with 238 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
// Copyright (C) 2021 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 {
default_applicable_licenses: ["frameworks_base_license"],
}
android_test {
name: "InputMethodStressTest",
srcs: ["src/**/*.java"],
libs: ["android.test.runner"],
static_libs: [
"androidx.test.ext.junit",
"androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
"platform-test-annotations",
"truth-prebuilt",
],
test_suites: [
"general-tests",
"vts",
],
sdk_version: "31",
}

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.inputmethod.stresstest">
<application>
<activity android:name=".TestActivity"/>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.inputmethod.stresstest">
</instrumentation>
</manifest>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<configuration description="InputMethod integration/regression test">
<option name="test-suite-tag" value="apct" />
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="InputMethodStressTest.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.inputmethod.stresstest" />
</test>
</configuration>

View File

@@ -0,0 +1,3 @@
# Bug component: 34867
include /services/core/java/com/android/server/inputmethod/OWNERS

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2021 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.inputmethod.stresstest;
import static com.android.compatibility.common.util.SystemUtil.eventually;
import static com.google.common.truth.Truth.assertThat;
import android.app.Instrumentation;
import android.content.Intent;
import android.platform.test.annotations.RootPermissionTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@RootPermissionTest
@RunWith(AndroidJUnit4.class)
public class ImeOpenCloseStressTest {
private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
private static final int NUM_TEST_ITERATIONS = 100;
private Instrumentation mInstrumentation;
@Test
public void test() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
Intent intent = new Intent()
.setAction(Intent.ACTION_MAIN)
.setClass(mInstrumentation.getContext(), TestActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
TestActivity activity = (TestActivity) mInstrumentation.startActivitySync(intent);
eventually(() -> assertThat(callOnMainSync(activity::hasWindowFocus)).isTrue(), TIMEOUT);
for (int i = 0; i < NUM_TEST_ITERATIONS; i++) {
mInstrumentation.runOnMainSync(activity::showIme);
eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isTrue(), TIMEOUT);
mInstrumentation.runOnMainSync(activity::hideIme);
eventually(() -> assertThat(callOnMainSync(activity::isImeShown)).isFalse(), TIMEOUT);
}
}
private <V> V callOnMainSync(Callable<V> callable) {
AtomicReference<V> result = new AtomicReference<>();
AtomicReference<Exception> thrownException = new AtomicReference<>();
mInstrumentation.runOnMainSync(() -> {
try {
result.set(callable.call());
} catch (Exception e) {
thrownException.set(e);
}
});
if (thrownException.get() != null) {
throw new RuntimeException("Exception thrown from Main thread", thrownException.get());
}
return result.get();
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2021 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.inputmethod.stresstest;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import android.app.Activity;
import android.os.Bundle;
import android.view.WindowInsets;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
public class TestActivity extends Activity {
private EditText mEditText;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout rootView = new LinearLayout(this);
rootView.setOrientation(LinearLayout.VERTICAL);
mEditText = new EditText(this);
rootView.addView(mEditText, new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT));
setContentView(rootView);
}
public boolean hasWindowFocus() {
return mEditText.hasWindowFocus();
}
public boolean isImeShown() {
WindowInsets insets = mEditText.getRootWindowInsets();
return insets.isVisible(WindowInsets.Type.ime());
}
public void showIme() {
mEditText.requestFocus();
InputMethodManager imm = getSystemService(InputMethodManager.class);
imm.showSoftInput(mEditText, 0);
}
public void hideIme() {
InputMethodManager imm = getSystemService(InputMethodManager.class);
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
}
}