Use ActivityLaunchUtils to launch activities in UiAutomationTest.
The 3 tests in this class which launch an activity are ~5% flaky
which recently seems to be from leftover system dialogs from
other tests. ActivityLaunchUtils has more robust activity-launching
logic that goes to the home screen first and closes popups before
launching the activity, which has proven more reliable.
(Also removes unused UiAutomationTestSecondActivity)
Bug: 270722665
Bug: 270752780
Test: atest UiAutomationTest
Test: Used go/abtd to run 50x: http://go/abtd-run/L50700000960459736
Change-Id: Ib0cb75c4fc89318f341c63156254526e478b6cd8
diff --git a/tests/tests/uiautomation/Android.bp b/tests/tests/uiautomation/Android.bp
index 573c5d1..483a45f 100644
--- a/tests/tests/uiautomation/Android.bp
+++ b/tests/tests/uiautomation/Android.bp
@@ -26,6 +26,7 @@
],
static_libs: [
"CtsAccessibilityCommon",
+ "CtsAccessibilityServiceUtils",
"ctstestrunner-axt",
"truth-prebuilt",
"ub-uiautomator",
diff --git a/tests/tests/uiautomation/AndroidManifest.xml b/tests/tests/uiautomation/AndroidManifest.xml
index 5cf94fa..7bc1d55 100644
--- a/tests/tests/uiautomation/AndroidManifest.xml
+++ b/tests/tests/uiautomation/AndroidManifest.xml
@@ -24,17 +24,14 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS"/>
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<application android:theme="@android:style/Theme.Holo.NoActionBar"
android:requestLegacyExternalStorage="true">
<uses-library android:name="android.test.runner"/>
- <activity android:name="android.app.uiautomation.cts.UiAutomationTestFirstActivity"
- android:exported="true">
- </activity>
-
- <activity android:name="android.app.uiautomation.cts.UiAutomationTestSecondActivity"
+ <activity android:name="android.app.uiautomation.cts.UiAutomationTestActivity"
android:exported="true">
</activity>
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
index 34c6246..b5bfd63 100755
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTest.java
@@ -27,23 +27,20 @@
import android.accessibility.cts.common.InstrumentedAccessibilityService;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.cts.utils.ActivityLaunchUtils;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.os.Process;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
import android.view.FrameStats;
import android.view.KeyEvent;
import android.view.WindowAnimationFrameStats;
@@ -51,10 +48,10 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityWindowInfo;
import android.widget.ListView;
import androidx.test.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.UserHelper;
@@ -64,9 +61,9 @@
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
-import java.util.List;
import java.util.concurrent.TimeoutException;
/**
@@ -75,8 +72,6 @@
@RunWith(AndroidJUnit4.class)
public final class UiAutomationTest {
- private static final String TAG = UiAutomationTest.class.getSimpleName();
-
private static final long IDLE_QUIET_TIME_MS = 1000;
private static final long IDLE_WAIT_TIME_MS = 10 * 1000;
private static final long TIMEOUT_FOR_SERVICE_ENABLE_MS = 10 * 1000;
@@ -84,9 +79,15 @@
// Used to enable/disable accessibility services
private static final String COMPONENT_NAME_SEPARATOR = ":";
- @Rule
- public final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
+ private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
new AccessibilityDumpOnFailureRule();
+ private final ActivityTestRule<UiAutomationTestActivity> mActivityRule =
+ new ActivityTestRule<>(UiAutomationTestActivity.class, false, false);
+
+ @Rule
+ public final RuleChain mRuleChain = RuleChain
+ .outerRule(mActivityRule)
+ .around(mDumpOnFailureRule);
private final UserHelper mUserHelper = new UserHelper();
@@ -111,9 +112,6 @@
if (mUiAutomation != null) {
mUiAutomation.destroy();
}
- if (mActivity != null) {
- mActivity.finish();
- }
}
@AfterClass
@@ -202,6 +200,7 @@
@Test
public void testWindowContentFrameStats() throws Exception {
+ mUiAutomation = getInstrumentation().getUiAutomation();
final int windowId = startActivitySync();
// Clear stats to start with a clean slate.
assertWithMessage("clearWindowContentFrameStats(%s)", windowId)
@@ -224,9 +223,9 @@
stats.getFramePresentedTimeNano(stats.getFrameCount() - 1));
}
- @FlakyTest
@Test
public void testWindowContentFrameStats_NoAnimation() throws Exception {
+ mUiAutomation = getInstrumentation().getUiAutomation();
final int windowId = startActivitySync();
// Clear stats to start with a clean slate.
assertWithMessage("clearWindowContentFrameStats(%s)", windowId)
@@ -517,58 +516,15 @@
fail(message);
}
- private int findAppWindowId(List<AccessibilityWindowInfo> windows, Activity activity) {
- final StringBuilder activityTitle = new StringBuilder();
- getInstrumentation().runOnMainSync(() -> activityTitle.append(activity.getTitle()));
- final int windowCount = windows.size();
- for (int i = 0; i < windowCount; i++) {
- AccessibilityWindowInfo window = windows.get(i);
- int displayId = window.getDisplayId();
- CharSequence title = window.getTitle();
- Log.v(TAG, "findAppWindowId()#" + i + ": title=" + title + ", display=" + displayId);
- if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION
- && TextUtils.equals(title, activityTitle)) {
- // TODO(b/271188189): once working, remove false or whole statement below
- if (false && displayId != mUserHelper.getMainDisplayId()) {
- continue;
- }
- return window.getId();
- }
- }
- return -1;
- }
-
private Instrumentation getInstrumentation() {
return InstrumentationRegistry.getInstrumentation();
}
/** Start an activity and return its accessibility window id. */
private int startActivitySync() throws Exception {
- mUiAutomation = getInstrumentation().getUiAutomation();
- AccessibilityServiceInfo info = mUiAutomation.getServiceInfo();
- info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
- mUiAutomation.setServiceInfo(info);
-
- // Start an activity.
- Intent intent = new Intent(getInstrumentation().getContext(),
- UiAutomationTestFirstActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mActivity = getInstrumentation().startActivitySync(intent,
- mUserHelper.getActivityOptions().toBundle());
-
- // Wait for things to settle.
- mUiAutomation.waitForIdle(IDLE_QUIET_TIME_MS, IDLE_WAIT_TIME_MS);
-
- // Wait for Activity draw finish
- getInstrumentation().waitForIdleSync();
-
- // Find the application window.
- List<AccessibilityWindowInfo> windows = mUiAutomation.getWindows();
- assertWithMessage("UiAutomation.getWindows()").that(windows).isNotEmpty();
- int windowId = findAppWindowId(windows, mActivity);
- assertWithMessage("window id for activity %s (windows=%s)", mActivity, windows)
- .that(windowId).isAtLeast(0);
-
- return windowId;
+ mActivity = ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen(
+ getInstrumentation(), mUiAutomation, mActivityRule);
+ return ActivityLaunchUtils.findWindowByTitle(mUiAutomation,
+ ActivityLaunchUtils.getActivityTitle(getInstrumentation(), mActivity)).getId();
}
}
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestActivity.java
similarity index 60%
rename from tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
rename to tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestActivity.java
index 8686e45..7c9fe97 100644
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestFirstActivity.java
+++ b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestActivity.java
@@ -1,18 +1,19 @@
/*
-* Copyright (C) 2014 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.
-*/
+ * Copyright (C) 2023 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 android.app.uiautomation.cts;
@@ -26,8 +27,8 @@
/**
* Activity for testing the UiAutomation APIs.
*/
-public class UiAutomationTestFirstActivity extends Activity {
- private static final String TAG = UiAutomationTestFirstActivity.class.getSimpleName();
+public class UiAutomationTestActivity extends Activity {
+ private static final String TAG = UiAutomationTestActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
diff --git a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java b/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
deleted file mode 100644
index 6c4b04c..0000000
--- a/tests/tests/uiautomation/src/android/app/uiautomation/cts/UiAutomationTestSecondActivity.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-* Copyright (C) 2014 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 android.app.uiautomation.cts;
-
-import android.app.Activity;
-import android.app.uiautomation.cts.R;
-import android.os.Bundle;
-import android.view.WindowManager;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-
-/**
-* Activity for testing the UiAutomation APIs.
-*/
-public class UiAutomationTestSecondActivity extends Activity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
- setContentView(R.layout.ui_automation_test);
-
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
-
- String[] cheeses = getResources().getStringArray(R.array.some_cheeses);
- ArrayAdapter<String> cheeseAdapter = new ArrayAdapter<String>(this,
- android.R.layout.simple_list_item_1, cheeses);
-
- ListView listView = (ListView) findViewById(R.id.list_view);
- listView.setAdapter(cheeseAdapter);
- }
-}