Merge "CTS for ForegroundServiceAccessAppOpOccurred atom" into rvc-dev
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
index e5300ab..2a322aa 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp22/res/values/strings.xml
@@ -5,4 +5,5 @@
<string name="Ask">Ask every time</string>
<string name="Allow">Allow</string>
<string name="AllowAll">Allow all the time</string>
+ <string name="AllowForeground">Allow only while using the app</string>
</resources>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
index e5300ab..2a322aa 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/res/values/strings.xml
@@ -5,4 +5,5 @@
<string name="Ask">Ask every time</string>
<string name="Allow">Allow</string>
<string name="AllowAll">Allow all the time</string>
+ <string name="AllowForeground">Allow only while using the app</string>
</resources>
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
index 8b5630c..da6e44b 100755
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/BasePermissionsTest.java
@@ -16,18 +16,16 @@
package com.android.cts.usepermission;
-import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
import static com.android.compatibility.common.util.UiAutomatorUtils.getUiDevice;
+import static com.android.compatibility.common.util.UiAutomatorUtils.waitFindObject;
import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
import android.Manifest;
import android.app.Activity;
@@ -36,20 +34,16 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
-import android.icu.text.CaseMap;
import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.Settings;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
-import android.support.test.uiautomator.Until;
import android.text.Spanned;
import android.text.style.ClickableSpan;
import android.util.ArrayMap;
@@ -67,7 +61,6 @@
import com.android.compatibility.common.util.UiDumpUtils;
import junit.framework.Assert;
-import junit.framework.TestCase;
import org.junit.Before;
import org.junit.runner.RunWith;
@@ -76,7 +69,6 @@
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.regex.Pattern;
@@ -449,19 +441,27 @@
waitForIdle();
}
- final boolean wasGranted = isTv() ? false : !(waitFindObject(byText(R.string.Deny)).isChecked() || (!legacyApp && waitFindObject(byText(R.string.Ask)).isChecked()));
+ final boolean wasGranted = isTv()
+ ? false
+ : !(waitFindObject(byText(R.string.Deny)).isChecked()
+ || (legacyApp
+ && hasAskButton(permission)
+ && waitFindObject(byText(R.string.Ask)).isChecked()));
boolean alreadyChecked = false;
if (isTv()) {
waitFindObject(By.text(permissionLabel)).click();
} else if (state == STATE_ALLOWED) {
- UiObject2 object = waitFindObject(byText(R.string.Allow));
+ UiObject2 object = waitFindObject(byText(
+ showsForegroundOnlyButton(permission)
+ ? R.string.AllowForeground
+ : R.string.Allow));
alreadyChecked = object.isChecked();
if (!alreadyChecked) {
object.click();
}
} else if (state == STATE_DENIED){
UiObject2 object;
- if (legacyApp) {
+ if (legacyApp || !hasAskButton(permission)) {
object = waitFindObject(byText(R.string.Deny));
} else {
object = waitFindObject(byText(R.string.Ask));
@@ -529,6 +529,19 @@
return mPlatformResources.getString(resourceId);
}
+ private boolean hasAskButton(String permission) {
+ return Manifest.permission.CAMERA.equals(permission)
+ || Manifest.permission.RECORD_AUDIO.equals(permission)
+ || Manifest.permission.ACCESS_FINE_LOCATION.equals(permission)
+ || Manifest.permission.ACCESS_COARSE_LOCATION.equals(permission)
+ || Manifest.permission.ACCESS_BACKGROUND_LOCATION.equals(permission);
+ }
+
+ private boolean showsForegroundOnlyButton(String permission) {
+ return Manifest.permission.CAMERA.equals(permission)
+ || Manifest.permission.RECORD_AUDIO.equals(permission);
+ }
+
private void startActivity(final Intent intent) throws Exception {
getInstrumentation().getUiAutomation().executeAndWaitForEvent(
() -> {
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
index a958816..3be949d 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionApp23/src/com/android/cts/usepermission/UsePermissionTest23.java
@@ -285,9 +285,9 @@
public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part1() throws Exception {
// Make sure we don't have the permission
assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
- .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+ .checkSelfPermission(Manifest.permission.CAMERA));
- String[] permissions = new String[] {Manifest.permission.READ_CALENDAR};
+ String[] permissions = new String[] {Manifest.permission.CAMERA};
// Request the permission and deny it
BasePermissionActivity.Result firstResult = requestPermissions(permissions, () -> {
@@ -300,7 +300,7 @@
// Request the permission and choose don't ask again
BasePermissionActivity.Result secondResult = requestPermissions(new String[]{
- Manifest.permission.READ_CALENDAR}, () -> {
+ Manifest.permission.CAMERA}, () -> {
denyWithPrejudice();
getUiDevice().waitForIdle();
});
@@ -309,8 +309,8 @@
assertPermissionRequestResult(secondResult, permissions, new boolean[] {false});
// Clear the denial with prejudice
- grantPermission(Manifest.permission.READ_CALENDAR);
- revokePermission(Manifest.permission.READ_CALENDAR);
+ grantPermission(Manifest.permission.CAMERA);
+ revokePermission(Manifest.permission.CAMERA);
// We just committed a suicide by revoking the permission. See part2 below...
}
@@ -319,17 +319,17 @@
public void testGrantPreviouslyRevokedWithPrejudiceShowsPrompt_part2() throws Exception {
// Make sure we don't have the permission
assertEquals(PackageManager.PERMISSION_DENIED, getInstrumentation().getContext()
- .checkSelfPermission(Manifest.permission.READ_CALENDAR));
+ .checkSelfPermission(Manifest.permission.CAMERA));
// Request the permission and allow it
BasePermissionActivity.Result thirdResult = requestPermissions(new String[]{
- Manifest.permission.READ_CALENDAR}, () -> {
- clickAllowButton();
+ Manifest.permission.CAMERA}, () -> {
+ clickAllowForegroundButton();
getUiDevice().waitForIdle();
});
// Make sure the permission is granted
- assertPermissionRequestResult(thirdResult, new String[] {Manifest.permission.READ_CALENDAR},
+ assertPermissionRequestResult(thirdResult, new String[] {Manifest.permission.CAMERA},
new boolean[] {true});
}
diff --git a/hostsidetests/incident/Android.bp b/hostsidetests/incident/Android.bp
index 1589078..3a3801b 100644
--- a/hostsidetests/incident/Android.bp
+++ b/hostsidetests/incident/Android.bp
@@ -26,5 +26,6 @@
"tradefed",
"compatibility-host-util",
"platformprotos",
+ "truth-prebuilt",
],
}
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/Android.bp b/hostsidetests/incident/apps/graphicsstatsapp/Android.bp
index 52b5c74..c64f8a8 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/Android.bp
+++ b/hostsidetests/incident/apps/graphicsstatsapp/Android.bp
@@ -24,6 +24,7 @@
"ctstestrunner-axt",
"compatibility-device-util-axt",
"androidx.legacy_legacy-support-v4",
+ "truth-prebuilt",
],
sdk_version: "test_current",
// tag this module as a cts test artifact
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml b/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
index be9d645..88e1eaf 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
+++ b/hostsidetests/incident/apps/graphicsstatsapp/AndroidManifest.xml
@@ -22,6 +22,8 @@
<uses-library android:name="android.test.runner" />
<activity android:name=".DrawFramesActivity"
android:label="GraphicsStats Test Activity"
+ android:screenOrientation="locked"
+ android:resizeableActivity="false"
android:theme="@style/DefaultTheme"/>
</application>
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
index 1bbc601..fd1206f 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
+++ b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/DrawFramesActivity.java
@@ -144,10 +144,6 @@
}
}
- public void drawFrames(final int frameCount) throws InterruptedException, TimeoutException {
- drawFrames(new int[frameCount]);
- }
-
public void waitForReady() throws InterruptedException, TimeoutException {
if (!mReady.await(4, TimeUnit.SECONDS)) {
throw new TimeoutException();
diff --git a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
index 56413f8..1a93309 100644
--- a/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
+++ b/hostsidetests/incident/apps/graphicsstatsapp/src/com/android/server/cts/device/graphicsstats/SimpleDrawFrameTests.java
@@ -15,13 +15,14 @@
*/
package com.android.server.cts.device.graphicsstats;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.google.common.collect.Range;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,25 +39,37 @@
public ActivityTestRule<DrawFramesActivity> mActivityRule =
new ActivityTestRule<>(DrawFramesActivity.class);
- @Test
- public void testDrawTenFrames() throws Throwable {
+ void runTest(final int frameCount) throws Throwable {
+ runTest(new int[frameCount]);
+ }
+
+ void runTest(final int[] framesToDraw) throws Throwable {
DrawFramesActivity activity = mActivityRule.getActivity();
activity.waitForReady();
int initialFrames = activity.getRenderedFramesCount();
- assertTrue(initialFrames < 5);
- assertEquals(0, activity.getDroppedReportsCount());
- activity.drawFrames(10);
- assertEquals(initialFrames + 10, activity.getRenderedFramesCount());
- assertEquals(0, activity.getDroppedReportsCount());
+ assertThat(initialFrames).isLessThan(5);
+ assertThat(activity.getDroppedReportsCount()).isEqualTo(0);
+ activity.drawFrames(framesToDraw);
+ final int expectedFrameCount = initialFrames + framesToDraw.length;
+ assertThat(activity.getRenderedFramesCount()).isIn(
+ Range.closedOpen(expectedFrameCount, expectedFrameCount + 5));
+ assertThat(activity.getDroppedReportsCount()).isEqualTo(0);
+ }
+
+ @Test
+ public void testNothing() throws Throwable {
+ DrawFramesActivity activity = mActivityRule.getActivity();
+ activity.waitForReady();
+ activity.drawFrames(new int[10]);
+ }
+
+ @Test
+ public void testDrawTenFrames() throws Throwable {
+ runTest(10);
}
@Test
public void testDrawJankyFrames() throws Throwable {
- DrawFramesActivity activity = mActivityRule.getActivity();
- activity.waitForReady();
- int initialFrames = activity.getRenderedFramesCount();
- assertTrue(initialFrames < 5);
- assertEquals(0, activity.getDroppedReportsCount());
int[] frames = new int[50];
for (int i = 0; i < 10; i++) {
int indx = i * 5;
@@ -65,26 +78,17 @@
frames[indx + 2] = DrawFramesActivity.FRAME_JANK_LAYOUT;
frames[indx + 3] = DrawFramesActivity.FRAME_JANK_MISS_VSYNC;
}
- activity.drawFrames(frames);
- assertEquals(initialFrames + 50, activity.getRenderedFramesCount());
- assertEquals(0, activity.getDroppedReportsCount());
+ runTest(frames);
}
@Test
public void testDrawDaveyFrames() throws Throwable {
- DrawFramesActivity activity = mActivityRule.getActivity();
- activity.waitForReady();
- int initialFrames = activity.getRenderedFramesCount();
- assertTrue(initialFrames < 5);
- assertEquals(0, activity.getDroppedReportsCount());
int[] frames = new int[40];
for (int i = 0; i < 10; i++) {
int indx = i * 4;
frames[indx] = DrawFramesActivity.FRAME_JANK_DAVEY;
frames[indx + 2] = DrawFramesActivity.FRAME_JANK_DAVEY_JR;
}
- activity.drawFrames(frames);
- assertEquals(initialFrames + 40, activity.getRenderedFramesCount());
- assertEquals(0, activity.getDroppedReportsCount());
+ runTest(frames);
}
}
diff --git a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
index ea1f803..843531d 100644
--- a/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/GraphicsStatsValidationTest.java
@@ -15,12 +15,14 @@
*/
package com.android.server.cts;
+import static com.google.common.truth.Truth.assertThat;
+
import android.service.GraphicsStatsHistogramBucketProto;
import android.service.GraphicsStatsJankSummaryProto;
import android.service.GraphicsStatsProto;
import android.service.GraphicsStatsServiceDumpProto;
-import com.android.tradefed.log.LogUtil.CLog;
+import com.google.common.collect.Range;
import java.util.ArrayList;
import java.util.Date;
@@ -46,7 +48,7 @@
turnScreenOn();
// Ensure that we have a starting point for our stats
runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".SimpleDrawFrameTests",
- "testDrawTenFrames");
+ "testNothing");
// Kill to ensure that stats persist/merge across process death
killTestApp();
}
@@ -91,24 +93,24 @@
int jankyDelta = summaryAfter.getJankyFrames() - summaryBefore.getJankyFrames();
// Test draws 50 frames + 1 initial frame. We expect 40 of them to be janky,
// 10 of each of ANIMATION, LAYOUT, RECORD_DRAW, and MISSED_VSYNC
- assertTrue(frameDelta < 55);
- assertTrue(jankyDelta >= 40);
- assertTrue(jankyDelta < 45);
+
+ assertThat(frameDelta).isAtLeast(50);
+ assertThat(jankyDelta).isAtLeast(40);
+ assertThat(jankyDelta).isLessThan(45);
// Although our current stats don't distinguish between ANIMATION, LAYOUT, and RECORD_DRAW
// so this will just be slowUi +30
int slowUiDelta = summaryAfter.getSlowUiThreadCount() - summaryBefore.getSlowUiThreadCount();
- assertTrue(slowUiDelta >= 30);
+ assertThat(slowUiDelta).isAtLeast(28);
int missedVsyncDelta = summaryAfter.getMissedVsyncCount()
- summaryBefore.getMissedVsyncCount();
- assertTrue(missedVsyncDelta >= 10);
- assertTrue(missedVsyncDelta <= 11);
+ assertThat(missedVsyncDelta).isIn(Range.closed(10, 11));
int veryJankyDelta = countFramesAbove(statsAfter, 60) - countFramesAbove(statsBefore, 60);
// The 1st frame could be >40ms, but nothing after that should be
- assertTrue(veryJankyDelta <= 2);
+ assertThat(veryJankyDelta).isAtMost(2);
int noGPUJank = countGPUFramesAbove(statsAfter, 60) - countGPUFramesAbove(statsBefore, 60);
- assertTrue(noGPUJank == 0);
+ assertThat(noGPUJank).isEqualTo(0);
}
public void testDaveyDrawFrame() throws Exception {
@@ -123,13 +125,12 @@
int jankyDelta = summaryAfter.getJankyFrames() - summaryBefore.getJankyFrames();
// Test draws 40 frames + 1 initial frame. We expect 10 of them to be daveys,
// 10 of them to be daveyjrs, and 20 to jank from missed vsync (from the davey/daveyjr prior to it)
- assertTrue(frameDelta < 45);
- assertTrue(jankyDelta >= 20);
- assertTrue(jankyDelta < 25);
+ assertThat(frameDelta).isAtLeast(40);
+ assertThat(jankyDelta).isAtLeast(20);
+ assertThat(jankyDelta).isLessThan(25);
int gt150msDelta = countFramesAbove(statsAfter, 150) - countFramesAbove(statsBefore, 150);
- assertTrue(gt150msDelta >= 20); // 10 davey jrs + 10 daveys + maybe first 2 frames
- assertTrue(gt150msDelta <= 22);
+ assertThat(gt150msDelta).isIn(Range.closed(20, 22));
int gt700msDelta = countFramesAbove(statsAfter, 700) - countFramesAbove(statsBefore, 700);
assertEquals(10, gt700msDelta); // 10 daveys
}
@@ -139,10 +140,10 @@
}
private GraphicsStatsProto[] doRunDrawTest(String testName, boolean canRetry) throws Exception {
- GraphicsStatsProto statsBefore = fetchStats();
- assertNotNull(statsBefore);
killTestApp();
turnScreenOn();
+ GraphicsStatsProto statsBefore = fetchStats();
+ assertNotNull(statsBefore);
runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".SimpleDrawFrameTests", testName);
killTestApp();
GraphicsStatsProto statsAfter = fetchStats();
diff --git a/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp b/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp
index ef0a5cb..1a7e5b6 100755
--- a/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/Bug-115739809/poc.cpp
@@ -49,6 +49,8 @@
case InputMessage::Type::KEY: {
// uint32_t seq
outMsg->body.key.seq = msg.body.key.seq;
+ // int32_t eventId
+ outMsg->body.key.eventId = msg.body.key.eventId;
// nsecs_t eventTime
outMsg->body.key.eventTime = msg.body.key.eventTime;
// int32_t deviceId
@@ -78,6 +80,8 @@
case InputMessage::Type::MOTION: {
// uint32_t seq
outMsg->body.motion.seq = msg.body.motion.seq;
+ // int32_t eventId
+ outMsg->body.motion.eventId = msg.body.key.eventId;
// nsecs_t eventTime
outMsg->body.motion.eventTime = msg.body.motion.eventTime;
// int32_t deviceId
@@ -146,6 +150,7 @@
}
case InputMessage::Type::FOCUS: {
outMsg->body.focus.seq = msg.body.focus.seq;
+ outMsg->body.focus.eventId = msg.body.focus.eventId;
outMsg->body.focus.hasFocus = msg.body.focus.hasFocus;
outMsg->body.focus.inTouchMode = msg.body.focus.inTouchMode;
break;
diff --git a/tests/accessibility/res/drawable/size_48x48.jpg b/tests/accessibility/res/drawable/jpg_48_48.jpg
similarity index 100%
rename from tests/accessibility/res/drawable/size_48x48.jpg
rename to tests/accessibility/res/drawable/jpg_48_48.jpg
Binary files differ
diff --git a/tests/accessibility/res/drawable/png_72_72.png b/tests/accessibility/res/drawable/png_72_72.png
new file mode 100644
index 0000000..941458d
--- /dev/null
+++ b/tests/accessibility/res/drawable/png_72_72.png
Binary files differ
diff --git a/tests/accessibility/res/drawable/vector_drawable_6kdp_6kdp.xml b/tests/accessibility/res/drawable/vector_drawable_6kdp_6kdp.xml
new file mode 100644
index 0000000..0d11dc0
--- /dev/null
+++ b/tests/accessibility/res/drawable/vector_drawable_6kdp_6kdp.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="6000dp"
+ android:height="6000dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z"/>
+</vector>
diff --git a/tests/accessibility/res/raw/test_file b/tests/accessibility/res/raw/test_file
new file mode 100644
index 0000000..acea7ed
--- /dev/null
+++ b/tests/accessibility/res/raw/test_file
@@ -0,0 +1,12 @@
+10101010110101010101101010101011010101010110101010101101010101011010101010110
+1010101011010101010110101010101101010101011010101011010101101101010101011011011010101101101
+1011010101010011010101010110101011011010101010110101011011010101010110110110101010101101
+10110101010101101010101011010101010110101010101101010101010101101010101011010101
+101101010101011010101010110101010101101010101011010101101011010101010110101010101101010101011010101
+101101010101101010101011010101101101010101011010101001010110101011011010101010110110101010101
+10110101010101101010101011010101010110101010101101010101010101101
+101101010101010110101010101101010110110101010101101010101011010101011101010101011010101101101010
+10110101010101011010101101101010101011010101101010101011010101101010101011010101
+101101010101011010101011010101010110101011011010101010110101010101101010101
+
+
diff --git a/tests/accessibility/res/values/strings.xml b/tests/accessibility/res/values/strings.xml
index de1539a..40c3359 100644
--- a/tests/accessibility/res/values/strings.xml
+++ b/tests/accessibility/res/values/strings.xml
@@ -32,8 +32,26 @@
<!-- Description of the speaking accessibility service -->
<string name="some_description">Some description</string>
+ <!-- Html description of the vibrating accessibility service -->
+ <string name="html_description_vibrating_accessibility_service"><![CDATA[
+ <A href=\"fake_link\">Test link</a> <IMG src = \"R.drawable.file_name\">
+ ]]></string>
+
<!-- Html description of the speaking accessibility service -->
- <string name="some_html_description">Some html description</string>
+ <string name="html_description_speaking_accessibility_service"><![CDATA[
+ <a href=\"fake_link\"> <img src=\"R.drawable.file_name\">
+ ]]></string>
+
+ <!-- Html description of the speaking and vibrating accessibility service -->
+ <string name="html_description_speaking_and_vibrating_accessibility_service"><![CDATA[
+ <a href=fake_link> <img src=R.drawable.file_name>
+ ]]></string>
+
+ <!-- Html description of the accessibility button service -->
+ <string name="html_description_accessibility_button_service"><![CDATA[
+ <img src=\"r.drawable.file_name\"> <img alt=\"foo\" src=\"R.drawable.file_name\">
+ <img src=\"file://path\"> <img src=\"http://path\">
+ ]]></string>
<!-- Summary of the speaking accessibility service -->
<string name="some_summary">Some summary</string>
diff --git a/tests/accessibility/res/xml/accessibility_button_service.xml b/tests/accessibility/res/xml/accessibility_button_service.xml
index d475266..e483fd4 100644
--- a/tests/accessibility/res/xml/accessibility_button_service.xml
+++ b/tests/accessibility/res/xml/accessibility_button_service.xml
@@ -18,4 +18,6 @@
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagRequestAccessibilityButton"
+ android:animatedImageDrawable="@raw/test_file"
+ android:htmlDescription="@string/html_description_accessibility_button_service"
android:notificationTimeout="0" />
\ No newline at end of file
diff --git a/tests/accessibility/res/xml/speaking_accessibilityservice.xml b/tests/accessibility/res/xml/speaking_accessibilityservice.xml
index ede686d..9128309 100644
--- a/tests/accessibility/res/xml/speaking_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/speaking_accessibilityservice.xml
@@ -21,9 +21,9 @@
android:canRequestTouchExplorationMode="true"
android:canRequestFilterKeyEvents="true"
android:settingsActivity="foo.bar.Activity"
- android:animatedImageDrawable="@drawable/size_48x48"
+ android:animatedImageDrawable="@drawable/jpg_48_48"
android:description="@string/some_description"
- android:htmlDescription="@string/some_html_description"
+ android:htmlDescription="@string/html_description_speaking_accessibility_service"
android:summary="@string/some_summary"
android:nonInteractiveUiTimeout="1000"
android:interactiveUiTimeout="6000"/>
\ No newline at end of file
diff --git a/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml b/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml
index 3ac8661..09d36c6 100644
--- a/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/speaking_and_vibrating_accessibilityservice.xml
@@ -22,7 +22,7 @@
android:canRequestFilterKeyEvents="true"
android:canRequestEnhancedWebAccessibility="true"
android:settingsActivity="foo.bar.Activity"
- android:animatedImageDrawable="@drawable/size_48x48"
+ android:animatedImageDrawable="@drawable/vector_drawable_6kdp_6kdp"
android:description="@string/some_description"
- android:htmlDescription="@string/some_html_description"
+ android:htmlDescription="@string/html_description_speaking_and_vibrating_accessibility_service"
android:summary="@string/some_summary" />
diff --git a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml b/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
index 93d9f0d..ddf4018 100644
--- a/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
+++ b/tests/accessibility/res/xml/vibrating_accessibilityservice.xml
@@ -20,4 +20,6 @@
android:canRetrieveWindowContent="true"
android:canRequestTouchExplorationMode="true"
android:nonInteractiveUiTimeout="2000"
+ android:animatedImageDrawable="@drawable/png_72_72"
+ android:htmlDescription="@string/html_description_vibrating_accessibility_service"
android:interactiveUiTimeout="5000"/>
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
index d2f7c2d..8a75b54 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityServiceInfoTest.java
@@ -19,6 +19,7 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
@@ -26,13 +27,16 @@
import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
import android.accessibilityservice.AccessibilityServiceInfo;
-import android.app.Service;
+import android.content.Context;
+import android.content.pm.PackageManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
@@ -49,22 +53,44 @@
*/
@RunWith(AndroidJUnit4.class)
public class AccessibilityServiceInfoTest {
+ private AccessibilityManager mAccessibilityManager;
+ private PackageManager mPackageManager;
+ private Context mContext;
- private InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
+ private final InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
mSpeakingAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
- SpeakingAccessibilityService.class);
+ SpeakingAccessibilityService.class);
- private InstrumentedAccessibilityServiceTestRule<VibratingAccessibilityService>
+ private final InstrumentedAccessibilityServiceTestRule<VibratingAccessibilityService>
mVibratingAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
- VibratingAccessibilityService.class);
+ VibratingAccessibilityService.class);
+
+ private final InstrumentedAccessibilityServiceTestRule<SpeakingAndVibratingAccessibilityService>
+ mSpeakingAndVibratingAccessibilityServiceRule =
+ new InstrumentedAccessibilityServiceTestRule<>(
+ SpeakingAndVibratingAccessibilityService.class, /* enableService= */ false);
+
+ private final InstrumentedAccessibilityServiceTestRule<AccessibilityButtonService>
+ mA11yButtonServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
+ AccessibilityButtonService.class, /* enableService= */ false);
@Rule
public final RuleChain mRuleChain = RuleChain
.outerRule(mVibratingAccessibilityServiceRule)
.around(mSpeakingAccessibilityServiceRule)
+ .around(mSpeakingAndVibratingAccessibilityServiceRule)
+ .around(mA11yButtonServiceRule)
// Inner rule capture failure and dump data before finishing a11y service
.around(new AccessibilityDumpOnFailureRule());
+ @Before
+ public void setUp() throws Exception {
+ mContext = getInstrumentation().getContext();
+ mAccessibilityManager = getInstrumentation().getContext().getSystemService(
+ AccessibilityManager.class);
+ mPackageManager = getInstrumentation().getContext().getPackageManager();
+ }
+
/**
* Tests whether a service can that requested it can retrieve
* window content.
@@ -73,13 +99,12 @@
@SuppressWarnings("deprecation")
@Test
public void testAccessibilityServiceInfoForEnabledService() {
- AccessibilityManager accessibilityManager = (AccessibilityManager)
- getInstrumentation().getContext().getSystemService(Service.ACCESSIBILITY_SERVICE);
- List<AccessibilityServiceInfo> enabledServices =
- accessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_SPOKEN);
- assertSame("There should be one speaking service.", 1, enabledServices.size());
- AccessibilityServiceInfo speakingService = enabledServices.get(0);
+ final List<AccessibilityServiceInfo> enabledServices =
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_SPOKEN);
+ assertSame(/* message= */ "There should be one speaking service.",
+ /* expected= */ 1, enabledServices.size());
+ final AccessibilityServiceInfo speakingService = enabledServices.get(0);
assertSame(AccessibilityEvent.TYPES_ALL_MASK, speakingService.eventTypes);
assertSame(AccessibilityServiceInfo.FEEDBACK_SPOKEN, speakingService.feedbackType);
assertEquals(AccessibilityServiceInfo.DEFAULT
@@ -89,8 +114,8 @@
| AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS
| AccessibilityServiceInfo.FLAG_REQUEST_SHORTCUT_WARNING_DIALOG_SPOKEN_FEEDBACK,
speakingService.flags);
- assertSame(0l, speakingService.notificationTimeout);
- assertEquals("Some description", speakingService.getDescription());
+ assertSame(/* expected= */ 0l, speakingService.notificationTimeout);
+ assertEquals(/* expected= */ "Some description", speakingService.getDescription());
assertNull(speakingService.packageNames /*all packages*/);
assertNotNull(speakingService.getId());
assertSame(speakingService.getCapabilities(),
@@ -98,15 +123,86 @@
| AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
| AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
assertEquals("foo.bar.Activity", speakingService.getSettingsActivityName());
- assertNotNull(speakingService.loadAnimatedImage(getInstrumentation().getContext()));
- assertEquals("Some description", speakingService.loadDescription(
- getInstrumentation().getContext().getPackageManager()));
- assertEquals("Some html description", speakingService.loadHtmlDescription(
- getInstrumentation().getContext().getPackageManager()));
- assertEquals("Some summary", speakingService.loadSummary(
- getInstrumentation().getContext().getPackageManager()));
+ assertNotNull(speakingService.loadAnimatedImage(mContext));
+ assertEquals(/* expected= */ "Some description",
+ speakingService.loadDescription(mPackageManager));
+ assertEquals(/* expected= */
+ "<invalidtag href=\"fake_link\"> <img src=\"R.drawable.file_name\">",
+ speakingService.loadHtmlDescription(mPackageManager));
+ assertEquals(/* expected= */ "Some summary",
+ speakingService.loadSummary(mPackageManager));
assertNotNull(speakingService.getResolveInfo());
- assertEquals(6000, speakingService.getInteractiveUiTimeoutMillis());
- assertEquals(1000, speakingService.getNonInteractiveUiTimeoutMillis());
+ assertEquals(/* expected= */ 6000,
+ speakingService.getInteractiveUiTimeoutMillis());
+ assertEquals(/* expected= */ 1000,
+ speakingService.getNonInteractiveUiTimeoutMillis());
+ }
+
+ /**
+ * Tests the html description of accessibility services whether to meet the custom
+ * specification.
+ */
+ @Test
+ public void testAccessibilityServicesHtmlDescription() {
+ mSpeakingAndVibratingAccessibilityServiceRule.enableService();
+ mA11yButtonServiceRule.enableService();
+ final List<AccessibilityServiceInfo> enabledServices =
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ final AccessibilityServiceInfo vibratingService =
+ mVibratingAccessibilityServiceRule.getService().getServiceInfo();
+ final AccessibilityServiceInfo speakingService =
+ mSpeakingAccessibilityServiceRule.getService().getServiceInfo();
+ final AccessibilityServiceInfo speakingAndVibratingService =
+ mSpeakingAndVibratingAccessibilityServiceRule.getService().getServiceInfo();
+ final AccessibilityServiceInfo a11yService =
+ mA11yButtonServiceRule.getService().getServiceInfo();
+
+ assertSame(/* message= */ "There should be four services.", /* expected= */ 4,
+ enabledServices.size());
+ assertEquals(/* expected= */
+ "<invalidtag href=\"fake_link\">Test link</invalidtag> "
+ + "<IMG src = \"R.drawable.file_name\">",
+ vibratingService.loadHtmlDescription(mPackageManager));
+ assertEquals(/* expected= */
+ "<invalidtag href=\"fake_link\"> <img src=\"R.drawable.file_name\">",
+ speakingService.loadHtmlDescription(mPackageManager));
+ assertEquals(/* expected= */
+ "<invalidtag href=fake_link> <invalidtag src=R.drawable.file_name>",
+ speakingAndVibratingService.loadHtmlDescription(mPackageManager));
+ assertEquals(/* expected= */
+ "<invalidtag src=\"r.drawable.file_name\"> "
+ + "<invalidtag alt=\"foo\" src=\"R.drawable.file_name\"> "
+ + "<invalidtag src=\"file://path\"> "
+ + "<invalidtag src=\"http://path\">",
+ a11yService.loadHtmlDescription(mPackageManager));
+ }
+
+ /**
+ * Tests the animated image resource of accessibility services whether to meet the custom
+ * specification.
+ */
+ @Test
+ public void testAccessibilityServicesAnimatedImageResource() {
+ mSpeakingAndVibratingAccessibilityServiceRule.enableService();
+ mA11yButtonServiceRule.enableService();
+ final List<AccessibilityServiceInfo> enabledServices =
+ mAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
+ final AccessibilityServiceInfo vibratingService =
+ mVibratingAccessibilityServiceRule.getService().getServiceInfo();
+ final AccessibilityServiceInfo speakingService =
+ mSpeakingAccessibilityServiceRule.getService().getServiceInfo();
+ final AccessibilityServiceInfo speakingAndVibratingService =
+ mSpeakingAndVibratingAccessibilityServiceRule.getService().getServiceInfo();
+ final AccessibilityServiceInfo a11yService =
+ mA11yButtonServiceRule.getService().getServiceInfo();
+
+ assertSame(/* message= */ "There should be four services.", /* expected= */ 4,
+ enabledServices.size());
+ assertNotNull(vibratingService.loadAnimatedImage(mContext));
+ assertNotNull(speakingService.loadAnimatedImage(mContext));
+ assertNull(speakingAndVibratingService.loadAnimatedImage(mContext));
+ assertNull(a11yService.loadAnimatedImage(mContext));
}
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
index 4111baf..8f79102 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityEmbeddedHierarchyTest.java
@@ -18,6 +18,7 @@
import static android.accessibilityservice.cts.utils.ActivityLaunchUtils.launchActivityAndWaitForItToBeOnscreen;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -69,6 +70,8 @@
private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
new AccessibilityDumpOnFailureRule();
+ private AccessibilityEmbeddedHierarchyActivity mActivity;
+
@Rule
public final RuleChain mRuleChain = RuleChain
.outerRule(mActivityRule)
@@ -90,8 +93,9 @@
@Before
public void setUp() throws Throwable {
- launchActivityAndWaitForItToBeOnscreen(sInstrumentation, sUiAutomation, mActivityRule)
- .waitForEmbeddedHierarchy();
+ mActivity = launchActivityAndWaitForItToBeOnscreen(sInstrumentation, sUiAutomation,
+ mActivityRule);
+ mActivity.waitForEmbeddedHierarchy();
}
@Test
@@ -114,6 +118,7 @@
final AccessibilityNodeInfo target =
findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
final AccessibilityNodeInfo parent = target.getParent();
+
final Rect hostViewBoundsInScreen = new Rect();
final Rect embeddedViewBoundsInScreen = new Rect();
parent.getBoundsInScreen(hostViewBoundsInScreen);
@@ -125,6 +130,36 @@
hostViewBoundsInScreen.contains(embeddedViewBoundsInScreen));
}
+ @Test
+ public void testEmbeddedViewHasCorrectBoundAfterHostViewMove() {
+ final AccessibilityNodeInfo target =
+ findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
+
+ final Rect hostViewBoundsInScreen = new Rect();
+ final Rect newEmbeddedViewBoundsInScreen = new Rect();
+ final Rect oldEmbeddedViewBoundsInScreen = new Rect();
+ target.getBoundsInScreen(oldEmbeddedViewBoundsInScreen);
+
+ // Move Host SurfaceView from (0, 0) to (100, 100).
+ mActivity.requestNewLayoutForTest();
+
+ final AccessibilityNodeInfo newTarget =
+ findEmbeddedAccessibilityNodeInfo(sUiAutomation.getRootInActiveWindow());
+ final AccessibilityNodeInfo parent = newTarget.getParent();
+
+ newTarget.getBoundsInScreen(newEmbeddedViewBoundsInScreen);
+ parent.getBoundsInScreen(hostViewBoundsInScreen);
+
+ assertTrue("hostViewBoundsInScreen" + hostViewBoundsInScreen.toShortString()
+ + " doesn't contain newEmbeddedViewBoundsInScreen"
+ + newEmbeddedViewBoundsInScreen.toShortString(),
+ hostViewBoundsInScreen.contains(newEmbeddedViewBoundsInScreen));
+ assertFalse("newEmbeddedViewBoundsInScreen" + newEmbeddedViewBoundsInScreen.toShortString()
+ + " shouldn't be the same with oldEmbeddedViewBoundsInScreen"
+ + oldEmbeddedViewBoundsInScreen.toShortString(),
+ newEmbeddedViewBoundsInScreen.equals(oldEmbeddedViewBoundsInScreen));
+ }
+
private AccessibilityNodeInfo findEmbeddedAccessibilityNodeInfo(AccessibilityNodeInfo root) {
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -150,8 +185,11 @@
AccessibilityTestActivity implements SurfaceHolder.Callback {
private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
- private static final int DEFAULT_WIDTH = 200;
- private static final int DEFAULT_HEIGHT = 200;
+ private static final int DEFAULT_WIDTH = 150;
+ private static final int DEFAULT_HEIGHT = 150;
+
+ private static final int POSITION_X = 50;
+ private static final int POSITION_Y = 50;
private SurfaceView mSurfaceView;
private SurfaceControlViewHost mViewHost;
@@ -195,5 +233,13 @@
throw new AssertionError(e);
}
}
+
+ public void requestNewLayoutForTest() {
+ sInstrumentation.runOnMainSync(() -> {
+ mSurfaceView.setX(POSITION_X);
+ mSurfaceView.setY(POSITION_Y);
+ mSurfaceView.requestLayout();
+ });
+ }
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAuthenticationTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAuthenticationTest.java
new file mode 100644
index 0000000..678bad0
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineAuthenticationTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2020 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.autofillservice.cts.inline;
+
+import static android.app.Activity.RESULT_OK;
+import static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.UNUSED_AUTOFILL_VALUE;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.Timeouts.MOCK_IME_TIMEOUT_MS;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+
+import static com.android.cts.mockime.ImeEventStreamTestUtils.expectBindInput;
+
+import static org.junit.Assume.assumeTrue;
+
+import android.autofillservice.cts.AbstractLoginActivityTestCase;
+import android.autofillservice.cts.AuthenticationActivity;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.Helper;
+import android.content.IntentSender;
+import android.os.Process;
+
+import com.android.cts.mockime.ImeEventStream;
+import com.android.cts.mockime.MockImeSession;
+
+import org.junit.Test;
+
+public class InlineAuthenticationTest extends AbstractLoginActivityTestCase {
+
+ private static final String TAG = "InlineAuthenticationTest";
+
+ @Override
+ protected void enableService() {
+ Helper.enableAutofillService(getContext(), SERVICE_NAME);
+ }
+
+ @Test
+ public void testDatasetAuthTwoFields() throws Exception {
+ datasetAuthTwoFields(/* cancelFirstAttempt */ false);
+ }
+
+ private void datasetAuthTwoFields(boolean cancelFirstAttempt) throws Exception {
+ // Set service.
+ enableService();
+
+ final MockImeSession mockImeSession = sMockImeSessionRule.getMockImeSession();
+ assumeTrue("MockIME not available", mockImeSession != null);
+
+ // Prepare the authenticated response
+ final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+ new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .build());
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_USERNAME, UNUSED_AUTOFILL_VALUE)
+ .setField(ID_PASSWORD, UNUSED_AUTOFILL_VALUE)
+ .setPresentation(createPresentation("auth"))
+ .setInlinePresentation(createInlinePresentation("auth"))
+ .setAuthentication(authentication)
+ .build());
+ sReplier.addResponse(builder.build());
+ mActivity.expectAutoFill("dude", "sweet");
+
+ final ImeEventStream stream = mockImeSession.openEventStream();
+ mockImeSession.callRequestShowSelf(0);
+
+ // Wait until the MockIme gets bound to the TestActivity.
+ expectBindInput(stream, Process.myPid(), MOCK_IME_TIMEOUT_MS);
+
+ // Trigger auto-fill.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdle();
+ sReplier.getNextFillRequest();
+ mUiBot.assertSuggestionStrip(1);
+
+ // Make sure UI is show on 2nd field as well
+ mUiBot.selectByRelativeId(ID_PASSWORD);
+ mUiBot.waitForIdle();
+ mUiBot.assertSuggestionStrip(1);
+
+ // Now tap on 1st field to show it again...
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdle();
+ mUiBot.assertSuggestionStrip(1);
+
+ // TODO(b/149891961): add logic for cancelFirstAttempt
+
+ // ...and select it this time
+ AuthenticationActivity.setResultCode(RESULT_OK);
+ mUiBot.selectSuggestion(0);
+ mUiBot.waitForIdle();
+
+ // Check the results.
+ mActivity.assertAutoFilled();
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
new file mode 100644
index 0000000..941ebe2
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineFillEventHistoryTest.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2020 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.autofillservice.cts.inline;
+
+import static android.autofillservice.cts.CannedFillResponse.DO_NOT_REPLY_RESPONSE;
+import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
+import static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.NULL_DATASET_ID;
+import static android.autofillservice.cts.Helper.assertFillEventForDatasetAuthenticationSelected;
+import static android.autofillservice.cts.Helper.assertFillEventForDatasetSelected;
+import static android.autofillservice.cts.Helper.assertFillEventForDatasetShown;
+import static android.autofillservice.cts.Helper.assertFillEventForSaveShown;
+import static android.autofillservice.cts.Helper.assertNoDeprecatedClientState;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilConnected;
+import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilDisconnected;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import android.autofillservice.cts.AbstractLoginActivityTestCase;
+import android.autofillservice.cts.AuthenticationActivity;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.CannedFillResponse.CannedDataset;
+import android.autofillservice.cts.Helper;
+import android.autofillservice.cts.InstrumentedAutoFillService;
+import android.autofillservice.cts.LoginActivity;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.platform.test.annotations.AppModeFull;
+import android.service.autofill.FillEventHistory;
+import android.service.autofill.FillEventHistory.Event;
+import android.support.test.uiautomator.UiObject2;
+import android.view.View;
+
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * Test that uses {@link LoginActivity} to test {@link FillEventHistory}.
+ */
+@AppModeFull(reason = "Service-specific test")
+public class InlineFillEventHistoryTest extends AbstractLoginActivityTestCase {
+
+ @Override
+ protected void enableService() {
+ Helper.enableAutofillService(getContext(), SERVICE_NAME);
+ }
+
+ @Test
+ public void testNoDatasetAndSave() throws Exception {
+ enableService();
+
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_USERNAME)
+ .build());
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdle();
+
+ sReplier.getNextFillRequest();
+
+ // Suggestion strip was never shown.
+ mUiBot.assertNoSuggestionStripEver();
+
+ // Change username
+ mActivity.syncRunOnUiThread(() -> mActivity.onUsername((v) -> v.setText("ID")));
+ mUiBot.waitForIdle();
+
+ // Trigger save UI.
+ mActivity.tapSave();
+ mUiBot.waitForIdle();
+
+ // Confirm the save UI shown
+ final UiObject2 saveUi = mUiBot.assertSaveShowing(SAVE_DATA_TYPE_GENERIC);
+
+ // Save it...
+ mUiBot.saveForAutofill(saveUi, true);
+ mUiBot.waitForIdle();
+ sReplier.getNextSaveRequest();
+
+ // Verify save event
+ final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(1);
+ assertNoDeprecatedClientState(selection);
+ final List<Event> events = selection.getEvents();
+ assertFillEventForSaveShown(events.get(0), NULL_DATASET_ID);
+ }
+
+ @Test
+ public void testOneDatasetAndSave() throws Exception {
+ enableService();
+
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_USERNAME)
+ .addDataset(new CannedDataset.Builder()
+ .setField(ID_USERNAME, "id")
+ .setField(ID_PASSWORD, "pass")
+ .setPresentation(createPresentation("Dataset"))
+ .setInlinePresentation(createInlinePresentation("Dataset"))
+ .build())
+ .build());
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdle();
+ sReplier.getNextFillRequest();
+
+ // Suggestion strip was shown.
+ mUiBot.assertSuggestionStrip(1);
+ mUiBot.waitForIdle();
+
+ mUiBot.selectSuggestion(0);
+
+ // Change username and password
+ mActivity.syncRunOnUiThread(() -> mActivity.onUsername((v) -> v.setText("ID")));
+ mActivity.syncRunOnUiThread(() -> mActivity.onPassword((v) -> v.setText("PASS")));
+ mUiBot.waitForIdle();
+
+ // Trigger save UI.
+ mActivity.tapSave();
+ mUiBot.waitForIdle();
+
+ // Confirm the save UI shown
+ final UiObject2 saveUi = mUiBot.assertUpdateShowing(SAVE_DATA_TYPE_GENERIC);
+
+ // Save it...
+ mUiBot.saveForAutofill(saveUi, true);
+ mUiBot.waitForIdle();
+ sReplier.getNextSaveRequest();
+
+ // Verify events history
+ final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(4);
+ assertNoDeprecatedClientState(selection);
+ final List<Event> events = selection.getEvents();
+ assertFillEventForDatasetShown(events.get(0));
+ assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+ assertFillEventForDatasetShown(events.get(0));
+ assertFillEventForSaveShown(events.get(3), NULL_DATASET_ID);
+ }
+
+ @Test
+ public void testDatasetAuthenticationSelected() throws Exception {
+ enableService();
+
+ // Set up FillResponse with dataset authentication
+ Bundle clientState = new Bundle();
+ clientState.putCharSequence("clientStateKey", "clientStateValue");
+
+ // Prepare the authenticated response
+ final IntentSender authentication = AuthenticationActivity.createSender(mContext, 1,
+ new CannedDataset.Builder()
+ .setField(ID_USERNAME, "dude")
+ .setField(ID_PASSWORD, "sweet")
+ .setPresentation(createPresentation("Dataset"))
+ .setInlinePresentation(createInlinePresentation("Dataset"))
+ .build());
+
+ sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+ new CannedDataset.Builder()
+ .setField(ID_USERNAME, "username")
+ .setId("name")
+ .setPresentation(createPresentation("authentication"))
+ .setInlinePresentation(createInlinePresentation("authentication"))
+ .setAuthentication(authentication)
+ .build())
+ .setExtras(clientState).build());
+ mActivity.expectAutoFill("dude", "sweet");
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ mUiBot.waitForIdle();
+
+ // ...
+ sReplier.getNextFillRequest();
+ mUiBot.assertSuggestionStrip(1);
+
+ // Authenticate
+ mUiBot.selectSuggestion(0);
+ mUiBot.waitForIdle();
+ mActivity.assertAutoFilled();
+
+ // Verify fill selection
+ final List<Event> events = InstrumentedAutoFillService.getFillEvents(2);
+ assertFillEventForDatasetShown(events.get(0), "clientStateKey", "clientStateValue");
+ assertFillEventForDatasetAuthenticationSelected(events.get(1), "name",
+ "clientStateKey", "clientStateValue");
+ }
+
+ @Test
+ public void testNoEvents_whenServiceReturnsNullResponse() throws Exception {
+ enableService();
+
+ // First reset
+ sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+ new CannedDataset.Builder()
+ .setField(ID_USERNAME, "username")
+ .setPresentation(createPresentation("dataset1"))
+ .setInlinePresentation(createInlinePresentation("dataset1"))
+ .build())
+ .build());
+ mActivity.expectAutoFill("username");
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ waitUntilConnected();
+ sReplier.getNextFillRequest();
+ mUiBot.selectSuggestion(0);
+ mUiBot.waitForIdle();
+ mActivity.assertAutoFilled();
+
+ {
+ // Verify fill selection
+ final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(2);
+ assertNoDeprecatedClientState(selection);
+ final List<Event> events = selection.getEvents();
+ assertFillEventForDatasetShown(events.get(0));
+ assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+ }
+
+ // Second request
+ sReplier.addResponse(NO_RESPONSE);
+ mActivity.onPassword(View::requestFocus);
+ sReplier.getNextFillRequest();
+ mUiBot.assertNoSuggestionStripEver();
+ waitUntilDisconnected();
+
+ InstrumentedAutoFillService.assertNoFillEventHistory();
+ }
+
+ @Test
+ public void testNoEvents_whenServiceReturnsFailure() throws Exception {
+ enableService();
+
+ // First reset
+ sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+ new CannedDataset.Builder()
+ .setField(ID_USERNAME, "username")
+ .setPresentation(createPresentation("dataset1"))
+ .setInlinePresentation(createInlinePresentation("dataset1"))
+ .build())
+ .build());
+ mActivity.expectAutoFill("username");
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ waitUntilConnected();
+ sReplier.getNextFillRequest();
+ mUiBot.selectSuggestion(0);
+ mUiBot.waitForIdle();
+ mActivity.assertAutoFilled();
+
+ {
+ // Verify fill selection
+ final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(2);
+ assertNoDeprecatedClientState(selection);
+ final List<Event> events = selection.getEvents();
+ assertFillEventForDatasetShown(events.get(0));
+ assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+ }
+
+ // Second request
+ sReplier.addResponse(new CannedFillResponse.Builder().returnFailure("D'OH!").build());
+ mActivity.onPassword(View::requestFocus);
+ sReplier.getNextFillRequest();
+ mUiBot.assertNoSuggestionStripEver();
+ waitUntilDisconnected();
+
+ InstrumentedAutoFillService.assertNoFillEventHistory();
+ }
+
+ @Test
+ public void testNoEvents_whenServiceTimesout() throws Exception {
+ enableService();
+
+ // First reset
+ sReplier.addResponse(new CannedFillResponse.Builder().addDataset(
+ new CannedDataset.Builder()
+ .setField(ID_USERNAME, "username")
+ .setPresentation(createPresentation("dataset1"))
+ .setInlinePresentation(createInlinePresentation("dataset1"))
+ .build())
+ .build());
+ mActivity.expectAutoFill("username");
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_USERNAME);
+ waitUntilConnected();
+ sReplier.getNextFillRequest();
+ mUiBot.selectSuggestion(0);
+ mUiBot.waitForIdle();
+ mActivity.assertAutoFilled();
+
+ {
+ // Verify fill selection
+ final FillEventHistory selection = InstrumentedAutoFillService.getFillEventHistory(2);
+ assertNoDeprecatedClientState(selection);
+ final List<Event> events = selection.getEvents();
+ assertFillEventForDatasetShown(events.get(0));
+ assertFillEventForDatasetSelected(events.get(1), NULL_DATASET_ID);
+ }
+
+ // Second request
+ sReplier.addResponse(DO_NOT_REPLY_RESPONSE);
+ mActivity.onPassword(View::requestFocus);
+ sReplier.getNextFillRequest();
+ waitUntilDisconnected();
+
+ InstrumentedAutoFillService.assertNoFillEventHistory();
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
new file mode 100644
index 0000000..17bcc2f
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/inline/InlineSimpleSaveActivityTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2020 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.autofillservice.cts.inline;
+
+import static android.autofillservice.cts.Helper.assertTextAndValue;
+import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
+import static android.autofillservice.cts.SimpleSaveActivity.ID_COMMIT;
+import static android.autofillservice.cts.SimpleSaveActivity.ID_INPUT;
+import static android.autofillservice.cts.SimpleSaveActivity.ID_PASSWORD;
+import static android.autofillservice.cts.inline.InstrumentedAutoFillServiceInlineEnabled.SERVICE_NAME;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import android.autofillservice.cts.AutoFillServiceTestCase;
+import android.autofillservice.cts.AutofillActivityTestRule;
+import android.autofillservice.cts.CannedFillResponse;
+import android.autofillservice.cts.Helper;
+import android.autofillservice.cts.InstrumentedAutoFillService;
+import android.autofillservice.cts.SimpleSaveActivity;
+import android.support.test.uiautomator.UiObject2;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Test;
+
+public class InlineSimpleSaveActivityTest
+ extends AutoFillServiceTestCase.AutoActivityLaunch<SimpleSaveActivity> {
+
+ private static final String TAG = "InlineSimpleSaveActivityTest";
+ protected SimpleSaveActivity mActivity;
+
+ @Override
+ protected void enableService() {
+ Helper.enableAutofillService(getContext(), SERVICE_NAME);
+ }
+
+ @NonNull
+ @Override
+ protected AutofillActivityTestRule<SimpleSaveActivity> getActivityRule() {
+ return new AutofillActivityTestRule<SimpleSaveActivity>(SimpleSaveActivity.class) {
+ @Override
+ protected void afterActivityLaunched() {
+ mActivity = getActivity();
+ }
+ };
+ }
+
+ @Test
+ public void testAutofillSave() throws Exception {
+ // Set service.
+ enableService();
+
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_INPUT)
+ .build());
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_INPUT);
+ mUiBot.waitForIdle();
+
+ sReplier.getNextFillRequest();
+
+ // Suggestion strip was never shown.
+ mUiBot.assertNoSuggestionStripEver();
+
+ // Change input
+ mActivity.syncRunOnUiThread(() -> mActivity.getInput().setText("ID"));
+ mUiBot.waitForIdle();
+
+ // Trigger save UI.
+ mUiBot.selectByRelativeId(ID_COMMIT);
+ mUiBot.waitForIdle();
+
+ // Confirm the save UI shown
+ final UiObject2 saveUi = mUiBot.assertSaveShowing(SAVE_DATA_TYPE_GENERIC);
+
+ // Save it...
+ mUiBot.saveForAutofill(saveUi, true);
+
+ // ... and assert results
+ final InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_INPUT), "ID");
+ }
+
+ @Test
+ public void testAutofill_oneDatasetAndSave() throws Exception {
+ // Set service.
+ enableService();
+
+ final CannedFillResponse.Builder builder = new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_INPUT, ID_PASSWORD)
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField(ID_INPUT, "id")
+ .setField(ID_PASSWORD, "pass")
+ .setPresentation(createPresentation("YO"))
+ .setInlinePresentation(createInlinePresentation("YO"))
+ .build());
+ sReplier.addResponse(builder.build());
+ mActivity.expectAutoFill("id", "pass");
+
+ // Trigger auto-fill and IME.
+ mUiBot.selectByRelativeId(ID_INPUT);
+ mUiBot.waitForIdle();
+
+ sReplier.getNextFillRequest();
+
+ // Confirm one suggestion
+ mUiBot.assertSuggestionStrip(1);
+
+ // Select suggestion
+ mUiBot.selectSuggestion(0);
+ mUiBot.waitForIdle();
+
+ // Check the results.
+ mActivity.expectAutoFill("id", "pass");
+
+ // Change input
+ mActivity.syncRunOnUiThread(() -> mActivity.getInput().setText("ID"));
+ mUiBot.waitForIdle();
+
+ // Trigger save UI.
+ mUiBot.selectByRelativeId(ID_COMMIT);
+ mUiBot.waitForIdle();
+
+ // Confirm the save UI shown
+ final UiObject2 saveUi = mUiBot.assertUpdateShowing(SAVE_DATA_TYPE_GENERIC);
+
+ // Save it...
+ mUiBot.saveForAutofill(saveUi, true);
+
+ // ... and assert results
+ final InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_INPUT), "ID");
+ assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_PASSWORD), "pass");
+ }
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
index c454c84..5121a39 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/MultiDisplaySystemDecorationTests.java
@@ -292,7 +292,6 @@
* Tests launching a single instance home activity on virtual display with system decoration
* support.
*/
- @FlakyTest(bugId = 149070587)
@Test
public void testLaunchSingleHomeActivityOnDisplayWithDecorations() {
createManagedHomeActivitySession(SINGLE_HOME_ACTIVITY);
@@ -316,7 +315,6 @@
* Tests launching a single instance home activity with SECONDARY_HOME on virtual display with
* system decoration support.
*/
- @FlakyTest(bugId = 149070587)
@Test
public void testLaunchSingleSecondaryHomeActivityOnDisplayWithDecorations() {
createManagedHomeActivitySession(SINGLE_SECONDARY_HOME_ACTIVITY);
@@ -340,7 +338,6 @@
* Tests launching a multi-instance home activity on virtual display with system decoration
* support.
*/
- @FlakyTest(bugId = 149070587)
@Test
public void testLaunchHomeActivityOnDisplayWithDecorations() {
createManagedHomeActivitySession(HOME_ACTIVITY);
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index e5a6f05..cd054c2 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -101,6 +101,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import static java.lang.Integer.toHexString;
@@ -529,9 +530,18 @@
}
protected ComponentName getDefaultSecondaryHomeComponent() {
+ assumeTrue(supportsMultiDisplay());
int resId = Resources.getSystem().getIdentifier(
- "config_secondaryHomeComponent", "string", "android");
- return ComponentName.unflattenFromString(mContext.getResources().getString(resId));
+ "config_secondaryHomePackage", "string", "android");
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_SECONDARY_HOME);
+ intent.setPackage(mContext.getResources().getString(resId));
+ final ResolveInfo resolveInfo =
+ mContext.getPackageManager().resolveActivity(intent, MATCH_DEFAULT_ONLY);
+ assertNotNull("Should have default secondary home activity", resolveInfo);
+
+ return new ComponentName(resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name);
}
/**
diff --git a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
index ab44335..afae17e 100644
--- a/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
+++ b/tests/tests/batterysaving/src/android/os/cts/batterysaving/BatterySaverTest.java
@@ -22,12 +22,15 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import android.app.UiModeManager;
+import android.content.res.Configuration;
import android.os.PowerManager;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.BatteryUtils;
+import com.android.compatibility.common.util.SettingsUtils;
import com.android.compatibility.common.util.SystemUtil;
import org.junit.Test;
@@ -91,4 +94,57 @@
assertFalse(manager.isPowerSaveMode());
});
}
+
+ /** Tests that Battery Saver exemptions activate when car mode is active. */
+ @Test
+ public void testCarModeExceptions() throws Exception {
+ UiModeManager uiModeManager = getContext().getSystemService(UiModeManager.class);
+ uiModeManager.disableCarMode(0);
+
+ final PowerManager powerManager = BatteryUtils.getPowerManager();
+
+ try {
+ runDumpsysBatteryUnplug();
+
+ SettingsUtils.set(SettingsUtils.NAMESPACE_GLOBAL, "battery_saver_constants",
+ "gps_mode=" + PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF
+ + ",enable_night_mode=true");
+
+ enableBatterySaver(true);
+
+ // Allow time for UI change.
+ Thread.sleep(1000);
+ assertTrue(powerManager.isPowerSaveMode());
+ assertEquals(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
+ powerManager.getLocationPowerSaveMode());
+ assertEquals(Configuration.UI_MODE_NIGHT_YES,
+ getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK);
+
+ uiModeManager.enableCarMode(0);
+ // Allow time for UI change.
+ Thread.sleep(1000);
+
+ final int locationPowerSaveMode = powerManager.getLocationPowerSaveMode();
+ assertTrue("Location power save mode didn't change from " + locationPowerSaveMode,
+ locationPowerSaveMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY
+ || locationPowerSaveMode == PowerManager.LOCATION_MODE_NO_CHANGE);
+ assertEquals(Configuration.UI_MODE_NIGHT_NO,
+ getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK);
+
+ uiModeManager.disableCarMode(0);
+ // Allow time for UI change.
+ Thread.sleep(1000);
+
+ assertEquals(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
+ powerManager.getLocationPowerSaveMode());
+ assertEquals(Configuration.UI_MODE_NIGHT_YES,
+ getContext().getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK);
+ } finally {
+ uiModeManager.disableCarMode(0);
+ SettingsUtils.delete(SettingsUtils.NAMESPACE_GLOBAL, "battery_saver_constants");
+ }
+ }
}
diff --git a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
index 583ff7c..1a27bf0 100644
--- a/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ApplicationInfoTest.java
@@ -26,7 +26,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import android.content.Context;
@@ -215,4 +217,62 @@
PARTIALLY_DIRECT_BOOT_AWARE_PACKAGE_NAME, 0);
assertTrue(applicationInfo.isEncryptionAware());
}
+
+ @Test
+ public void testWriteToParcelDontSquash() throws Exception {
+ // Make sure ApplicationInfo.writeToParcel() doesn't do the "squashing",
+ // because Parcel.allowSquashing() isn't called.
+
+ mApplicationInfo = getContext().getPackageManager().getApplicationInfo(mPackageName, 0);
+
+ final Parcel p = Parcel.obtain();
+ mApplicationInfo.writeToParcel(p, 0);
+ mApplicationInfo.writeToParcel(p, 0);
+
+ // Don't call Parcel.allowSquashing()
+
+ p.setDataPosition(0);
+ final ApplicationInfo copy1 = ApplicationInfo.CREATOR.createFromParcel(p);
+ final ApplicationInfo copy2 = ApplicationInfo.CREATOR.createFromParcel(p);
+
+ p.recycle();
+
+ assertNotSame(mApplicationInfo, copy1);
+
+ // writeToParcel() doesn't do the squashing, so copy1 and copy2 will be different.
+ assertNotSame(copy1, copy2);
+
+ // Check several fields to make sure they're properly copied.
+ assertEquals(mApplicationInfo.packageName, copy2.packageName);
+ assertEquals(copy1.packageName, copy2.packageName);
+
+ assertEquals(mApplicationInfo.flags, copy2.flags);
+ assertEquals(copy1.flags, copy2.flags);
+ }
+
+ @Test
+ public void testWriteToParcelSquash() throws Exception {
+ // Make sure ApplicationInfo.writeToParcel() does the "squashing", after
+ // Parcel.allowSquashing() is called.
+
+ mApplicationInfo = getContext().getPackageManager().getApplicationInfo(mPackageName, 0);
+
+ final Parcel p = Parcel.obtain();
+
+ final boolean prevSquashing = p.allowSquashing(); // Allow squashing.
+
+ mApplicationInfo.writeToParcel(p, 0);
+ mApplicationInfo.writeToParcel(p, 0);
+
+ p.setDataPosition(0);
+ final ApplicationInfo copy1 = ApplicationInfo.CREATOR.createFromParcel(p);
+ final ApplicationInfo copy2 = ApplicationInfo.CREATOR.createFromParcel(p);
+
+ p.recycle();
+
+ assertNotSame(mApplicationInfo, copy1);
+ assertSame(copy1, copy2); //
+
+ p.restoreAllowSquashing(prevSquashing);
+ }
}
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
index b2aae0d..8cfab20 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageInfoTest.java
@@ -18,6 +18,7 @@
import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
import android.content.pm.ConfigurationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
@@ -63,6 +64,19 @@
p.recycle();
}
+ public void testApplicationInfoSame() {
+ ApplicationInfo ai = mPackageInfo.applicationInfo;
+
+ // Make sure all the components in it has the same ApplicationInfo.
+ for (ComponentInfo[] ar : new ComponentInfo[][]{
+ mPackageInfo.activities, mPackageInfo.services, mPackageInfo.providers,
+ mPackageInfo.receivers}) {
+ for (ComponentInfo ci : ar) {
+ assertSame("component=" + ci.getComponentName(), ai, ci.applicationInfo);
+ }
+ }
+ }
+
private void checkPkgInfoSame(PackageInfo expected, PackageInfo actual) {
assertEquals(expected.packageName, actual.packageName);
assertEquals(expected.getLongVersionCode(), actual.getLongVersionCode());
diff --git a/tests/tests/content/src/android/content/pm/cts/ProviderInfoListTest.java b/tests/tests/content/src/android/content/pm/cts/ProviderInfoListTest.java
new file mode 100644
index 0000000..2578058
--- /dev/null
+++ b/tests/tests/content/src/android/content/pm/cts/ProviderInfoListTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2020 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.content.pm.cts;
+
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ProviderInfoList;
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ProviderInfoListTest extends AndroidTestCase {
+ private static final String PACKAGE_NAME = "android.content.cts";
+
+ public void testApplicationInfoSquashed() throws Exception {
+ final PackageManager pm = getContext().getPackageManager();
+ final PackageInfo pi = pm.getPackageInfo(PACKAGE_NAME,
+ PackageManager.GET_PROVIDERS | PackageManager.GET_UNINSTALLED_PACKAGES);
+
+ // Make sure the package contains more than 1 providers.
+ assertNotNull(pi);
+ assertNotNull(pi.providers);
+ assertTrue(pi.providers.length > 1);
+
+ final List<ProviderInfo> providers = new ArrayList<>();
+ Collections.addAll(providers, pi.providers);
+
+ // Create a target list.
+ final ProviderInfoList source = ProviderInfoList.fromList(providers);
+
+ // Parcel it and uparcel
+ final Parcel p = Parcel.obtain();
+ source.writeToParcel(p, 0);
+ p.setDataPosition(0);
+ final ProviderInfoList dest = ProviderInfoList.CREATOR.createFromParcel(p);
+ p.recycle();
+
+ final List<ProviderInfo> destList = dest.getList();
+ assertEquals(source.getList().size(), destList.size());
+ for (int i = 0; i < destList.size(); i++) {
+ assertEquals(destList.get(0).applicationInfo, destList.get(i).applicationInfo);
+ }
+ }
+}
diff --git a/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java b/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
index 44a9cc2..d5361d7 100644
--- a/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
+++ b/tests/tests/net/src/android/net/wifi/rtt/cts/WifiRttTest.java
@@ -163,7 +163,7 @@
// Analyze results
assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS="
- + NUM_OF_RTT_ITERATIONS,
+ + NUM_OF_RTT_ITERATIONS + ", AP RSSI=" + testAp.level,
numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100);
if (numFailures != NUM_OF_RTT_ITERATIONS) {
double distanceAvg = distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
diff --git a/tests/tests/provider/OWNERS b/tests/tests/provider/OWNERS
index fea932d..ed13f6fa 100644
--- a/tests/tests/provider/OWNERS
+++ b/tests/tests/provider/OWNERS
@@ -5,3 +5,5 @@
tgunn@google.com
nicksauer@google.com
nona@google.com
+nandana@google.com
+zezeozue@google.com
diff --git a/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml b/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
index f1829f6..31ffdd8 100644
--- a/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
+++ b/tests/tests/role/CtsRoleTestApp/AndroidManifest.xml
@@ -50,6 +50,14 @@
<data android:scheme="tel" />
</intent-filter>
</activity>
+ <service
+ android:name=".DialerInCallService"
+ android:permission="android.permission.BIND_INCALL_SERVICE">
+ <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
+ <intent-filter>
+ <action android:name="android.telecom.InCallService" />
+ </intent-filter>
+ </service>
<!-- Sms -->
<activity android:name=".SmsSendToActivity">
@@ -64,7 +72,6 @@
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
- <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="smsto" />
</intent-filter>
</service>
diff --git a/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml b/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml
index 8fd7012..574f768 100644
--- a/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml
+++ b/tests/tests/role/CtsRoleTestApp28/AndroidManifest.xml
@@ -45,6 +45,14 @@
<data android:scheme="tel" />
</intent-filter>
</activity>
+ <service
+ android:name=".DialerInCallService"
+ android:permission="android.permission.BIND_INCALL_SERVICE">
+ <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
+ <intent-filter>
+ <action android:name="android.telecom.InCallService" />
+ </intent-filter>
+ </service>
<!-- Sms -->
<activity android:name=".SmsSendToActivity">
@@ -59,7 +67,6 @@
android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
<intent-filter>
<action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />
- <category android:name="android.intent.category.DEFAULT" />
<data android:scheme="smsto" />
</intent-filter>
</service>