Merge "Revert "add CTS tests for concurrent audio capture"" into oc-dev
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 9e98b79..070bada 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -63,7 +63,8 @@
# Not yet mandated tests
NOT_YET_MANDATED = {
"scene0": [
- "test_jitter"
+ "test_jitter",
+ "test_burst_capture"
],
"scene1": [
"test_ae_af",
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
index 1d585ac..035dc3f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
@@ -56,6 +56,10 @@
"<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\" />" +
"<InputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\" />" +
"</PeripheralProfile>" +
+ "<PeripheralProfile ProfileName=\"AudioBox USB\" ProfileDescription=\"Presonus AudioBox USB\" ProductName=\"USB-Audio - AudioBox USB\">" +
+ "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+ "<InputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+ "</PeripheralProfile>" +
"</ProfileList>";
// XML Tags and Attributes
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
index acd346a..476eb80 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/IntentFiltersTestHelper.java
@@ -29,6 +29,7 @@
import android.media.audiofx.AudioEffect;
import android.net.Uri;
import android.nfc.cardemulation.CardEmulation;
+import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserHandle;
@@ -67,7 +68,6 @@
new Intent(AlarmClock.ACTION_SET_TIMER),
new Intent(AlarmClock.ACTION_SHOW_ALARMS),
new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS),
- new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS),
new Intent(Settings.ACTION_CAPTIONING_SETTINGS),
new Intent(Settings.ACTION_DATE_SETTINGS),
new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS),
@@ -266,6 +266,11 @@
notForwardedIntentsFromManaged.add(
new Intent(Settings.ACTION_PRINT_SETTINGS));
}
+
+ if (Build.TYPE.equals("user")) {
+ forwardedIntentsFromManaged.add(
+ new Intent(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS));
+ }
}
public boolean checkCrossProfileIntentFilters(int flag) {
diff --git a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
index a047732..15197a0 100644
--- a/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
+++ b/hostsidetests/appsecurity/test-apps/EncryptionApp/src/com/android/cts/encryptionapp/EncryptionAppTest.java
@@ -92,8 +92,6 @@
mDevice.waitForIdle();
// Set a PIN for this user
- mDevice.executeShellCommand("settings put global require_password_to_decrypt 0");
- mDevice.executeShellCommand("locksettings set-disabled false");
mDevice.executeShellCommand("locksettings set-pin 12345");
}
@@ -107,8 +105,6 @@
// Clear PIN for this user
mDevice.executeShellCommand("locksettings clear --old 12345");
- mDevice.executeShellCommand("locksettings set-disabled true");
- mDevice.executeShellCommand("settings delete global require_password_to_decrypt");
}
public void doBootCountBefore() throws Exception {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
index e591c25..63caebc 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/AndroidManifest.xml
@@ -63,6 +63,7 @@
android:theme="@android:style/Theme.NoDisplay">
<!-- TEST: ephemeral apps can start this activity using directed intent -->
</activity>
+
<service
android:name=".EphemeralService">
<!-- TEST: ephemeral apps can see this service using query methods -->
@@ -76,6 +77,15 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
+
+ <provider
+ android:name=".EphemeralProvider"
+ android:authorities="com.android.cts.ephemeralapp1.provider"
+ android:exported="true">
+ <intent-filter android:priority="0">
+ <action android:name="com.android.cts.ephemeraltest.QUERY" />
+ </intent-filter>
+ </provider>
</application>
<instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
index ada9c36..c0f4d2b 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/ClientTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import android.annotation.Nullable;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -32,6 +33,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.IBinder;
@@ -135,6 +137,53 @@
@Test
public void testQuery() throws Exception {
+ // query normal activities
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(2));
+ assertThat(resolveInfo.get(0).activityInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).activityInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralActivity"));
+ assertThat(resolveInfo.get(0).instantAppAvailable,
+ is(true));
+ assertThat(resolveInfo.get(1).activityInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(1).activityInfo.name,
+ is("com.android.cts.normalapp.ExposedActivity"));
+ assertThat(resolveInfo.get(1).instantAppAvailable,
+ is(false));
+ }
+
+ // query normal activities; directed package
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(2));
+ assertThat(resolveInfo.get(0).activityInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).activityInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralActivity"));
+ assertThat(resolveInfo.get(0).instantAppAvailable,
+ is(true));
+ assertThat(resolveInfo.get(1).activityInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(1).activityInfo.name,
+ is("com.android.cts.normalapp.ExposedActivity"));
+ assertThat(resolveInfo.get(1).instantAppAvailable,
+ is(false));
+ }
+
+ // query normal activities; directed component
{
final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
@@ -176,6 +225,93 @@
assertThat(resolveInfo.get(1).instantAppAvailable,
is(false));
}
+
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setPackage("com.android.cts.ephemeralapp1");
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+ .getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(1));
+ assertThat(resolveInfo.get(0).serviceInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).serviceInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralService"));
+ }
+
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setComponent(
+ new ComponentName("com.android.cts.ephemeralapp1",
+ "com.android.cts.ephemeralapp1.EphemeralService"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+ .getContext().getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(1));
+ assertThat(resolveInfo.get(0).serviceInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).serviceInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralService"));
+ }
+
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+ .getContext().getPackageManager().queryIntentContentProviders(
+ queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(2));
+ assertThat(resolveInfo.get(0).providerInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).providerInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralProvider"));
+ assertThat(resolveInfo.get(1).providerInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(1).providerInfo.name,
+ is("com.android.cts.normalapp.ExposedProvider"));
+ assertThat(resolveInfo.get(1).instantAppAvailable,
+ is(false));
+ }
+
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setPackage("com.android.cts.ephemeralapp1");
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+ .getContext().getPackageManager().queryIntentContentProviders(
+ queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(1));
+ assertThat(resolveInfo.get(0).providerInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).providerInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralProvider"));
+ }
+
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setComponent(
+ new ComponentName("com.android.cts.ephemeralapp1",
+ "com.android.cts.ephemeralapp1.EphemeralProvider"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+ .getContext().getPackageManager().queryIntentContentProviders(
+ queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(1));
+ assertThat(resolveInfo.get(0).providerInfo.packageName,
+ is("com.android.cts.ephemeralapp1"));
+ assertThat(resolveInfo.get(0).providerInfo.name,
+ is("com.android.cts.ephemeralapp1.EphemeralProvider"));
+ }
}
@Test
@@ -230,6 +366,48 @@
// provide any feedback. The alternative is to wait for the broadcast timeout
// but it's silly to artificially slow down CTS. We'll rely on queryIntentService
// to check whether or not the service is actually exposed
+
+ // bind to the normal service; directed package
+ {
+ final Intent startNormalIntent = new Intent(ACTION_START_NORMAL);
+ startNormalIntent.setPackage("com.android.cts.normalapp");
+ final TestServiceConnection connection = new TestServiceConnection();
+ try {
+ assertThat(InstrumentationRegistry.getContext().bindService(
+ startNormalIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
+ is(false));
+ } finally {
+ InstrumentationRegistry.getContext().unbindService(connection);
+ }
+ }
+
+ // bind to the normal service; directed component
+ {
+ final Intent startNormalIntent = new Intent(ACTION_START_NORMAL);
+ startNormalIntent.setComponent(new ComponentName(
+ "com.android.cts.normalapp", "com.android.cts.normalapp.NormalService"));
+ final TestServiceConnection connection = new TestServiceConnection();
+ try {
+ assertThat(InstrumentationRegistry.getContext().bindService(
+ startNormalIntent, connection, Context.BIND_AUTO_CREATE /*flags*/),
+ is(false));
+ } finally {
+ InstrumentationRegistry.getContext().unbindService(connection);
+ }
+ }
+
+ // connect to the normal provider
+ {
+ final String provider = "content://com.android.cts.normalapp.provider/table";
+ final Cursor testCursor = InstrumentationRegistry
+ .getContext().getContentResolver().query(
+ Uri.parse(provider),
+ null /*projection*/,
+ null /*selection*/,
+ null /*selectionArgs*/,
+ null /*sortOrder*/);
+ assertThat(testCursor, is(nullValue()));
+ }
}
@Test
@@ -376,12 +554,43 @@
is("onBind"));
assertThat(testResult.getStatus(),
is("PASS"));
+ assertThat(testResult.getEphemeralPackageInfoExposed(),
+ is(true));
assertThat(testResult.getException(),
is(nullValue()));
} finally {
InstrumentationRegistry.getContext().unbindService(connection);
}
}
+
+ // connect to exposed provider
+ {
+ final String provider = "content://com.android.cts.normalapp.exposed.provider/table";
+ final Cursor testCursor = InstrumentationRegistry
+ .getContext().getContentResolver().query(
+ Uri.parse(provider),
+ null /*projection*/,
+ null /*selection*/,
+ null /*selectionArgs*/,
+ null /*sortOrder*/);
+ assertThat(testCursor, is(notNullValue()));
+ assertThat(testCursor.getCount(), is(1));
+ assertThat(testCursor.getColumnCount(), is(2));
+ assertThat(testCursor.moveToFirst(), is(true));
+ assertThat(testCursor.getInt(0), is(1));
+ assertThat(testCursor.getString(1), is("ExposedProvider"));
+ final TestResult testResult = getResult();
+ assertThat(testResult.getPackageName(),
+ is("com.android.cts.normalapp"));
+ assertThat(testResult.getComponentName(),
+ is("ExposedProvider"));
+ assertThat(testResult.getStatus(),
+ is("PASS"));
+ assertThat(testResult.getEphemeralPackageInfoExposed(),
+ is(true));
+ assertThat(testResult.getException(),
+ is(nullValue()));
+ }
}
@Test
@@ -607,6 +816,24 @@
InstrumentationRegistry.getContext().unbindService(connection);
}
}
+
+ // connect to the instant app provider
+ {
+ final String provider = "content://com.android.cts.ephemeralapp1.provider/table";
+ final Cursor testCursor = InstrumentationRegistry
+ .getContext().getContentResolver().query(
+ Uri.parse(provider),
+ null /*projection*/,
+ null /*selection*/,
+ null /*selectionArgs*/,
+ null /*sortOrder*/);
+ assertThat(testCursor, is(notNullValue()));
+ assertThat(testCursor.getCount(), is(1));
+ assertThat(testCursor.getColumnCount(), is(2));
+ assertThat(testCursor.moveToFirst(), is(true));
+ assertThat(testCursor.getInt(0), is(1));
+ assertThat(testCursor.getString(1), is("InstantAppProvider"));
+ }
}
@Test
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralProvider.java
new file mode 100644
index 0000000..d34d494
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp1/src/com/android/cts/ephemeralapp1/EphemeralProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.cts.ephemeralapp1;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class EphemeralProvider extends ContentProvider {
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ static {
+ sUriMatcher.addURI("com.android.cts.ephemeralapp1.provider", "table", 1);
+ }
+ private static final String[] sColumnNames = { "_ID", "name" };
+ private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+ static {
+ sCursor.newRow().add(1).add("InstantAppProvider");
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
index 06d569e..78c282b 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/EphemeralApp2/AndroidManifest.xml
@@ -43,12 +43,23 @@
<action android:name="com.android.cts.ephemeraltest.START_EPHEMERAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- </activity>
- <!-- This should still not be visible to other Instant Apps -->
- <activity
- android:name=".FakeExposedActivity"
+ </activity>
+
+ <!-- This should still not be visible to other Instant Apps -->
+ <activity
+ android:name=".ExposedActivity"
android:visibleToInstantApps="true"
android:theme="@android:style/Theme.NoDisplay" />
+
+ <!-- This should still not be visible to other Instant Apps -->
+ <provider
+ android:name=".EphemeralProvider"
+ android:authorities="com.android.cts.ephemeralapp2.provider"
+ android:exported="true">
+ <intent-filter android:priority="0">
+ <action android:name="com.android.cts.ephemeraltest.QUERY" />
+ </intent-filter>
+ </provider>
</application>
<instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
index ff542a4..4c27dba 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/AndroidManifest.xml
@@ -64,6 +64,7 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
+
<service
android:name=".NormalService">
<!-- TEST: ephemeral apps can't see this service using query methods -->
@@ -91,6 +92,24 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
+
+ <provider
+ android:name=".NormalProvider"
+ android:authorities="com.android.cts.normalapp.provider"
+ android:exported="true">
+ <intent-filter android:priority="-20">
+ <action android:name="com.android.cts.ephemeraltest.QUERY" />
+ </intent-filter>
+ </provider>
+ <provider
+ android:name=".ExposedProvider"
+ android:authorities="com.android.cts.normalapp.exposed.provider"
+ android:visibleToInstantApps="true"
+ android:exported="true">
+ <intent-filter android:priority="-10">
+ <action android:name="com.android.cts.ephemeraltest.QUERY" />
+ </intent-filter>
+ </provider>
</application>
<instrumentation
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
index d428158..14ee824 100644
--- a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ClientTest.java
@@ -17,6 +17,8 @@
package com.android.cts.normalapp;
import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@@ -27,6 +29,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ResolveInfo;
+import android.database.Cursor;
import android.net.Uri;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -83,9 +86,9 @@
@Test
public void testQuery() throws Exception {
- final Intent queryIntent = new Intent(ACTION_QUERY);
// query activities without flags
{
+ final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
@@ -108,6 +111,7 @@
// query activities asking for ephemeral apps [we should only get normal apps]
{
+ final Intent queryIntent = new Intent(ACTION_QUERY);
final int MATCH_EPHEMERAL = 0x00800000;
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
@@ -130,8 +134,29 @@
is(false));
}
+ // query activities; directed package
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setPackage("com.android.cts.ephemeralapp1");
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+ assertThat(resolveInfo.size(), is(0));
+ }
+
+ // query activities; directed component
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setComponent(
+ new ComponentName("com.android.cts.ephemeralapp1",
+ "com.android.cts.ephemeralapp1.EphemeralActivity"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentActivities(queryIntent, 0 /*flags*/);
+ assertThat(resolveInfo.size(), is(0));
+ }
+
// query services without flags
{
+ final Intent queryIntent = new Intent(ACTION_QUERY);
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
.getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
if (resolveInfo == null || resolveInfo.size() == 0) {
@@ -154,6 +179,7 @@
// query services asking for ephemeral apps [we should only get normal apps]
{
+ final Intent queryIntent = new Intent(ACTION_QUERY);
final int MATCH_EPHEMERAL = 0x00800000;
final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
@@ -175,6 +201,92 @@
assertThat(resolveInfo.get(1).instantAppAvailable,
is(false));
}
+
+ // query services; directed package
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setPackage("com.android.cts.ephemeralapp1");
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+ assertThat(resolveInfo.size(), is(0));
+ }
+
+ // query services; directed component
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setComponent(
+ new ComponentName("com.android.cts.ephemeralapp1",
+ "com.android.cts.ephemeralapp1.EphemeralService"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentServices(queryIntent, 0 /*flags*/);
+ assertThat(resolveInfo.size(), is(0));
+ }
+
+ // query content providers without flags
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry
+ .getContext().getPackageManager().queryIntentContentProviders(
+ queryIntent, 0 /*flags*/);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(2));
+ assertThat(resolveInfo.get(0).providerInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(0).providerInfo.name,
+ is("com.android.cts.normalapp.ExposedProvider"));
+ assertThat(resolveInfo.get(1).providerInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(1).providerInfo.name,
+ is("com.android.cts.normalapp.NormalProvider"));
+ assertThat(resolveInfo.get(1).instantAppAvailable,
+ is(false));
+ }
+
+ // query content providers asking for ephemeral apps [we should only get normal apps]
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ final int MATCH_EPHEMERAL = 0x00800000;
+
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentContentProviders(
+ queryIntent, MATCH_EPHEMERAL);
+ if (resolveInfo == null || resolveInfo.size() == 0) {
+ fail("didn't resolve any intents");
+ }
+ assertThat(resolveInfo.size(), is(2));
+ assertThat(resolveInfo.get(0).providerInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(0).providerInfo.name,
+ is("com.android.cts.normalapp.ExposedProvider"));
+ assertThat(resolveInfo.get(1).providerInfo.packageName,
+ is("com.android.cts.normalapp"));
+ assertThat(resolveInfo.get(1).providerInfo.name,
+ is("com.android.cts.normalapp.NormalProvider"));
+ assertThat(resolveInfo.get(1).instantAppAvailable,
+ is(false));
+ }
+
+ // query content providers; directed package
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setPackage("com.android.cts.ephemeralapp1");
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentContentProviders(queryIntent, 0 /*flags*/);
+ assertThat(resolveInfo.size(), is(0));
+ }
+
+ // query content providers; directed component
+ {
+ final Intent queryIntent = new Intent(ACTION_QUERY);
+ queryIntent.setComponent(
+ new ComponentName("com.android.cts.ephemeralapp1",
+ "com.android.cts.ephemeralapp1.EphemeralProvider"));
+ final List<ResolveInfo> resolveInfo = InstrumentationRegistry.getContext()
+ .getPackageManager().queryIntentContentProviders(queryIntent, 0 /*flags*/);
+ assertThat(resolveInfo.size(), is(0));
+ }
}
@Test
@@ -220,6 +332,24 @@
assertThat(testResult.getException(),
is("android.content.pm.PackageManager$NameNotFoundException"));
}
+
+ // connect to the normal provider
+ {
+ final String provider = "content://com.android.cts.normalapp.provider/table";
+ final Cursor testCursor = InstrumentationRegistry
+ .getContext().getContentResolver().query(
+ Uri.parse(provider),
+ null /*projection*/,
+ null /*selection*/,
+ null /*selectionArgs*/,
+ null /*sortOrder*/);
+ assertThat(testCursor, is(notNullValue()));
+ assertThat(testCursor.getCount(), is(1));
+ assertThat(testCursor.getColumnCount(), is(2));
+ assertThat(testCursor.moveToFirst(), is(true));
+ assertThat(testCursor.getInt(0), is(1));
+ assertThat(testCursor.getString(1), is("NormalProvider"));
+ }
}
@Test
@@ -269,6 +399,19 @@
assertThat("com.android.cts.ephemeralapp1", is(testResult.getPackageName()));
assertThat("EphemeralActivity", is(testResult.getComponentName()));
}
+
+ // connect to the instant app provider
+ {
+ final String provider = "content://com.android.cts.ephemeralapp1.provider/table";
+ final Cursor testCursor = InstrumentationRegistry
+ .getContext().getContentResolver().query(
+ Uri.parse(provider),
+ null /*projection*/,
+ null /*selection*/,
+ null /*selectionArgs*/,
+ null /*sortOrder*/);
+ assertThat(testCursor, is(nullValue()));
+ }
}
private TestResult getResult() {
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedProvider.java
new file mode 100644
index 0000000..99658d4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/ExposedProvider.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.cts.normalapp;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+import com.android.cts.util.TestResult;
+
+public class ExposedProvider extends ContentProvider {
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ static {
+ sUriMatcher.addURI("com.android.cts.normalapp.exposed.provider", "table", 1);
+ }
+ private static final String[] sColumnNames = { "_ID", "name" };
+ private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+ static {
+ sCursor.newRow().add(1).add("ExposedProvider");
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ boolean canAccessInstantApp = false;
+ String exception = null;
+ try {
+ canAccessInstantApp = tryAccessingInstantApp();
+ } catch (Throwable t) {
+ exception = t.getClass().getName();
+ }
+
+ TestResult.getBuilder()
+ .setPackageName("com.android.cts.normalapp")
+ .setComponentName("ExposedProvider")
+ .setStatus("PASS")
+ .setException(exception)
+ .setEphemeralPackageInfoExposed(canAccessInstantApp)
+ .build()
+ .broadcast(getContext());
+
+ return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+ }
+
+ private boolean tryAccessingInstantApp() throws NameNotFoundException {
+ final PackageInfo info = getContext().getPackageManager()
+ .getPackageInfo("com.android.cts.ephemeralapp1", 0 /*flags*/);
+ return (info != null);
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalProvider.java b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalProvider.java
new file mode 100644
index 0000000..8351a27
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/EphemeralTestApp/NormalApp/src/com/android/cts/normalapp/NormalProvider.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.cts.normalapp;
+
+import android.content.ContentProvider;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.CharArrayBuffer;
+import android.database.ContentObserver;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.os.Bundle;
+
+public class NormalProvider extends ContentProvider {
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+ static {
+ sUriMatcher.addURI("com.android.cts.normalapp.provider", "table", 1);
+ }
+ private static final String[] sColumnNames = { "_ID", "name" };
+ private static final MatrixCursor sCursor = new MatrixCursor(sColumnNames, 1);
+ static {
+ sCursor.newRow().add(1).add("NormalProvider");
+ }
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return (sUriMatcher.match(uri) != 1) ? null : sCursor;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+}
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
index 22eaaea..9778f12 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/StorageTest.java
@@ -41,6 +41,7 @@
import java.io.File;
import java.io.IOException;
+import java.util.UUID;
/**
* Client app for verifying storage behaviors.
@@ -85,8 +86,10 @@
public void testVerifySpaceApi() throws Exception {
final StorageManager sm = getContext().getSystemService(StorageManager.class);
- final long cacheSize = sm.getCacheSizeBytes(getContext().getCacheDir());
- final long extCacheSize = sm.getCacheSizeBytes(getContext().getExternalCacheDir());
+ final long cacheSize = sm.getCacheSizeBytes(
+ sm.getUuidForPath(getContext().getCacheDir()));
+ final long extCacheSize = sm.getCacheSizeBytes(
+ sm.getUuidForPath(getContext().getExternalCacheDir()));
if (cacheSize == extCacheSize) {
assertMostlyEquals(CACHE_ALL, cacheSize);
} else {
@@ -97,22 +100,28 @@
public void testVerifyQuotaApi() throws Exception {
final StorageManager sm = getContext().getSystemService(StorageManager.class);
- assertTrue("Apps must have at least 10MB quota",
- sm.getCacheQuotaBytes(getContext().getCacheDir()) > 10 * MB_IN_BYTES);
+
+ final long cacheSize = sm.getCacheQuotaBytes(
+ sm.getUuidForPath(getContext().getCacheDir()));
+ assertTrue("Apps must have at least 10MB quota", cacheSize > 10 * MB_IN_BYTES);
}
public void testVerifyAllocateApi() throws Exception {
final StorageManager sm = getContext().getSystemService(StorageManager.class);
final File filesDir = getContext().getFilesDir();
- assertTrue("Apps must be able to allocate internal space",
- sm.getAllocatableBytes(filesDir, 0) > 10 * MB_IN_BYTES);
final File extDir = Environment.getExternalStorageDirectory();
+
+ final UUID filesUuid = sm.getUuidForPath(filesDir);
+ final UUID extUuid = sm.getUuidForPath(extDir);
+
+ assertTrue("Apps must be able to allocate internal space",
+ sm.getAllocatableBytes(filesUuid, 0) > 10 * MB_IN_BYTES);
assertTrue("Apps must be able to allocate external space",
- sm.getAllocatableBytes(extDir, 0) > 10 * MB_IN_BYTES);
+ sm.getAllocatableBytes(extUuid, 0) > 10 * MB_IN_BYTES);
// Should always be able to allocate 1MB indirectly
- sm.allocateBytes(filesDir, 1 * MB_IN_BYTES, 0);
+ sm.allocateBytes(filesUuid, 1 * MB_IN_BYTES, 0);
// Should always be able to allocate 1MB directly
final File filesFile = makeUniqueFile(filesDir);
diff --git a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
index bab84aa..2845185 100644
--- a/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
+++ b/hostsidetests/appsecurity/test-apps/StorageApp/src/com/android/cts/storageapp/UtilsReceiver.java
@@ -50,13 +50,13 @@
public static Bundle doAllocation(Context context, Bundle extras) {
final StorageManager sm = context.getSystemService(StorageManager.class);
- final double fraction = extras.getDouble(EXTRA_FRACTION, 0);
- final long quota = sm.getCacheQuotaBytes(context.getCacheDir());
- final long bytes = (long) (quota * fraction);
- final long time = extras.getLong(EXTRA_TIME, System.currentTimeMillis());
-
long allocated = 0;
try {
+ final double fraction = extras.getDouble(EXTRA_FRACTION, 0);
+ final long quota = sm.getCacheQuotaBytes(sm.getUuidForPath(context.getCacheDir()));
+ final long bytes = (long) (quota * fraction);
+ final long time = extras.getLong(EXTRA_TIME, System.currentTimeMillis());
+
while (allocated < bytes) {
final File f = makeUniqueFile(context.getCacheDir());
final long size = 1024 * 1024;
@@ -64,15 +64,15 @@
f.setLastModified(time);
allocated += Os.stat(f.getAbsolutePath()).st_blocks * 512;
}
+
+ Log.d(TAG, "Quota " + quota + ", target " + bytes + ", allocated " + allocated);
+
+ final Bundle res = new Bundle();
+ res.putLong(EXTRA_BYTES, allocated);
+ return res;
} catch (Exception e) {
Log.e(TAG, "Failed to allocate cache files", e);
return null;
}
-
- Log.d(TAG, "Quota " + quota + ", target " + bytes + ", allocated " + allocated);
-
- final Bundle res = new Bundle();
- res.putLong(EXTRA_BYTES, allocated);
- return res;
}
}
diff --git a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
index 72a420d..41439f0 100644
--- a/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
+++ b/hostsidetests/appsecurity/test-apps/StorageStatsApp/src/com/android/cts/storagestatsapp/StorageStatsTest.java
@@ -16,6 +16,8 @@
package com.android.cts.storagestatsapp;
+import static android.os.storage.StorageManager.UUID_DEFAULT;
+
import static com.android.cts.storageapp.Utils.CACHE_ALL;
import static com.android.cts.storageapp.Utils.DATA_ALL;
import static com.android.cts.storageapp.Utils.MB_IN_BYTES;
@@ -54,6 +56,7 @@
import com.android.cts.storageapp.UtilsReceiver;
import java.io.File;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -81,15 +84,18 @@
.getSystemService(StorageStatsManager.class);
assertTrue("You're running kernel 3.18 or newer (" + uname.release + ") which "
+ "means that CONFIG_QUOTA, CONFIG_QFMT_V2, CONFIG_QUOTACTL and the "
- + "'quota' fstab option on /data are required", stats.isQuotaSupported(null));
+ + "'quota' fstab option on /data are required",
+ stats.isQuotaSupported(UUID_DEFAULT));
}
}
public void testVerifySummary() throws Exception {
final StorageStatsManager stats = getContext().getSystemService(StorageStatsManager.class);
- assertAtLeast(Environment.getDataDirectory().getTotalSpace(), stats.getTotalBytes(null));
- assertAtLeast(Environment.getDataDirectory().getUsableSpace(), stats.getFreeBytes(null));
+ assertAtLeast(Environment.getDataDirectory().getTotalSpace(),
+ stats.getTotalBytes(UUID_DEFAULT));
+ assertAtLeast(Environment.getDataDirectory().getUsableSpace(),
+ stats.getFreeBytes(UUID_DEFAULT));
}
public void testVerifyStats() throws Exception {
@@ -97,13 +103,13 @@
final int uid = android.os.Process.myUid();
final UserHandle user = UserHandle.getUserHandleForUid(uid);
- final StorageStats beforeApp = stats.queryStatsForUid(null, uid);
- final StorageStats beforeUser = stats.queryStatsForUser(null, user);
+ final StorageStats beforeApp = stats.queryStatsForUid(UUID_DEFAULT, uid);
+ final StorageStats beforeUser = stats.queryStatsForUser(UUID_DEFAULT, user);
useSpace(getContext());
- final StorageStats afterApp = stats.queryStatsForUid(null, uid);
- final StorageStats afterUser = stats.queryStatsForUser(null, user);
+ final StorageStats afterApp = stats.queryStatsForUid(UUID_DEFAULT, uid);
+ final StorageStats afterUser = stats.queryStatsForUser(UUID_DEFAULT, user);
final long deltaData = DATA_ALL;
assertMostlyEquals(deltaData, afterApp.getDataBytes() - beforeApp.getDataBytes());
@@ -121,8 +127,8 @@
final ApplicationInfo a = pm.getApplicationInfo(PKG_A, 0);
final ApplicationInfo b = pm.getApplicationInfo(PKG_B, 0);
- final StorageStats as = stats.queryStatsForUid(null, a.uid);
- final StorageStats bs = stats.queryStatsForUid(null, b.uid);
+ final StorageStats as = stats.queryStatsForUid(UUID_DEFAULT, a.uid);
+ final StorageStats bs = stats.queryStatsForUid(UUID_DEFAULT, b.uid);
assertMostlyEquals(DATA_ALL * 2, as.getDataBytes());
assertMostlyEquals(CACHE_ALL * 2, as.getCacheBytes());
@@ -140,7 +146,7 @@
final int uid = android.os.Process.myUid();
final UserHandle user = UserHandle.getUserHandleForUid(uid);
- final ExternalStorageStats before = stats.queryExternalStatsForUser(null, user);
+ final ExternalStorageStats before = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
final File dir = Environment.getExternalStorageDirectory();
final File downloadsDir = Environment.getExternalStoragePublicDirectory(
@@ -158,7 +164,7 @@
useWrite(audio, 5 * MB_IN_BYTES);
useWrite(internal, 7 * MB_IN_BYTES);
- final ExternalStorageStats afterInit = stats.queryExternalStatsForUser(null, user);
+ final ExternalStorageStats afterInit = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
assertMostlyEquals(17 * MB_IN_BYTES, afterInit.getTotalBytes() - before.getTotalBytes());
assertMostlyEquals(5 * MB_IN_BYTES, afterInit.getAudioBytes() - before.getAudioBytes());
@@ -168,7 +174,7 @@
// Rename to ensure that stats are updated
video.renameTo(new File(dir, System.nanoTime() + ".PnG"));
- final ExternalStorageStats afterRename = stats.queryExternalStatsForUser(null, user);
+ final ExternalStorageStats afterRename = stats.queryExternalStatsForUser(UUID_DEFAULT, user);
assertMostlyEquals(17 * MB_IN_BYTES, afterRename.getTotalBytes() - before.getTotalBytes());
assertMostlyEquals(5 * MB_IN_BYTES, afterRename.getAudioBytes() - before.getAudioBytes());
@@ -199,7 +205,7 @@
logCommand("sync");
final long manualSize = getSizeManual(Environment.getExternalStorageDirectory());
- final long statsSize = stats.queryExternalStatsForUser(null, user).getTotalBytes();
+ final long statsSize = stats.queryExternalStatsForUser(UUID_DEFAULT, user).getTotalBytes();
assertMostlyEquals(manualSize, statsSize);
}
@@ -220,9 +226,10 @@
final UserHandle user = android.os.Process.myUserHandle();
final File filesDir = context.getFilesDir();
+ final UUID filesUuid = sm.getUuidForPath(filesDir);
- final long beforeAllocatable = sm.getAllocatableBytes(filesDir, 0);
- final long beforeFree = stats.getFreeBytes(null);
+ final long beforeAllocatable = sm.getAllocatableBytes(filesUuid, 0);
+ final long beforeFree = stats.getFreeBytes(UUID_DEFAULT);
final long beforeRaw = filesDir.getUsableSpace();
Log.d(TAG, "Before raw " + beforeRaw + ", free " + beforeFree + ", allocatable "
@@ -239,16 +246,16 @@
// Apps using up some cache space shouldn't change how much we can
// allocate, or how much we think is free; but it should decrease real
// disk space.
- if (stats.isQuotaSupported(null)) {
+ if (stats.isQuotaSupported(UUID_DEFAULT)) {
assertMostlyEquals(beforeAllocatable,
- sm.getAllocatableBytes(filesDir, 0), 10 * MB_IN_BYTES);
+ sm.getAllocatableBytes(filesUuid, 0), 10 * MB_IN_BYTES);
assertMostlyEquals(beforeFree,
- stats.getFreeBytes(null), 10 * MB_IN_BYTES);
+ stats.getFreeBytes(UUID_DEFAULT), 10 * MB_IN_BYTES);
} else {
assertMostlyEquals(beforeAllocatable - totalAllocated,
- sm.getAllocatableBytes(filesDir, 0), 10 * MB_IN_BYTES);
+ sm.getAllocatableBytes(filesUuid, 0), 10 * MB_IN_BYTES);
assertMostlyEquals(beforeFree - totalAllocated,
- stats.getFreeBytes(null), 10 * MB_IN_BYTES);
+ stats.getFreeBytes(UUID_DEFAULT), 10 * MB_IN_BYTES);
}
assertMostlyEquals(beforeRaw - totalAllocated,
filesDir.getUsableSpace(), 10 * MB_IN_BYTES);
@@ -259,7 +266,7 @@
// Allocate some space for ourselves, which should trim away at
// over-quota app first, even though its files are newer.
final long clear1 = filesDir.getUsableSpace() + (targetB / 2);
- sm.allocateBytes(filesDir, clear1, 0);
+ sm.allocateBytes(filesUuid, clear1, 0);
assertMostlyEquals(targetA, getCacheBytes(PKG_A, user));
assertMostlyEquals(targetB / 2, getCacheBytes(PKG_B, user), 2 * MB_IN_BYTES);
@@ -269,7 +276,7 @@
// they're tied for cache ratios, we expect to clear about half of the
// remaining space from each of them.
final long clear2 = filesDir.getUsableSpace() + (targetB / 2);
- sm.allocateBytes(filesDir, clear2, 0);
+ sm.allocateBytes(filesUuid, clear2, 0);
assertMostlyEquals(targetA / 2, getCacheBytes(PKG_A, user), 2 * MB_IN_BYTES);
assertMostlyEquals(targetA / 2, getCacheBytes(PKG_B, user), 2 * MB_IN_BYTES);
@@ -313,7 +320,7 @@
tomb.setLastModified(tombTime);
final long clear1 = group.getUsableSpace() + (8 * MB_IN_BYTES);
- sm.allocateBytes(group, clear1, 0);
+ sm.allocateBytes(sm.getUuidForPath(group), clear1, 0);
assertTrue(a.exists());
assertTrue(b.exists());
@@ -327,9 +334,9 @@
assertTrue(i.exists()); assertEquals(0, i.length());
}
- private long getCacheBytes(String pkg, UserHandle user) {
+ private long getCacheBytes(String pkg, UserHandle user) throws Exception {
return getContext().getSystemService(StorageStatsManager.class)
- .queryStatsForPackage(null, pkg, user).getCacheBytes();
+ .queryStatsForPackage(UUID_DEFAULT, pkg, user).getCacheBytes();
}
private long doAllocateReceiver(String pkg, double fraction, long time) throws Exception {
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java
index 302f9da..c9cf648 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/DelegationTest.java
@@ -44,6 +44,7 @@
private static final String DELEGATE_PKG = "com.android.cts.delegate";
private static final String DELEGATE_ACTIVITY_NAME =
DELEGATE_PKG + ".DelegatedScopesReceiverActivity";
+ private static final String TEST_PKG = "com.android.cts.apprestrictions.targetapp";
// Broadcasts received from the delegate app.
private static final String ACTION_REPORT_SCOPES = "com.android.cts.delegate.report_scopes";
@@ -130,6 +131,53 @@
.getDelegatedScopes(ADMIN_RECEIVER_COMPONENT, NON_EXISTENT_PKG).isEmpty());
}
+ public void testCanRetrieveDelegates() {
+ final List<String> someScopes = Arrays.asList(
+ DELEGATION_APP_RESTRICTIONS,
+ DELEGATION_ENABLE_SYSTEM_APP);
+ final List<String> otherScopes = Arrays.asList(
+ DELEGATION_BLOCK_UNINSTALL,
+ DELEGATION_ENABLE_SYSTEM_APP);
+
+ // In the beginning there are no delegates.
+ assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_APP_RESTRICTIONS)
+ .isEmpty());
+ assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL)
+ .isEmpty());
+ assertTrue("No delegates should be found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP)
+ .isEmpty());
+
+ // After delegating scopes to two packages.
+ mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT,
+ DELEGATE_PKG, someScopes);
+ mDevicePolicyManager.setDelegatedScopes(ADMIN_RECEIVER_COMPONENT,
+ TEST_PKG, otherScopes);
+
+ // The expected delegates are returned.
+ assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_APP_RESTRICTIONS)
+ .contains(DELEGATE_PKG));
+ assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL)
+ .contains(TEST_PKG));
+ assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP)
+ .contains(DELEGATE_PKG));
+ assertTrue("Expected delegate not found", getDelegatePackages(DELEGATION_ENABLE_SYSTEM_APP)
+ .contains(TEST_PKG));
+
+ // Packages are only returned in their recpective scopes.
+ assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_APP_RESTRICTIONS)
+ .contains(TEST_PKG));
+ assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_BLOCK_UNINSTALL)
+ .contains(DELEGATE_PKG));
+ assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_CERT_INSTALL)
+ .contains(DELEGATE_PKG));
+ assertFalse("Unexpected delegate package", getDelegatePackages(DELEGATION_CERT_INSTALL)
+ .contains(TEST_PKG));
+ }
+
+ private List<String> getDelegatePackages(String scope) {
+ return mDevicePolicyManager.getDelegatePackages(ADMIN_RECEIVER_COMPONENT, scope);
+ }
+
private void startAndWaitDelegateActivity() throws InterruptedException {
mContext.startActivity(new Intent()
.setComponent(new ComponentName(DELEGATE_PKG, DELEGATE_ACTIVITY_NAME))
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java
index ff51e9e..0694d76 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AdminActionBookkeepingTest.java
@@ -16,7 +16,6 @@
package com.android.cts.deviceowner;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.os.Process;
@@ -25,7 +24,6 @@
import com.android.org.conscrypt.TrustedCertificateStore;
import java.io.ByteArrayInputStream;
-import java.lang.reflect.Method;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.List;
@@ -133,9 +131,7 @@
mDevicePolicyManager.setNetworkLoggingEnabled(getWho(), true);
long timeBefore = System.currentTimeMillis();
- final Method retrieveNetworkLogsMethod = DevicePolicyManager.class.getDeclaredMethod(
- "retrieveNetworkLogs", ComponentName.class, long.class);
- retrieveNetworkLogsMethod.invoke(mDevicePolicyManager, getWho(), 0 /* batchToken */);
+ mDevicePolicyManager.retrieveNetworkLogs(getWho(), 0 /* batchToken */);
long timeAfter = System.currentTimeMillis();
final long newTimestamp = mDevicePolicyManager.getLastNetworkLogRetrievalTime();
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
index 7528cac..4570cdf 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsBgVsFgActions.java
@@ -16,11 +16,14 @@
package com.android.server.cts.device.batterystats;
+import android.accounts.Account;
+import android.app.Activity;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -31,6 +34,7 @@
import android.os.Looper;
import android.util.Log;
+
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -40,6 +44,7 @@
public static final String KEY_ACTION = "action";
public static final String ACTION_JOB_SCHEDULE = "action.jobs";
+ public static final String ACTION_SYNC = "action.sync";
public static final String ACTION_WIFI_SCAN = "action.wifi_scan";
/** Perform the action specified by the given action code (see constants above). */
@@ -53,6 +58,9 @@
case ACTION_JOB_SCHEDULE:
doScheduleJob(ctx);
break;
+ case ACTION_SYNC:
+ doSync(ctx);
+ break;
case ACTION_WIFI_SCAN:
doWifi(ctx);
break;
@@ -86,6 +94,41 @@
}.execute();
}
+ private static void doSync(Context ctx) {
+ BatteryStatsAuthenticator.removeAllAccounts(ctx);
+ final Account account = BatteryStatsAuthenticator.getTestAccount();
+ // Create the test account.
+ BatteryStatsAuthenticator.ensureTestAccount(ctx);
+ // Force set is syncable.
+ ContentResolver.setMasterSyncAutomatically(true);
+ ContentResolver.setIsSyncable(account, BatteryStatsProvider.AUTHORITY, 1);
+
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ Log.v(TAG, "Starting sync");
+ BatteryStatsSyncAdapter.requestSync(account);
+ sleep(500);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception trying to sync", e);
+ }
+ BatteryStatsAuthenticator.removeAllAccounts(ctx);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void aVoid) {
+ super.onPostExecute(aVoid);
+ Log.v(TAG, "Finished sync method");
+ // If ctx is an Activity, finish it when sync is done. If it's a service, don't.
+ if(ctx instanceof Activity){
+ ((Activity) ctx).finish();
+ }
+ }
+ }.execute();
+ }
+
private static void doWifi(Context ctx) {
IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
CountDownLatch onReceiveLatch = new CountDownLatch(1);
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
index d6869a1..c41b244 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsForegroundActivity.java
@@ -18,6 +18,7 @@
import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions
.ACTION_JOB_SCHEDULE;
+import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.ACTION_SYNC;
import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.KEY_ACTION;
import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.doAction;
import static com.android.server.cts.device.batterystats.BatteryStatsBgVsFgActions.isAppInBackground;
@@ -51,7 +52,12 @@
Log.w(TAG, "Couldn't determine if app is in foreground. Proceeding with test anyway");
}
- doAction(this, intent.getStringExtra(KEY_ACTION));
- finish();
+ String action = intent.getStringExtra(KEY_ACTION);
+ doAction(this, action);
+
+ // ACTION_SYNC will finish itself. Others get finished here.
+ if (!ACTION_SYNC.equals(action)) {
+ finish();
+ }
}
}
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java
index c619166..c40c950 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsProcessStateTests.java
@@ -34,12 +34,7 @@
public void testForegroundService() throws Exception {
Intent intent = new Intent();
intent.setClass(mContext, SimpleForegroundService.class);
- Notification notification = new Notification.Builder(mContext, "Foreground Service")
- .setContentTitle("CTS Foreground")
- .setSmallIcon(android.R.drawable.ic_secure)
- .build();
- mContext.getSystemService(NotificationManager.class).startServiceInForeground(intent,
- 1, notification);
+ mContext.startForegroundService(intent);
Thread.sleep(3000);
}
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
index 394a070..de0954d 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/BatteryStatsWifiTransferTests.java
@@ -63,6 +63,9 @@
/** String extra of any error encountered during wifi transfer. */
private static final String EXTRA_TRANSFER_ERROR = "transfer_error";
+ /** String extra: the service is required to startForeground() */
+ private static final String EXTRA_FOREGROUND = "fg";
+
private static final int READ_BUFFER_SIZE = 4096;
/** Server to send requests to. */
@@ -120,15 +123,10 @@
if (!mHasFeature) {
return;
}
- mTransferService.putExtra(EXTRA_ACTION, action);
- Notification notification =
- new Notification.Builder(mContext, "Wifi Transfer Foreground Service")
- .setContentTitle("Wifi Transfer Foreground")
- .setContentText("Wifi Transfer Foreground")
- .setSmallIcon(android.R.drawable.ic_secure)
- .build();
- mContext.getSystemService(NotificationManager.class).startServiceInForeground(mTransferService,
- 1, notification);
+ Intent launchIntent = new Intent(mTransferService)
+ .putExtra(EXTRA_ACTION, action)
+ .putExtra(EXTRA_FOREGROUND, true);
+ mContext.startForegroundService(launchIntent);
mResultsReceivedSignal.await(10, TimeUnit.SECONDS);
assertTrue("Got error: " + mError, mError == null);
@@ -155,6 +153,16 @@
@Override
protected void onHandleIntent(Intent intent) {
+ if (intent.getBooleanExtra(EXTRA_FOREGROUND, false)) {
+ Notification notification =
+ new Notification.Builder(this, "Wifi Transfer Foreground Service")
+ .setContentTitle("Wifi Transfer Foreground")
+ .setContentText("Wifi Transfer Foreground")
+ .setSmallIcon(android.R.drawable.ic_secure)
+ .build();
+ startForeground(1, notification);
+ }
+
String error = null;
switch (intent.getStringExtra(EXTRA_ACTION)) {
case ACTION_DOWNLOAD:
diff --git a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java
index b8d4507..ed21615 100644
--- a/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java
+++ b/hostsidetests/incident/apps/batterystatsapp/src/com/android/server/cts/device/batterystats/SimpleForegroundService.java
@@ -16,6 +16,7 @@
package com.android.server.cts.device.batterystats;
+import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
@@ -67,6 +68,12 @@
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
+ Notification notification = new Notification.Builder(this, "Foreground Service")
+ .setContentTitle("CTS Foreground")
+ .setSmallIcon(android.R.drawable.ic_secure)
+ .build();
+ startForeground(1, notification);
+
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
diff --git a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
index f6e9e31..3a96ccb 100644
--- a/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
+++ b/hostsidetests/incident/src/com/android/server/cts/BatteryStatsValidationTest.java
@@ -42,6 +42,7 @@
// Constants from BatteryStatsBgVsFgActions.java (not directly accessible here).
public static final String KEY_ACTION = "action";
public static final String ACTION_JOB_SCHEDULE = "action.jobs";
+ public static final String ACTION_SYNC = "action.sync";
public static final String ACTION_WIFI_SCAN = "action.wifi_scan";
@Override
@@ -136,6 +137,26 @@
batteryOffScreenOn();
}
+ public void testSyncBgVsFg() throws Exception {
+ batteryOnScreenOff();
+ installPackage(DEVICE_SIDE_TEST_APK, true);
+
+ // Foreground test.
+ executeForeground(ACTION_SYNC);
+ Thread.sleep(3_000);
+ // Allow one or two syncs in this time frame (not just one) due to unpredictable syncs.
+ assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 1, 2); // count
+ assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 0, 0); // background_count
+
+ // Background test.
+ executeBackground(ACTION_SYNC);
+ Thread.sleep(3_000);
+ assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 6, 2, 4); // count
+ assertValueRange("sy", DEVICE_SIDE_SYNC_COMPONENT, 8, 1, 2); // background_count
+
+ batteryOffScreenOn();
+ }
+
public void testWifiScans() throws Exception {
batteryOnScreenOff();
installPackage(DEVICE_SIDE_TEST_APK, true);
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index 2fc0bc2..0f2965c 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -143,6 +143,8 @@
assertBackgroundNetworkAccess(true);
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
+ // Use setBatterySaverMode API to leave power-save mode instead of plugging in charger
+ setBatterySaverMode(false);
turnBatteryOn();
assertBackgroundNetworkAccess(true);
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index 15daed9..b6857ae 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -100,6 +100,7 @@
protected ConnectivityManager mCm;
protected WifiManager mWfm;
protected int mUid;
+ private int mMyUid;
private String mMeteredWifi;
private MyServiceClient mServiceClient;
private boolean mHasWatch;
@@ -115,7 +116,7 @@
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mWfm = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mUid = getUid(TEST_APP2_PKG);
- final int myUid = getUid(mContext.getPackageName());
+ mMyUid = getUid(mContext.getPackageName());
mServiceClient = new MyServiceClient(mContext);
mServiceClient.bind();
mHasWatch = mContext.getPackageManager().hasSystemFeature(
@@ -128,7 +129,7 @@
mSupported = setUpActiveNetworkMeteringState();
Log.i(TAG, "Apps status on " + getName() + ":\n"
- + "\ttest app: uid=" + myUid + ", state=" + getProcessStateByUid(myUid) + "\n"
+ + "\ttest app: uid=" + mMyUid + ", state=" + getProcessStateByUid(mMyUid) + "\n"
+ "\tapp2: uid=" + mUid + ", state=" + getProcessStateByUid(mUid));
}
@@ -204,6 +205,21 @@
assertEquals("wrong status", toString(expectedStatus), actualStatus);
}
+ protected void assertMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+ final int actualStatus = mCm.getRestrictBackgroundStatus();
+ assertEquals("Wrong status", toString(expectedStatus), toString(actualStatus));
+ }
+
+ protected boolean isMyRestrictBackgroundStatus(int expectedStatus) throws Exception {
+ final int actualStatus = mCm.getRestrictBackgroundStatus();
+ if (expectedStatus != actualStatus) {
+ Log.d(TAG, "Expected: " + toString(expectedStatus)
+ + " but actual: " + toString(actualStatus));
+ return false;
+ }
+ return true;
+ }
+
protected void assertBackgroundNetworkAccess(boolean expectAllowed) throws Exception {
assertBackgroundState(); // Sanity check.
assertNetworkAccess(expectAllowed);
@@ -700,9 +716,9 @@
Log.i(TAG, "Setting Battery Saver Mode to " + enabled);
if (enabled) {
turnBatteryOff();
- executeSilentShellCommand("settings put global low_power 1");
+ executeSilentShellCommand("cmd power set-mode 1");
} else {
- executeSilentShellCommand("settings put global low_power 0");
+ executeSilentShellCommand("cmd power set-mode 0");
turnBatteryOn();
}
}
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index c3537c8..599a31c 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -20,16 +20,21 @@
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED;
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
+import android.util.Log;
+
public class DataSaverModeTest extends AbstractRestrictBackgroundNetworkTestCase {
private static final String[] REQUIRED_WHITELISTED_PACKAGES = {
"com.android.providers.downloads"
};
+ private boolean mIsDataSaverSupported;
+
@Override
public void setUp() throws Exception {
super.setUp();
+ mIsDataSaverSupported = isDataSaverSupported();
if (!isSupported()) return;
// Set initial state.
@@ -59,6 +64,32 @@
return setMeteredNetwork();
}
+ @Override
+ protected boolean isSupported() throws Exception {
+ if (!mIsDataSaverSupported) {
+ Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ + "() because device does not support Data Saver Mode");
+ }
+ return mIsDataSaverSupported && super.isSupported();
+ }
+
+ /**
+ * As per CDD requirements, if the device doesn't support data saver mode then
+ * ConnectivityManager.getRestrictBackgroundStatus() will always return
+ * RESTRICT_BACKGROUND_STATUS_DISABLED. So, enable the data saver mode and check if
+ * ConnectivityManager.getRestrictBackgroundStatus() for an app in background returns
+ * RESTRICT_BACKGROUND_STATUS_DISABLED or not.
+ */
+ private boolean isDataSaverSupported() throws Exception {
+ assertMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+ try {
+ setRestrictBackground(true);
+ return !isMyRestrictBackgroundStatus(RESTRICT_BACKGROUND_STATUS_DISABLED);
+ } finally {
+ setRestrictBackground(false);
+ }
+ }
+
public void testGetRestrictBackgroundStatus_disabled() throws Exception {
if (!isSupported()) return;
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 8ed60e6..46779de 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -251,9 +251,9 @@
/**
* Asserts that no vendor domains are exempted from the prohibition on Binder use.
*
- * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
- * during Android O development. This test will be removed before Android O.
- * TODO(b/35870313): Remove this test once b/35870313 is fixed.
+ * <p>NOTE: binder_in_vendor_violators attribute is only there to help bring up Treble devices.
+ * It offers a convenient way to temporarily bypass the prohibition on Binder use in vendor
+ * domains. This attribute must not be used on production Treble devices.
*/
public void testNoExemptionsForBinderInVendorBan() throws Exception {
if (!isFullTrebleDevice()) {
@@ -273,9 +273,10 @@
* Asserts that no domains are exempted from the prohibition on initiating socket communications
* between core and vendor domains.
*
- * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
- * during Android O development. This test will be removed before Android O.
- * TODO(b/36577153): Remove this test once b/36577153 is fixed.
+ * <p>NOTE: socket_between_core_and_vendor_violators attribute is only there to help bring up
+ * Treble devices. It offers a convenient way to temporarily bypass the prohibition on
+ * initiating socket communications between core and vendor domains. This attribute must not be
+ * used on production Treble devices.
*/
public void testNoExemptionsForSocketsBetweenCoreAndVendorBan() throws Exception {
if (!isFullTrebleDevice()) {
@@ -295,52 +296,25 @@
/**
* Asserts that no vendor domains are exempted from the prohibition on directly
- * accessing /data outside /data/vendor.
- *
- * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
- * during Android O development. This test will be removed before Android O.
- * TODO(b/34980020): Remove this test once b/34980020 is fixed.
- */
- public void testNoExemptionsForCoreDataInVendor() throws Exception {
+ * executing binaries from /system.
+ * */
+ public void testNoExemptionsForVendorExecutingCore() throws Exception {
if (!isFullTrebleDevice()) {
return;
}
Set<String> types =
sepolicyAnalyzeGetTypesAssociatedWithAttribute(
- "coredata_in_vendor_violators");
+ "vendor_executes_system_violators");
if (!types.isEmpty()) {
List<String> sortedTypes = new ArrayList<>(types);
Collections.sort(sortedTypes);
- fail("Policy exempts domains from ban on vendor domains accessing data partition"
- + " outside /data/vendor: " + sortedTypes);
+ fail("Policy exempts vendor domains from ban on executing files in /system: "
+ + sortedTypes);
}
}
/**
- * Asserts that no core domains are exempted from the prohibition on directly
- * accessing /data/vendor.
- *
- * <p>NOTE: There's no explicit CDD requirement for this because this is a temporary crutch
- * during Android O development. This test will be removed before Android O.
- * TODO(b/34980020): Remove this test once b/34980020 is fixed.
- */
- public void testNoExemptionsForVendorDataInCore() throws Exception {
- if (!isFullTrebleDevice()) {
- return;
- }
-
- Set<String> types =
- sepolicyAnalyzeGetTypesAssociatedWithAttribute(
- "vendordata_in_core_violators");
- if (!types.isEmpty()) {
- List<String> sortedTypes = new ArrayList<>(types);
- Collections.sort(sortedTypes);
- fail("Policy exempts domains from ban on core domains accessing vendor data"
- + " in /data/vendor: " + sortedTypes);
- }
- }
- /**
* Tests that mlstrustedsubject does not include untrusted_app
* and that mlstrustedobject does not include app_data_file.
* This helps prevent circumventing the per-user isolation of
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
index 3cdc754..d7800c4 100755
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
@@ -90,6 +90,14 @@
android:exported="true"
android:taskAffinity="nobody.but.PipActivity"
/>
+ <activity android:name=".PipActivity2"
+ android:resizeableActivity="false"
+ android:supportsPictureInPicture="true"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
+ android:exported="true"
+ android:taskAffinity="nobody.but.PipActivity2"
+ />
+
<activity android:name=".AlwaysFocusablePipActivity"
android:theme="@style/Theme.Transparent"
android:resizeableActivity="false"
@@ -325,6 +333,11 @@
android:permission="android.permission.BIND_VOICE_INTERACTION"
android:exported="true" />
+ <activity android:name=".SplashscreenActivity"
+ android:taskAffinity="nobody.but.SplashscreenActivity"
+ android:theme="@style/SplashscreenTheme"
+ android:exported="true" />
+
<service android:name="com.android.cts.verifier.vr.MockVrListenerService"
android:exported="true"
android:enabled="true"
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/colors.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/colors.xml
new file mode 100644
index 0000000..2a51310
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/colors.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2017 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
+ -->
+
+<resources>
+ <drawable name="red">#ff0000</drawable>
+</resources>
\ No newline at end of file
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml
index 7fc6725..5068ea9 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/res/values/styles.xml
@@ -40,4 +40,7 @@
<style name="NoPreview">
<item name="android:windowDisablePreview">true</item>
</style>
+ <style name="SplashscreenTheme" parent="@android:style/Theme.Material.NoActionBar">
+ <item name="android:windowSplashscreenContent">@drawable/red</item>
+ </style>
</resources>
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity2.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity2.java
new file mode 100644
index 0000000..53b4f75
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity2.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 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.server.cts;
+
+/**
+ * A secondary activity that has the same behavior as {@link PipActivity}.
+ */
+public class PipActivity2 extends PipActivity {
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SplashscreenActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SplashscreenActivity.java
new file mode 100644
index 0000000..22391bd
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/SplashscreenActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 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.server.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.SystemClock;
+
+/**
+ * Activity that shows a custom splashscreen when being launched.
+ */
+public class SplashscreenActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Make sure splash screen is visible. The test won't take 5 seconds because the condition
+ // such that we can dump the state will trigger much earlier and then the test will just
+ // kill us.
+ SystemClock.sleep(5000);
+ }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
index a31e985..8374f7c 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/VirtualDisplayActivity.java
@@ -18,8 +18,6 @@
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
-import static android.hardware.display.DisplayManager
- .VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
import android.app.Activity;
import android.content.Intent;
@@ -42,8 +40,6 @@
private static final int DEFAULT_DENSITY_DPI = 160;
private static final String KEY_DENSITY_DPI = "density_dpi";
- private static final String KEY_CAN_SHOW_WITH_INSECURE_KEYGUARD
- = "can_show_with_insecure_keyguard";
private static final String KEY_PUBLIC_DISPLAY = "public_display";
private static final String KEY_RESIZE_DISPLAY = "resize_display";
private static final String KEY_COUNT = "count";
@@ -165,20 +161,13 @@
int flags = 0;
- final boolean canShowWithInsecureKeyguard
- = entry.extras.getBoolean(KEY_CAN_SHOW_WITH_INSECURE_KEYGUARD);
- if (canShowWithInsecureKeyguard) {
- flags |= VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
- }
-
final boolean publicDisplay = entry.extras.getBoolean(KEY_PUBLIC_DISPLAY);
if (publicDisplay) {
flags |= VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
}
Log.d(TAG, "createVirtualDisplay: " + width + "x" + height + ", dpi: "
- + densityDpi + ", canShowWithInsecureKeyguard=" + canShowWithInsecureKeyguard
- + ", publicDisplay=" + publicDisplay);
+ + densityDpi + ", publicDisplay=" + publicDisplay);
try {
VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(
"VirtualDisplay" + mVirtualDisplays.size(), width,
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
index 5665c29..c89b9c4 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerActivityVisibilityTests.java
@@ -18,9 +18,15 @@
import static android.server.cts.ActivityManagerState.STATE_RESUMED;
+import android.platform.test.annotations.Presubmit;
+
import java.lang.Exception;
import java.lang.String;
+import static com.android.ddmlib.Log.LogLevel.INFO;
+
+import com.android.tradefed.log.LogUtil.CLog;
+
/**
* Build: mmma -j32 cts/hostsidetests/services
* Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerActivityVisibilityTests
@@ -142,6 +148,11 @@
}
public void testTranslucentActivityOverDockedStack() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -157,6 +168,7 @@
mAmWmState.assertVisibility(TRANSLUCENT_ACTIVITY_NAME, true);
}
+ @Presubmit
public void testTurnScreenOnActivity() throws Exception {
sleepDevice();
launchActivity(TURN_SCREEN_ON_ACTIVITY_NAME);
@@ -165,6 +177,11 @@
}
public void testFinishActivityInNonFocusedStack() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
// Launch two activities in docked stack.
launchActivityInDockStack(LAUNCHING_ACTIVITY);
getLaunchActivityBuilder().setTargetActivityName(BROADCAST_RECEIVER_ACTIVITY).execute();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
index 284f1a7..31f82ac 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerAppConfigurationTests.java
@@ -55,6 +55,11 @@
* docked state.
*/
public void testConfigurationUpdatesWhenResizedFromFullscreen() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
String logSeparator = clearLogcat();
launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
@@ -73,6 +78,11 @@
* from docked state to fullscreen (reverse).
*/
public void testConfigurationUpdatesWhenResizedFromDockedStack() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
String logSeparator = clearLogcat();
launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, DOCKED_STACK_ID);
final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME,
@@ -103,7 +113,13 @@
* Same as {@link #testConfigurationUpdatesWhenRotatingWhileFullscreen()} but when the Activity
* is in the docked stack.
*/
+ @Presubmit
public void testConfigurationUpdatesWhenRotatingWhileDocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
setDeviceRotation(0);
final String logSeparator = clearLogcat();
launchActivityInDockStack(LAUNCHING_ACTIVITY);
@@ -124,6 +140,11 @@
* is launched to side from docked stack.
*/
public void testConfigurationUpdatesWhenRotatingToSideFromDocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
setDeviceRotation(0);
final String logSeparator = clearLogcat();
@@ -171,6 +192,7 @@
/**
* Same as {@link #testSameConfigurationFullSplitFullRelaunch} but without relaunch.
*/
+ @Presubmit
public void testSameConfigurationFullSplitFullNoRelaunch() throws Exception {
moveActivityFullSplitFull(RESIZEABLE_ACTIVITY_NAME);
}
@@ -183,6 +205,11 @@
* Asserts that initial and final reported sizes in fullscreen stack are the same.
*/
private void moveActivityFullSplitFull(String activityName) throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
// Launch to fullscreen stack and record size.
String logSeparator = clearLogcat();
launchActivityInStack(activityName, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -367,6 +394,11 @@
* Asserts that initial and final reported sizes in docked stack are the same.
*/
private void moveActivitySplitFullSplit(String activityName) throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
// Launch to docked stack and record size.
String logSeparator = clearLogcat();
launchActivityInStack(activityName, DOCKED_STACK_ID);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
index ba56639..cf4f803 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerConfigChangeTests.java
@@ -16,9 +16,14 @@
package android.server.cts;
+import android.platform.test.annotations.Presubmit;
+
import static android.server.cts.ActivityManagerState.STATE_RESUMED;
import static android.server.cts.StateLogger.logE;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -51,11 +56,13 @@
testRotation(NO_RELAUNCH_ACTIVITY_NAME, 2, 0, 0);
}
+ @Presubmit
public void testChangeFontScaleRelaunch() throws Exception {
// Should relaunch and receive no onConfigurationChanged()
testChangeFontScale(TEST_ACTIVITY_NAME, true /* relaunch */);
}
+ @Presubmit
public void testChangeFontScaleNoRelaunch() throws Exception {
// Should receive onConfigurationChanged() and no relaunch
testChangeFontScale(NO_RELAUNCH_ACTIVITY_NAME, false /* relaunch */);
@@ -69,8 +76,21 @@
final String[] waitForActivitiesVisible = new String[] {activityName};
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
- setDeviceRotation(4 - rotationStep);
+ final int initialRotation = 4 - rotationStep;
+ setDeviceRotation(initialRotation);
mAmWmState.computeState(mDevice, waitForActivitiesVisible);
+ final int actualStackId = mAmWmState.getAmState().getTaskByActivityName(
+ activityName).mStackId;
+ final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId;
+ final int newDeviceRotation = getDeviceRotation(displayId);
+ if (newDeviceRotation == INVALID_DEVICE_ROTATION) {
+ CLog.logAndDisplay(LogLevel.WARN, "Got an invalid device rotation value. "
+ + "Continuing the test despite of that, but it is likely to fail.");
+ } else if (newDeviceRotation != initialRotation) {
+ CLog.logAndDisplay(LogLevel.INFO, "This device doesn't support user rotation "
+ + "mode. Not continuing the rotation checks.");
+ return;
+ }
for (int rotation = 0; rotation < 4; rotation += rotationStep) {
final String logSeparator = clearLogcat();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
index ea25e04..cda836f 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDisplayTests.java
@@ -15,6 +15,8 @@
*/
package android.server.cts;
+import android.platform.test.annotations.Presubmit;
+
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -345,6 +347,7 @@
/**
* Tests launching an activity on virtual display.
*/
+ @Presubmit
public void testLaunchActivityOnSecondaryDisplay() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -381,6 +384,7 @@
* command and without specifying the display id - the second activity must appear on the
* primary display.
*/
+ @Presubmit
public void testConsequentLaunchActivity() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -413,6 +417,7 @@
* Tests launching an activity on virtual display and then launching another activity from the
* first one - it must appear on the secondary display, because it was launched from there.
*/
+ @Presubmit
public void testConsequentLaunchActivityFromSecondaryDisplay() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -474,6 +479,7 @@
* Tests launching activities on secondary and then on primary display to see if the stack
* visibility is not affected.
*/
+ @Presubmit
public void testLaunchActivitiesAffectsVisibility() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -506,6 +512,7 @@
/**
* Test that move-task works when moving between displays.
*/
+ @Presubmit
public void testMoveTaskBetweenDisplays() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -536,6 +543,7 @@
* is moved correctly.
* This version launches virtual display creator to fullscreen stack.
*/
+ @Presubmit
public void testStackFocusSwitchOnDisplayRemoved() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -898,54 +906,9 @@
}
/**
- * Test that show-with-insecure-keyguard virtual display is showing content when device is
- * locked.
- */
- public void testShowWhenLockedVirtualDisplay() throws Exception {
- if (!supportsMultiDisplay()) { return; }
-
- // Create new show-with-insecure-keyguard virtual display.
- final DisplayState newDisplay = new VirtualDisplayBuilder(this)
- .setCanShowWithInsecureKeyguard(true)
- .build();
- mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
-
- // Launch activity on new secondary display.
- launchActivityOnDisplay(TEST_ACTIVITY_NAME, newDisplay.mDisplayId);
- mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-
- // Lock the device.
- sleepDevice();
- mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_STOPPED);
- mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
-
- // Unlock and check if visibility is back.
- wakeUpAndUnlockDevice();
- mAmWmState.waitForActivityState(mDevice, TEST_ACTIVITY_NAME, STATE_RESUMED);
- mAmWmState.assertVisibility(TEST_ACTIVITY_NAME, true /* visible */);
- }
-
- /**
- * Test that only private virtual display can show content with insecure keyguard.
- */
- public void testShowWhenLockedPublicVirtualDisplay() throws Exception {
- if (!supportsMultiDisplay()) { return; }
-
- // Try to create new show-with-insecure-keyguard public virtual display.
- final DisplayState newDisplay = new VirtualDisplayBuilder(this)
- .setPublicDisplay(true)
- .setCanShowWithInsecureKeyguard(true)
- .setMustBeCreated(false)
- .build();
-
- // Check that the display is not created.
- mAmWmState.assertVisibility(VIRTUAL_DISPLAY_ACTIVITY, true /* visible */);
- assertNull(newDisplay);
- }
-
- /**
* Test that all activities that were on the private display are destroyed on display removal.
*/
+ @Presubmit
public void testContentDestroyOnDisplayRemoved() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -1000,6 +963,7 @@
/**
* Test that the update of display metrics updates all its content.
*/
+ @Presubmit
public void testDisplayResize() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -1080,6 +1044,7 @@
* Tests that when activities that handle configuration changes are moved between displays,
* they receive onMovedToDisplay and onConfigurationChanged callbacks.
*/
+ @Presubmit
public void testOnMovedToDisplayCallback() throws Exception {
if (!supportsMultiDisplay()) { return; }
@@ -1312,7 +1277,8 @@
* Test that display overrides apply correctly and won't be affected by display changes.
* This sets overrides to display size and density, initiates a display changed event by locking
* and unlocking the phone and verifies that overrides are kept.
- * */
+ */
+ @Presubmit
public void testForceDisplayMetrics() throws Exception {
launchHomeActivity();
@@ -1485,8 +1451,6 @@
* @param densityDpi provide custom density for the display.
* @param launchInSplitScreen start {@link VirtualDisplayActivity} to side from
* {@link LaunchingActivity} on primary display.
- * @param canShowWithInsecureKeyguard allow showing content when device is showing an insecure
- * keyguard.
* @param publicDisplay make display public.
* @param mustBeCreated should assert if the display was or wasn't created.
* @param resizeDisplay should resize display when surface size changes.
@@ -1494,8 +1458,8 @@
* @throws Exception
*/
private List<DisplayState> createVirtualDisplays(int densityDpi, boolean launchInSplitScreen,
- boolean canShowWithInsecureKeyguard, boolean publicDisplay, boolean mustBeCreated,
- boolean resizeDisplay, int displayCount) throws Exception {
+ boolean publicDisplay, boolean mustBeCreated, boolean resizeDisplay, int displayCount)
+ throws Exception {
// Start an activity that is able to create virtual displays.
if (launchInSplitScreen) {
getLaunchActivityBuilder().setToSide(true)
@@ -1509,8 +1473,8 @@
final int originalDisplayCount = originalDS.mDisplayStates.size();
// Create virtual display with custom density dpi.
- executeShellCommand(getCreateVirtualDisplayCommand(densityDpi, canShowWithInsecureKeyguard,
- publicDisplay, resizeDisplay, displayCount));
+ executeShellCommand(getCreateVirtualDisplayCommand(densityDpi, publicDisplay, resizeDisplay,
+ displayCount));
mVirtualDisplayCreated = true;
// Wait for the virtual display to be created and get configurations.
@@ -1711,7 +1675,6 @@
private int mDensityDpi = CUSTOM_DENSITY_DPI;
private boolean mLaunchInSplitScreen = false;
- private boolean mCanShowWithInsecureKeyguard = false;
private boolean mPublicDisplay = false;
private boolean mMustBeCreated = true;
private boolean mResizeDisplay = true;
@@ -1730,12 +1693,6 @@
return this;
}
- public VirtualDisplayBuilder setCanShowWithInsecureKeyguard(
- boolean canShowWithInsecureKeyguard) {
- mCanShowWithInsecureKeyguard = canShowWithInsecureKeyguard;
- return this;
- }
-
public VirtualDisplayBuilder setPublicDisplay(boolean publicDisplay) {
mPublicDisplay = publicDisplay;
return this;
@@ -1756,15 +1713,13 @@
}
public List<DisplayState> build(int count) throws Exception {
- return mTests.createVirtualDisplays(mDensityDpi, mLaunchInSplitScreen,
- mCanShowWithInsecureKeyguard, mPublicDisplay, mMustBeCreated, mResizeDisplay,
- count);
+ return mTests.createVirtualDisplays(mDensityDpi, mLaunchInSplitScreen, mPublicDisplay,
+ mMustBeCreated, mResizeDisplay, count);
}
}
- private static String getCreateVirtualDisplayCommand(int densityDpi,
- boolean canShowWithInsecureKeyguard, boolean publicDisplay, boolean resizeDisplay,
- int displayCount) {
+ private static String getCreateVirtualDisplayCommand(int densityDpi, boolean publicDisplay,
+ boolean resizeDisplay, int displayCount) {
final StringBuilder commandBuilder
= new StringBuilder(getAmStartCmd(VIRTUAL_DISPLAY_ACTIVITY));
commandBuilder.append(" -f 0x20000000");
@@ -1773,8 +1728,6 @@
commandBuilder.append(" --ei density_dpi ").append(densityDpi);
}
commandBuilder.append(" --ei count ").append(displayCount);
- commandBuilder.append(" --ez can_show_with_insecure_keyguard ")
- .append(canShowWithInsecureKeyguard);
commandBuilder.append(" --ez public_display ").append(publicDisplay);
commandBuilder.append(" --ez resize_display ").append(resizeDisplay);
return commandBuilder.toString();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index 1cf60f4..d5ba74e 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -16,6 +16,9 @@
package android.server.cts;
+import com.android.ddmlib.Log.LogLevel;
+import com.android.tradefed.log.LogUtil.CLog;
+
import java.awt.Rectangle;
/**
@@ -36,6 +39,11 @@
private static final int STACK_SIZE = 300;
public void testStackList() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivity(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
@@ -45,6 +53,11 @@
}
public void testDockActivity() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
mAmWmState.assertContainsStack("Must contain home stack.", HOME_STACK_ID);
@@ -52,6 +65,11 @@
}
public void testNonResizeableNotDocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(NON_RESIZEABLE_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {NON_RESIZEABLE_ACTIVITY_NAME});
@@ -62,6 +80,11 @@
}
public void testLaunchToSide() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
getLaunchActivityBuilder().setToSide(true).execute();
@@ -72,6 +95,11 @@
}
public void testLaunchToSideAndBringToFront() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
final String[] waitForFirstVisible = new String[] {TEST_ACTIVITY_NAME};
final String[] waitForSecondVisible = new String[] {NO_RELAUNCH_ACTIVITY_NAME};
@@ -107,6 +135,11 @@
}
public void testLaunchToSideMultiple() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
final String[] waitForActivitiesVisible =
@@ -148,6 +181,11 @@
private void launchTargetToSide(String targetActivityName,
boolean taskCountMustIncrement) throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
@@ -203,6 +241,11 @@
}
public void testLaunchToSideMultipleWithFlag() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
final String[] waitForActivitiesVisible =
@@ -232,6 +275,11 @@
}
public void testRotationWhenDocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
getLaunchActivityBuilder().setToSide(true).execute();
@@ -263,6 +311,11 @@
}
public void testRotationWhenDockedWhileLocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(LAUNCHING_ACTIVITY);
mAmWmState.computeState(mDevice, new String[] {LAUNCHING_ACTIVITY});
getLaunchActivityBuilder().setToSide(true).execute();
@@ -283,6 +336,11 @@
}
public void testRotationWhileDockMinimized() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStackAndMinimize(TEST_ACTIVITY_NAME);
assertDockMinimized();
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
@@ -314,6 +372,11 @@
}
public void testFinishDockActivityWhileMinimized() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStackAndMinimize(FINISHABLE_ACTIVITY_NAME);
assertDockMinimized();
@@ -324,6 +387,11 @@
}
public void testDockedStackToMinimizeWhenUnlocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {TEST_ACTIVITY_NAME});
sleepDevice();
@@ -333,6 +401,11 @@
}
public void testMinimizedStateWhenUnlockedAndUnMinimized() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStackAndMinimize(FINISHABLE_ACTIVITY_NAME);
assertDockMinimized();
@@ -346,6 +419,11 @@
}
public void testResizeDockedStack() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(DOCKED_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[] {DOCKED_ACTIVITY_NAME});
launchActivityInStack(TEST_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID);
@@ -364,6 +442,11 @@
}
public void testActivityLifeCycleOnResizeDockedStack() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
final String[] waitTestActivityName = new String[] {TEST_ACTIVITY_NAME};
launchActivity(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, waitTestActivityName);
@@ -414,6 +497,11 @@
}
public void testStackListOrderLaunchDockedActivity() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no split multi-window support");
+ return;
+ }
+
launchActivityInDockStack(TEST_ACTIVITY_NAME);
mAmWmState.computeState(mDevice, new String[]{TEST_ACTIVITY_NAME});
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
index b7df926..e6df4b2 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerManifestLayoutTests.java
@@ -82,6 +82,10 @@
}
public void testMinimalSizeDocked() throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+ return;
+ }
testMinimalSize(DOCKED_STACK_ID);
}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
index 666ca73..a6372a2 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -38,6 +38,7 @@
private static final String NON_RESIZEABLE_ACTIVITY = "NonResizeableActivity";
private static final String RESUME_WHILE_PAUSING_ACTIVITY = "ResumeWhilePausingActivity";
private static final String PIP_ACTIVITY = "PipActivity";
+ private static final String PIP_ACTIVITY2 = "PipActivity2";
private static final String ALWAYS_FOCUSABLE_PIP_ACTIVITY = "AlwaysFocusablePipActivity";
private static final String LAUNCH_INTO_PINNED_STACK_PIP_ACTIVITY =
"LaunchIntoPinnedStackPipActivity";
@@ -467,6 +468,27 @@
ALWAYS_FOCUSABLE_PIP_ACTIVITY)));
}
+ public void testDisallowMultipleTasksInPinnedStack() throws Exception {
+ if (!supportsPip()) return;
+
+ // Launch first PIP activity
+ launchActivity(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true");
+
+ // Launch second PIP activity
+ launchActivity(PIP_ACTIVITY2, EXTRA_ENTER_PIP, "true");
+
+ final ActivityStack pinnedStack = mAmWmState.getAmState().getStackById(PINNED_STACK_ID);
+ assertEquals(1, pinnedStack.getTasks().size());
+
+ assertTrue(pinnedStack.getTasks().get(0).mRealActivity.equals(getActivityComponentName(
+ PIP_ACTIVITY2)));
+
+ final ActivityStack fullScreenStack = mAmWmState.getAmState().getStackById(
+ FULLSCREEN_WORKSPACE_STACK_ID);
+ assertTrue(fullScreenStack.getBottomTask().mRealActivity.equals(getActivityComponentName(
+ PIP_ACTIVITY)));
+ }
+
public void testPipUnPipOverHome() throws Exception {
if (!supportsPip()) return;
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
index 59d632a..3aa3ce0 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerReplaceWindowTests.java
@@ -49,6 +49,11 @@
}
private void testReplaceWindow_Dock(boolean relaunch) throws Exception {
+ if (!supportsSplitScreenMultiWindow()) {
+ CLog.logAndDisplay(INFO, "Skipping test: no multi-window support");
+ return;
+ }
+
final String activityName =
relaunch ? SLOW_CREATE_ACTIVITY_NAME : NO_RELAUNCH_ACTIVITY_NAME;
final String windowName = getWindowName(activityName);
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java
index 28161bc..a3099ae 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardLockedTests.java
@@ -45,6 +45,9 @@
}
public void testLockAndUnlock() throws Exception {
+ if (!isHandheld()) {
+ return;
+ }
gotoKeyguard();
mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
assertShowingAndNotOccluded();
@@ -54,6 +57,9 @@
}
public void testDismissKeyguard() throws Exception {
+ if (!isHandheld()) {
+ return;
+ }
gotoKeyguard();
mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
assertShowingAndNotOccluded();
@@ -65,6 +71,9 @@
}
public void testDismissKeyguard_whileOccluded() throws Exception {
+ if (!isHandheld()) {
+ return;
+ }
gotoKeyguard();
mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
assertShowingAndNotOccluded();
@@ -80,6 +89,9 @@
}
public void testDismissKeyguard_fromShowWhenLocked_notAllowed() throws Exception {
+ if (!isHandheld()) {
+ return;
+ }
gotoKeyguard();
mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
assertShowingAndNotOccluded();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java
index f17221ef..877369a 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/KeyguardTests.java
@@ -217,6 +217,9 @@
}
public void testDismissKeyguard_fromShowWhenLocked_notAllowed() throws Exception {
+ if (!isHandheld()) {
+ return;
+ }
gotoKeyguard();
mAmWmState.waitForKeyguardShowingAndNotOccluded(mDevice);
assertShowingAndNotOccluded();
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/SplashscreenTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/SplashscreenTests.java
new file mode 100644
index 0000000..4694d7a
--- /dev/null
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/SplashscreenTests.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 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.server.cts;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+/**
+ * Build: mmma -j32 cts/hostsidetests/services
+ * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.SplashscreenTests
+ */
+public class SplashscreenTests extends ActivityManagerTestBase {
+
+ public void testSplashscreenContent() throws Exception {
+ launchActivityNoWait("SplashscreenActivity");
+ mAmWmState.waitForAppTransitionIdle(mDevice);
+ mAmWmState.getWmState().getStableBounds();
+ final BufferedImage image = takeScreenshot();
+ assertAllColor(image, mAmWmState.getWmState().getStableBounds(), Color.RED.getRGB());
+ }
+
+ private void assertAllColor(BufferedImage img, Rectangle bounds, int expectedColor) {
+ for (int x = bounds.x; x < bounds.x + bounds.width; x++) {
+ for (int y = bounds.y; y < bounds.y + bounds.height; y++) {
+ assertTrue(x < img.getWidth());
+ assertTrue(y < img.getHeight());
+ final int color = img.getRGB(x, y);
+ assertEquals("Colors must match at x=" + x + " y=" + y, expectedColor, color);
+ }
+ }
+ }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
index ece45f2..9f4cf6c 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityAndWindowManagersState.java
@@ -34,13 +34,12 @@
import junit.framework.Assert;
-import java.awt.*;
+import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
-import java.util.regex.Pattern;
/** Combined state of the activity manager and window manager. */
public class ActivityAndWindowManagersState extends Assert {
@@ -195,7 +194,8 @@
mAmState.computeState(device);
mWmState.computeState(device);
if (shouldWaitForValidStacks(compareTaskAndStackBounds)
- || shouldWaitForActivities(waitForActivitiesVisible, stackIds, packageName)) {
+ || shouldWaitForActivities(waitForActivitiesVisible, stackIds, packageName)
+ || shouldWaitForWindows()) {
log("***Waiting for valid stacks and activities states...");
try {
Thread.sleep(1000);
@@ -252,6 +252,12 @@
"***Waiting for focused stack...");
}
+ void waitForAppTransitionIdle(ITestDevice device) throws Exception {
+ waitForWithWmState(device,
+ state -> WindowManagerState.APP_STATE_IDLE.equals(state.getAppTransitionState()),
+ "***Waiting for app transition idle...");
+ }
+
void waitForWithAmState(ITestDevice device, Predicate<ActivityManagerState> waitCondition,
String message) throws Exception{
waitFor(device, (amState, wmState) -> waitCondition.test(amState), message);
@@ -283,6 +289,7 @@
} while (retriesLeft-- > 0);
}
+ /** @return true if should wait for valid stacks state. */
private boolean shouldWaitForValidStacks(boolean compareTaskAndStackBounds) {
if (!taskListsInAmAndWmAreEqual()) {
// We want to wait for equal task lists in AM and WM in case we caught them in the
@@ -304,9 +311,24 @@
log("***taskBoundsInAMAndWMAreEqual=false : " + e.getMessage());
return true;
}
+ final int stackCount = mAmState.getStackCount();
+ if (stackCount == 0) {
+ log("***stackCount=" + stackCount);
+ return true;
+ }
+ final int resumedActivitiesCount = mAmState.getResumedActivitiesCount();
+ if (!mAmState.getKeyguardControllerState().keyguardShowing && resumedActivitiesCount != 1) {
+ log("***resumedActivitiesCount=" + resumedActivitiesCount);
+ return true;
+ }
+ if (mAmState.getFocusedActivity() == null) {
+ log("***focusedActivity=null");
+ return true;
+ }
return false;
}
+ /** @return true if should wait for some activities to become visible. */
private boolean shouldWaitForActivities(String[] waitForActivitiesVisible, int[] stackIds,
String packageName) {
if (waitForActivitiesVisible == null || waitForActivitiesVisible.length == 0) {
@@ -353,6 +375,24 @@
return !allActivityWindowsVisible || !tasksInCorrectStacks;
}
+ /** @return true if should wait valid windows state. */
+ private boolean shouldWaitForWindows() {
+ if (mWmState.getFrontWindow() == null) {
+ log("***frontWindow=null");
+ return true;
+ }
+ if (mWmState.getFocusedWindow() == null) {
+ log("***focusedWindow=null");
+ return true;
+ }
+ if (mWmState.getFocusedApp() == null) {
+ log("***focusedApp=null");
+ return true;
+ }
+
+ return false;
+ }
+
private boolean shouldWaitForDebuggerWindow() {
List<WindowManagerState.WindowState> matchingWindowStates = new ArrayList<>();
mWmState.getMatchingVisibleWindowState("android.server.cts", matchingWindowStates);
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
index 96bcc1c..4ef07cf 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
@@ -21,8 +21,11 @@
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.InputStreamSource;
import com.android.tradefed.testtype.DeviceTestCase;
+import java.awt.*;
+import java.awt.image.BufferedImage;
import java.lang.Exception;
import java.lang.Integer;
import java.lang.String;
@@ -37,6 +40,8 @@
import android.server.cts.ActivityManagerState.ActivityStack;
+import javax.imageio.ImageIO;
+
public abstract class ActivityManagerTestBase extends DeviceTestCase {
private static final boolean PRETEND_DEVICE_SUPPORTS_PIP = false;
private static final boolean PRETEND_DEVICE_SUPPORTS_FREEFORM = false;
@@ -115,6 +120,8 @@
static final String AM_MOVE_TASK = "am stack move-task ";
+ private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
+ "am supports-split-screen-multiwindow";
private static final String AM_NO_HOME_SCREEN = "am no-home-screen";
private static final String INPUT_KEYEVENT_HOME = "input keyevent 3";
@@ -289,13 +296,25 @@
mDevice.executeShellCommand(command, outputReceiver);
}
+ protected BufferedImage takeScreenshot() throws Exception {
+ final InputStreamSource stream = mDevice.getScreenshot("PNG", false /* rescale */);
+ if (stream == null) {
+ fail("Failed to take screenshot of device");
+ }
+ return ImageIO.read(stream.createInputStream());
+ }
+
protected void launchActivity(final String targetActivityName, final String... keyValuePairs)
throws Exception {
executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
-
mAmWmState.waitForValidState(mDevice, targetActivityName);
}
+ protected void launchActivityNoWait(final String targetActivityName,
+ final String... keyValuePairs) throws Exception {
+ executeShellCommand(getAmStartCmd(targetActivityName, keyValuePairs));
+ }
+
protected void launchActivityInNewTask(final String targetActivityName) throws Exception {
executeShellCommand(getAmStartCmdInNewTask(targetActivityName));
mAmWmState.waitForValidState(mDevice, targetActivityName);
@@ -506,6 +525,13 @@
&& !hasDeviceFeature("android.software.watch");
}
+ protected boolean supportsSplitScreenMultiWindow() throws DeviceNotAvailableException {
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ executeShellCommand(AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW, outputReceiver);
+ String output = outputReceiver.getOutput();
+ return !output.startsWith("false");
+ }
+
protected boolean noHomeScreen() throws DeviceNotAvailableException {
CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
executeShellCommand(AM_NO_HOME_SCREEN, outputReceiver);
@@ -710,70 +736,139 @@
return uniqueString;
}
- protected void assertActivityLifecycle(String activityName, boolean relaunched,
+ void assertActivityLifecycle(String activityName, boolean relaunched,
String logSeparator) throws DeviceNotAvailableException {
+ int retriesLeft = 5;
+ String resultString;
+ do {
+ resultString = verifyLifecycleCondition(activityName, logSeparator, relaunched);
+ if (resultString != null) {
+ log("***Waiting for valid lifecycle state: " + resultString);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ log(e.toString());
+ }
+ } else {
+ break;
+ }
+ } while (retriesLeft-- > 0);
+
+ assertNull(resultString, resultString);
+ }
+
+ /** @return Error string if lifecycle counts don't match, null if everything is fine. */
+ private String verifyLifecycleCondition(String activityName, String logSeparator,
+ boolean relaunched) throws DeviceNotAvailableException {
final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(activityName,
logSeparator);
-
if (relaunched) {
if (lifecycleCounts.mDestroyCount < 1) {
- fail(activityName + " must have been destroyed. mDestroyCount="
- + lifecycleCounts.mDestroyCount);
+ return activityName + " must have been destroyed. mDestroyCount="
+ + lifecycleCounts.mDestroyCount;
}
if (lifecycleCounts.mCreateCount < 1) {
- fail(activityName + " must have been (re)created. mCreateCount="
- + lifecycleCounts.mCreateCount);
+ return activityName + " must have been (re)created. mCreateCount="
+ + lifecycleCounts.mCreateCount;
}
} else {
if (lifecycleCounts.mDestroyCount > 0) {
- fail(activityName + " must *NOT* have been destroyed. mDestroyCount="
- + lifecycleCounts.mDestroyCount);
+ return activityName + " must *NOT* have been destroyed. mDestroyCount="
+ + lifecycleCounts.mDestroyCount;
}
if (lifecycleCounts.mCreateCount > 0) {
- fail(activityName + " must *NOT* have been (re)created. mCreateCount="
- + lifecycleCounts.mCreateCount);
+ return activityName + " must *NOT* have been (re)created. mCreateCount="
+ + lifecycleCounts.mCreateCount;
}
if (lifecycleCounts.mConfigurationChangedCount < 1) {
- fail(activityName + " must have received configuration changed. "
+ return activityName + " must have received configuration changed. "
+ "mConfigurationChangedCount="
- + lifecycleCounts.mConfigurationChangedCount);
+ + lifecycleCounts.mConfigurationChangedCount;
}
}
+ return null;
}
protected void assertRelaunchOrConfigChanged(
String activityName, int numRelaunch, int numConfigChange, String logSeparator)
throws DeviceNotAvailableException {
+ int retriesLeft = 5;
+ String resultString;
+ do {
+ resultString = verifyRelaunchOrConfigChanged(activityName, numRelaunch, numConfigChange,
+ logSeparator);
+ if (resultString != null) {
+ log("***Waiting for relaunch or config changed: " + resultString);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ log(e.toString());
+ }
+ } else {
+ break;
+ }
+ } while (retriesLeft-- > 0);
+
+ assertNull(resultString, resultString);
+ }
+
+ /** @return Error string if lifecycle counts don't match, null if everything is fine. */
+ private String verifyRelaunchOrConfigChanged(String activityName, int numRelaunch,
+ int numConfigChange, String logSeparator) throws DeviceNotAvailableException {
final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(activityName,
logSeparator);
if (lifecycleCounts.mDestroyCount != numRelaunch) {
- fail(activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
- + " time(s), expecting " + numRelaunch);
+ return activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
+ + " time(s), expecting " + numRelaunch;
} else if (lifecycleCounts.mCreateCount != numRelaunch) {
- fail(activityName + " has been (re)created " + lifecycleCounts.mCreateCount
- + " time(s), expecting " + numRelaunch);
+ return activityName + " has been (re)created " + lifecycleCounts.mCreateCount
+ + " time(s), expecting " + numRelaunch;
} else if (lifecycleCounts.mConfigurationChangedCount != numConfigChange) {
- fail(activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
- + " onConfigurationChanged() calls, expecting " + numConfigChange);
+ return activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
+ + " onConfigurationChanged() calls, expecting " + numConfigChange;
}
+ return null;
}
protected void assertActivityDestroyed(String activityName, String logSeparator)
throws DeviceNotAvailableException {
+ int retriesLeft = 5;
+ String resultString;
+ do {
+ resultString = verifyActivityDestroyed(activityName, logSeparator);
+ if (resultString != null) {
+ log("***Waiting for activity destroyed: " + resultString);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ log(e.toString());
+ }
+ } else {
+ break;
+ }
+ } while (retriesLeft-- > 0);
+
+ assertNull(resultString, resultString);
+ }
+
+ /** @return Error string if lifecycle counts don't match, null if everything is fine. */
+ private String verifyActivityDestroyed(String activityName, String logSeparator)
+ throws DeviceNotAvailableException {
final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(activityName,
logSeparator);
if (lifecycleCounts.mDestroyCount != 1) {
- fail(activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
- + " time(s), expecting single destruction.");
+ return activityName + " has been destroyed " + lifecycleCounts.mDestroyCount
+ + " time(s), expecting single destruction.";
} else if (lifecycleCounts.mCreateCount != 0) {
- fail(activityName + " has been (re)created " + lifecycleCounts.mCreateCount
- + " time(s), not expecting any.");
+ return activityName + " has been (re)created " + lifecycleCounts.mCreateCount
+ + " time(s), not expecting any.";
} else if (lifecycleCounts.mConfigurationChangedCount != 0) {
- fail(activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
- + " onConfigurationChanged() calls, not expecting any.");
+ return activityName + " has received " + lifecycleCounts.mConfigurationChangedCount
+ + " onConfigurationChanged() calls, not expecting any.";
}
+ return null;
}
protected String[] getDeviceLogsForComponent(String componentName, String logSeparator)
@@ -861,6 +956,27 @@
ReportedSizes getLastReportedSizesForActivity(String activityName, String logSeparator)
throws DeviceNotAvailableException {
+ int retriesLeft = 5;
+ ReportedSizes result;
+ do {
+ result = readLastReportedSizes(activityName, logSeparator);
+ if (result == null) {
+ log("***Waiting for sizes to be reported...");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ log(e.toString());
+ // Well I guess we are not waiting...
+ }
+ } else {
+ break;
+ }
+ } while (retriesLeft-- > 0);
+ return result;
+ }
+
+ private ReportedSizes readLastReportedSizes(String activityName, String logSeparator)
+ throws DeviceNotAvailableException {
final String[] lines = getDeviceLogsForComponent(activityName, logSeparator);
for (int i = lines.length - 1; i >= 0; i--) {
final String line = lines[i].trim();
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java
index f9ad434..0cdf13e 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/WindowManagerState.java
@@ -37,7 +37,7 @@
public class WindowManagerState {
- public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
+ public static final String TRANSIT_ACTIVITY_OPEN = "TRANSIT_ACTIVITY_OPEN";
public static final String TRANSIT_ACTIVITY_CLOSE = "TRANSIT_ACTIVITY_CLOSE";
public static final String TRANSIT_TASK_OPEN = "TRANSIT_TASK_OPEN";
public static final String TRANSIT_TASK_CLOSE = "TRANSIT_TASK_CLOSE";
@@ -53,6 +53,8 @@
public static final String TRANSIT_KEYGUARD_OCCLUDE = "TRANSIT_KEYGUARD_OCCLUDE";
public static final String TRANSIT_KEYGUARD_UNOCCLUDE = "TRANSIT_KEYGUARD_UNOCCLUDE";
+ public static final String APP_STATE_IDLE = "APP_STATE_IDLE";
+
private static final String DUMPSYS_WINDOW = "dumpsys window -a";
private static final Pattern sWindowPattern =
@@ -87,6 +89,8 @@
private static final Pattern sLastAppTransitionPattern =
Pattern.compile("mLastUsedAppTransition=(.+)");
+ private static final Pattern sAppTransitionStatePattern =
+ Pattern.compile("mAppTransitionState=(.+)");
private static final Pattern sStackIdPattern = Pattern.compile("mStackId=(\\d+)");
@@ -120,6 +124,7 @@
private String mFocusedWindow = null;
private String mFocusedApp = null;
private String mLastTransition = null;
+ private String mAppTransitionState = null;
private String mInputMethodWindowAppToken = null;
private Rectangle mStableBounds = new Rectangle();
private final Rectangle mDefaultPinnedStackBounds = new Rectangle();
@@ -157,7 +162,7 @@
dump = outputReceiver.getOutput();
parseSysDump(dump);
- retry = mWindowStates.isEmpty() || mFocusedWindow == null || mFocusedApp == null;
+ retry = mWindowStates.isEmpty() || mFocusedApp == null;
} while (retry && retriesLeft-- > 0);
if (retry) {
@@ -260,6 +265,15 @@
continue;
}
+ matcher = sAppTransitionStatePattern.matcher(line);
+ if (matcher.matches()) {
+ log(line);
+ final String appTransitionState = matcher.group(1);
+ log(appTransitionState);
+ mAppTransitionState = appTransitionState;
+ continue;
+ }
+
matcher = sLastAppTransitionPattern.matcher(line);
if (matcher.matches()) {
log(line);
@@ -442,6 +456,10 @@
return mLastTransition;
}
+ String getAppTransitionState() {
+ return mAppTransitionState;
+ }
+
int getFrontStackId(int displayId) {
return mDisplayStacks.get(displayId).get(0).mStackId;
}
diff --git a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
index f594123..6281e16 100644
--- a/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
+++ b/hostsidetests/services/activityandwindowmanager/windowmanager/src/android/server/cts/CrossAppDragAndDropTests.java
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.Map;
+import java.util.regex.Pattern;
public class CrossAppDragAndDropTests extends DeviceTestCase {
// Constants copied from ActivityManager.StackId. If they are changed there, these must be
@@ -42,12 +43,18 @@
private static final String AM_FORCE_STOP = "am force-stop ";
private static final String AM_MOVE_TASK = "am stack move-task ";
+ private static final String AM_RESIZE_TASK = "am task resize ";
private static final String AM_REMOVE_STACK = "am stack remove ";
private static final String AM_START_N = "am start -n ";
private static final String AM_STACK_LIST = "am stack list";
private static final String INPUT_MOUSE_SWIPE = "input mouse swipe ";
private static final String TASK_ID_PREFIX = "taskId";
+ // Regex pattern to match adb shell am stack list output of the form:
+ // taskId=<TASK_ID>: <componentName> bounds=[LEFT,TOP][RIGHT,BOTTOM]
+ private static final String TASK_REGEX_PATTERN_STRING =
+ "taskId=[0-9]+: %s bounds=\\[[0-9]+,[0-9]+\\]\\[[0-9]+,[0-9]+\\]";
+
private static final int SWIPE_DURATION_MS = 500;
private static final String SOURCE_PACKAGE_NAME = "android.wm.cts.dndsourceapp";
@@ -94,6 +101,9 @@
private static final String RESULT_EXCEPTION = "Exception";
private static final String RESULT_NULL_DROP_PERMISSIONS = "Null DragAndDropPermissions";
+ private static final String AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW =
+ "am supports-split-screen-multiwindow";
+
private ITestDevice mDevice;
private Map<String, String> mSourceResults;
@@ -145,6 +155,12 @@
return AM_MOVE_TASK + taskId + " " + stackId + " true";
}
+ private String getResizeTaskCommand(int taskId, Point topLeft, Point bottomRight)
+ throws Exception {
+ return AM_RESIZE_TASK + taskId + " " + topLeft.x + " " + topLeft.y + " " + bottomRight.x
+ + " " + bottomRight.y;
+ }
+
private String getComponentName(String packageName, String activityName) {
return packageName + "/" + packageName + "." + activityName;
}
@@ -195,6 +211,24 @@
waitForResume(packageName, activityName);
}
+ /**
+ * @param displaySize size of the display
+ * @param leftSide {@code true} to launch the app taking up the left half of the display,
+ * {@code false} to launch the app taking up the right half of the display.
+ */
+ private void launchFreeformActivity(String packageName, String activityName, String mode,
+ Point displaySize, boolean leftSide) throws Exception{
+ clearLogs();
+ final String componentName = getComponentName(packageName, activityName);
+ executeShellCommand(getStartCommand(componentName, mode) + " --stack "
+ + FREEFORM_WORKSPACE_STACK_ID);
+ waitForResume(packageName, activityName);
+ Point topLeft = new Point(leftSide ? 0 : displaySize.x / 2, 0);
+ Point bottomRight = new Point(leftSide ? displaySize.x / 2 : displaySize.x, displaySize.y);
+ executeShellCommand(getResizeTaskCommand(getActivityTaskId(componentName), topLeft,
+ bottomRight));
+ }
+
private void waitForResume(String packageName, String activityName) throws Exception {
final String fullActivityName = packageName + "." + activityName;
int retryCount = 3;
@@ -238,6 +272,7 @@
builder.append("\nParsing adb shell am output: " );
builder.append(output);
CLog.i(builder.toString());
+ final Pattern pattern = Pattern.compile(String.format(TASK_REGEX_PATTERN_STRING, name));
for (String line : output.split("\\n")) {
final String truncatedLine;
// Only look for the activity name before the "topActivity" string.
@@ -247,7 +282,7 @@
} else {
truncatedLine = line;
}
- if (truncatedLine.contains(name)) {
+ if (pattern.matcher(truncatedLine).find()) {
return truncatedLine;
}
}
@@ -280,6 +315,12 @@
return -1;
}
+ private Point getDisplaySize() throws Exception {
+ final String output = executeShellCommand("wm size");
+ final String[] sizes = output.split(" ")[2].split("x");
+ return new Point(Integer.valueOf(sizes[0].trim()), Integer.valueOf(sizes[1].trim()));
+ }
+
private Point getWindowCenter(String name) throws Exception {
Point p1 = new Point();
Point p2 = new Point();
@@ -343,8 +384,19 @@
return;
}
- launchDockedActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode);
- launchFullscreenActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode);
+ if (supportsSplitScreenMultiWindow()) {
+ launchDockedActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode);
+ launchFullscreenActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode);
+ } else if (supportsFreeformMultiWindow()) {
+ // Fallback to try to launch two freeform windows side by side.
+ Point displaySize = getDisplaySize();
+ launchFreeformActivity(mSourcePackageName, SOURCE_ACTIVITY_NAME, sourceMode,
+ displaySize, true /* leftSide */);
+ launchFreeformActivity(mTargetPackageName, TARGET_ACTIVITY_NAME, targetMode,
+ displaySize, false /* leftSide */);
+ } else {
+ return;
+ }
clearLogs();
@@ -412,6 +464,14 @@
}
}
+ private boolean supportsSplitScreenMultiWindow() throws DeviceNotAvailableException {
+ return !executeShellCommand(AM_SUPPORTS_SPLIT_SCREEN_MULTIWINDOW).startsWith("false");
+ }
+
+ private boolean supportsFreeformMultiWindow() throws DeviceNotAvailableException {
+ return mDevice.hasFeature("feature:android.software.freeform_window_management");
+ }
+
public void testCancelSoon() throws Exception {
assertDropResult(CANCEL_SOON, REQUEST_NONE, RESULT_MISSING);
}
diff --git a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
index 7d06682..1955483 100644
--- a/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
+++ b/tests/JobScheduler/src/android/jobscheduler/MockJobService.java
@@ -26,6 +26,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.net.Uri;
import android.os.Process;
import android.util.Log;
@@ -99,16 +100,90 @@
while ((work = params.dequeueWork()) != null) {
Log.i(TAG, "Received work #" + index + ": " + work.getIntent());
mReceivedWork.add(work.getIntent());
- params.completeWork(work);
- if (index < expectedWork.length && expectedWork[index].subitems != null) {
- final TestWorkItem[] sub = expectedWork[index].subitems;
- final JobInfo ji = expectedWork[index].jobInfo;
- final JobScheduler js = (JobScheduler) getSystemService(
- Context.JOB_SCHEDULER_SERVICE);
- for (int subi = 0; subi < sub.length; subi++) {
- js.enqueue(ji, new JobWorkItem(sub[subi].intent));
+
+ if (index < expectedWork.length) {
+ TestWorkItem expected = expectedWork[index];
+ int grantFlags = work.getIntent().getFlags();
+ if (expected.requireUrisGranted != null) {
+ for (int ui = 0; ui < expected.requireUrisGranted.length; ui++) {
+ if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Expected read permission but not granted: "
+ + expected.requireUrisGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Expected write permission but not granted: "
+ + expected.requireUrisGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ }
+ }
+ if (expected.requireUrisNotGranted != null) {
+ // XXX note no delay here, current impl will have fully revoked the
+ // permission by the time we return from completing the last work.
+ for (int ui = 0; ui < expected.requireUrisNotGranted.length; ui++) {
+ if ((grantFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisNotGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ != PackageManager.PERMISSION_DENIED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Not expected read permission but granted: "
+ + expected.requireUrisNotGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ if ((grantFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ if (checkUriPermission(expected.requireUrisNotGranted[ui],
+ Process.myPid(), Process.myUid(),
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+ != PackageManager.PERMISSION_DENIED) {
+ TestEnvironment.getTestEnvironment().notifyExecution(params,
+ permCheckRead, permCheckWrite, null,
+ "Not expected write permission but granted: "
+ + expected.requireUrisNotGranted[ui]
+ + " @ #" + index);
+ return false;
+ }
+ }
+ }
}
}
+
+ params.completeWork(work);
+
+ if (index < expectedWork.length) {
+ TestWorkItem expected = expectedWork[index];
+ if (expected.subitems != null) {
+ final TestWorkItem[] sub = expected.subitems;
+ final JobInfo ji = expected.jobInfo;
+ final JobScheduler js = (JobScheduler) getSystemService(
+ Context.JOB_SCHEDULER_SERVICE);
+ for (int subi = 0; subi < sub.length; subi++) {
+ js.enqueue(ji, new JobWorkItem(sub[subi].intent));
+ }
+ }
+ }
+
+ index++;
}
Log.i(TAG, "Done with all work at #" + index);
// We don't notifyExecution here because we want to make sure the job properly
@@ -130,17 +205,32 @@
public final Intent intent;
public final JobInfo jobInfo;
public final TestWorkItem[] subitems;
+ public final Uri[] requireUrisGranted;
+ public final Uri[] requireUrisNotGranted;
public TestWorkItem(Intent _intent) {
intent = _intent;
jobInfo = null;
subitems = null;
+ requireUrisGranted = null;
+ requireUrisNotGranted = null;
}
public TestWorkItem(Intent _intent, JobInfo _jobInfo, TestWorkItem[] _subitems) {
intent = _intent;
jobInfo = _jobInfo;
subitems = _subitems;
+ requireUrisGranted = null;
+ requireUrisNotGranted = null;
+ }
+
+ public TestWorkItem(Intent _intent, Uri[] _requireUrisGranted,
+ Uri[] _requireUrisNotGranted) {
+ intent = _intent;
+ jobInfo = null;
+ subitems = null;
+ requireUrisGranted = _requireUrisGranted;
+ requireUrisNotGranted = _requireUrisNotGranted;
}
}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
index 47089d4..03d941e 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ClipDataJobTest.java
@@ -73,7 +73,7 @@
// Schedule the job, the system should now also be holding a URI grant for us.
kTestEnvironment.setExpectedExecutions(1);
mJobScheduler.schedule(mBuilder.setRequiresStorageNotLow(true)
- .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
// Remove the explicit grant, we should still have a grant due to the job.
@@ -105,7 +105,7 @@
public void testClipDataGrant_Failed() throws Exception {
try {
mJobScheduler.schedule(mBuilder.setRequiresStorageNotLow(true)
- .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
} catch (SecurityException e) {
return;
@@ -131,7 +131,7 @@
// Schedule the job, the system should now also be holding a URI grant for us.
kTestEnvironment.setExpectedExecutions(1);
mJobScheduler.schedule(mBuilder.setMinimumLatency(60*60*1000)
- .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
// Remove the explicit grant, we should still have a grant due to the job.
@@ -145,7 +145,7 @@
// Now reschedule the job to have it happen right now.
mJobScheduler.schedule(mBuilder.setMinimumLatency(0)
- .setClipData(mClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ .setClipData(mFirstClipData, Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION).build());
assertTrue("Job with storage not low constraint did not fire when storage not low.",
kTestEnvironment.awaitExecution());
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index a7c7003..0a3ff9c 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -163,6 +163,27 @@
kTestEnvironment.awaitExecution());
}
+ /**
+ * Schedule a job with a metered connectivity constraint, and ensure that it executes
+ * on on a mobile data connection.
+ */
+ public void testConnectivityConstraintExecutes_metered() throws Exception {
+ if (!checkDeviceSupportsMobileData()) {
+ return;
+ }
+ disconnectWifiToConnectToMobile();
+
+ kTestEnvironment.setExpectedExecutions(1);
+ mJobScheduler.schedule(
+ mBuilder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_METERED)
+ .build());
+
+ sendExpediteStableChargingBroadcast();
+
+ assertTrue("Job with metered connectivity constraint did not fire on mobile.",
+ kTestEnvironment.awaitExecution());
+ }
+
// --------------------------------------------------------------------------------------------
// Negatives - schedule jobs under conditions that require that they fail.
// --------------------------------------------------------------------------------------------
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
index c92e521..bcc1e08 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConstraintTest.java
@@ -17,7 +17,6 @@
import android.annotation.TargetApi;
import android.app.Instrumentation;
-import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ClipData;
import android.content.ComponentName;
@@ -30,7 +29,6 @@
import android.os.Bundle;
import android.os.Process;
import android.os.SystemClock;
-import android.test.AndroidTestCase;
import android.test.InstrumentationTestCase;
import android.util.Log;
@@ -67,7 +65,10 @@
Uri mFirstUri;
Bundle mFirstUriBundle;
- ClipData mClipData;
+ Uri mSecondUri;
+ Bundle mSecondUriBundle;
+ ClipData mFirstClipData;
+ ClipData mSecondClipData;
boolean mStorageStateChanged;
@@ -82,8 +83,13 @@
mFirstUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/foo");
mFirstUriBundle = new Bundle();
mFirstUriBundle.putParcelable("uri", mFirstUri);
- mClipData = new ClipData("JobPerm", new String[] { "application/*" },
+ mSecondUri = Uri.parse("content://" + JOBPERM_AUTHORITY + "/protected/bar");
+ mSecondUriBundle = new Bundle();
+ mSecondUriBundle.putParcelable("uri", mSecondUri);
+ mFirstClipData = new ClipData("JobPerm1", new String[] { "application/*" },
new ClipData.Item(mFirstUri));
+ mSecondClipData = new ClipData("JobPerm2", new String[] { "application/*" },
+ new ClipData.Item(mSecondUri));
try {
SystemUtil.runShellCommand(getInstrumentation(), "cmd activity set-inactive "
+ mContext.getPackageName() + " false");
@@ -122,10 +128,23 @@
getContext().sendBroadcast(EXPEDITE_STABLE_CHARGING);
}
+ public void assertHasUriPermission(Uri uri, int grantFlags) {
+ if ((grantFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+ assertEquals(PackageManager.PERMISSION_GRANTED,
+ getContext().checkUriPermission(uri, Process.myPid(),
+ Process.myUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION));
+ }
+ if ((grantFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+ assertEquals(PackageManager.PERMISSION_GRANTED,
+ getContext().checkUriPermission(uri, Process.myPid(),
+ Process.myUid(), Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
+ }
+ }
+
void waitPermissionRevoke(Uri uri, int access, long timeout) {
long startTime = SystemClock.elapsedRealtime();
while (getContext().checkUriPermission(uri, Process.myPid(), Process.myUid(), access)
- != PackageManager.PERMISSION_GRANTED) {
+ != PackageManager.PERMISSION_DENIED) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
index ad5a20f..402233b 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/EnqueueJobWorkTest.java
@@ -22,6 +22,7 @@
import android.content.ContentProviderClient;
import android.content.Intent;
import android.jobscheduler.MockJobService.TestWorkItem;
+import android.net.Uri;
import java.util.ArrayList;
@@ -44,13 +45,13 @@
super.setUp();
mBuilder = new JobInfo.Builder(ENQUEUE_WORK_JOB_ID, kJobServiceComponent);
- //mProvider = getContext().getContentResolver().acquireContentProviderClient(mFirstUri);
+ mProvider = getContext().getContentResolver().acquireContentProviderClient(mFirstUri);
}
@Override
public void tearDown() throws Exception {
super.tearDown();
- //mProvider.close();
+ mProvider.close();
mJobScheduler.cancel(ENQUEUE_WORK_JOB_ID);
}
@@ -74,19 +75,19 @@
}
for (int i = 0; i < received.size(); i++) {
Intent work = received.get(i);
- if (i >= expected.length) {
- fail("Received more than " + expected.length + " work items, first extra is "
- + work);
- }
- if (!intentEquals(work, expectedArray.get(i).intent)) {
- fail("Received work #" + i + " " + work + " but expected " + expected[i]);
- }
if (i < expected.length && expected[i].subitems != null) {
TestWorkItem[] sub = expected[i].subitems;
for (int j = 0; j < sub.length; j++) {
expectedArray.add(sub[j]);
}
}
+ if (i >= expectedArray.size()) {
+ fail("Received more than " + expected.length + " work items, first extra is "
+ + work);
+ }
+ if (!intentEquals(work, expectedArray.get(i).intent)) {
+ fail("Received work #" + i + " " + work + " but expected " + expected[i]);
+ }
}
if (received.size() < expected.length) {
fail("Received only " + received.size() + " work items, but expected "
@@ -176,4 +177,61 @@
kTestEnvironment.awaitExecution());
compareWork(work, kTestEnvironment.getLastReceivedWork());
}
+
+ /**
+ * Test basic enqueueing batches of work.
+ */
+ public void testEnqueueMultipleUriGrantWork() throws Exception {
+ // Start out with storage low, so job is enqueued but not executed yet.
+ setStorageState(true);
+
+ // We need to get a permission grant so that we can grant it to ourself.
+ mProvider.call("grant", MY_PACKAGE, mFirstUriBundle);
+ mProvider.call("grant", MY_PACKAGE, mSecondUriBundle);
+ assertHasUriPermission(mFirstUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ assertHasUriPermission(mSecondUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ Intent work1 = new Intent("work1");
+ work1.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ work1.setData(mFirstUri);
+ work1.setClipData(mSecondClipData);
+
+ Intent work2 = new Intent("work2");
+ work2.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ work2.setData(mFirstUri);
+
+ TestWorkItem[] work = new TestWorkItem[] {
+ new TestWorkItem(work1, new Uri[] { mFirstUri, mSecondUri}, new Uri[0]),
+ new TestWorkItem(work2, new Uri[] { mFirstUri }, new Uri[] { mSecondUri}) };
+ kTestEnvironment.setExpectedExecutions(1);
+ kTestEnvironment.setExpectedWork(work);
+ JobInfo ji = mBuilder.setOverrideDeadline(0).setRequiresStorageNotLow(true).build();
+ mJobScheduler.enqueue(ji, new JobWorkItem(work1));
+ mJobScheduler.enqueue(ji, new JobWorkItem(work2));
+
+ // Remove the explicit grant, we should still have a grant due to the job.
+ mProvider.call("revoke", MY_PACKAGE, mFirstUriBundle);
+ mProvider.call("revoke", MY_PACKAGE, mSecondUriBundle);
+ assertHasUriPermission(mFirstUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ assertHasUriPermission(mSecondUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ kTestEnvironment.readyToWork();
+
+ // Now allow the job to run.
+ setStorageState(false);
+
+ assertTrue("Job with work enqueued did not fire.",
+ kTestEnvironment.awaitExecution());
+ compareWork(work, kTestEnvironment.getLastReceivedWork());
+
+ // And wait for everything to be cleaned up.
+ waitPermissionRevoke(mFirstUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000);
+ waitPermissionRevoke(mSecondUri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, 5000);
+ }
}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
index 1185813..1979e97 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityManagerTest.java
@@ -23,7 +23,6 @@
import android.test.InstrumentationTestCase;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
@@ -83,15 +82,6 @@
assertFalse(mAccessibilityManager.removeTouchExplorationStateChangeListener(listener));
}
- public void testAddAndRemoveServiceStateChangeListener() throws Exception {
- AccessibilityServicesStateChangeListener listener = () -> {
- // Do Nothing
- };
- assertTrue(mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener));
- assertTrue(mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener));
- assertFalse(mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener));
- }
-
public void testIsTouchExplorationEnabled() throws Exception {
new PollingCheck() {
@Override
@@ -240,44 +230,6 @@
waitForTouchExplorationEnabled();
}
- public void testServiceStateChanges_stateChangeListenersCalled() throws Exception {
- final Object waitObject = new Object();
- final AtomicBoolean listenerCalled = new AtomicBoolean(false);
- final SpeakingAccessibilityService service =
- SpeakingAccessibilityService.sConnectedInstance;
- final AccessibilityServicesStateChangeListener listener = () -> {
- synchronized (waitObject) {
- listenerCalled.set(true);
- waitObject.notifyAll();
- }
- };
-
- mAccessibilityManager.addAccessibilityServicesStateChangeListener(listener);
- // Verify called on info change
- final AccessibilityServiceInfo initialInfo = service.getServiceInfo();
- AccessibilityServiceInfo tempInfo = service.getServiceInfo();
- tempInfo.flags ^= AccessibilityServiceInfo.FLAG_ENABLE_ACCESSIBILITY_VOLUME;
- try {
- service.setServiceInfo(tempInfo);
- assertListenerCalled(listenerCalled, waitObject);
- } finally {
- service.setServiceInfo(initialInfo);
- }
-
- // Verify called on service disabled
- listenerCalled.set(false);
- ServiceControlUtils.turnAccessibilityOff(getInstrumentation());
- assertListenerCalled(listenerCalled, waitObject);
-
- // Verify called on service enabled
- listenerCalled.set(false);
- ServiceControlUtils.enableSpeakingAndVibratingServices(getInstrumentation());
- assertListenerCalled(listenerCalled, waitObject);
-
- mAccessibilityManager.removeAccessibilityServicesStateChangeListener(listener);
-
- }
-
private void assertListenerCalled(AtomicBoolean listenerCalled, Object waitObject)
throws Exception {
long timeoutTime = System.currentTimeMillis() + WAIT_FOR_ACCESSIBILITY_ENABLED_TIMEOUT;
diff --git a/tests/app/src/android/app/cts/ActivityManagerTest.java b/tests/app/src/android/app/cts/ActivityManagerTest.java
index e3e7c53..f29ae1e 100644
--- a/tests/app/src/android/app/cts/ActivityManagerTest.java
+++ b/tests/app/src/android/app/cts/ActivityManagerTest.java
@@ -36,6 +36,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ConfigurationInfo;
+import android.content.res.Resources;
import android.platform.test.annotations.RestrictedBuildTest;
import android.test.InstrumentationTestCase;
@@ -398,6 +399,20 @@
Thread.sleep(WAIT_TIME);
}
+ /**
+ * Gets the value of com.android.internal.R.bool.config_noHomeScreen.
+ * @return true if no home screen is supported, false otherwise.
+ */
+ private boolean noHomeScreen() {
+ try {
+ return getInstrumentation().getContext().getResources().getBoolean(
+ Resources.getSystem().getIdentifier("config_noHomeScreen", "bool", "android"));
+ } catch (Resources.NotFoundException e) {
+ // Assume there's a home screen.
+ return false;
+ }
+ }
+
/**
* Verify that the TimeTrackingAPI works properly when starting and ending an activity.
*/
@@ -429,10 +444,20 @@
assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
appEndReceiver.close();
- // At this time the timerReceiver should not fire, even though the activity has shut down,
- // because we are back to the home screen.
- assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
- assertTrue(timeReceiver.mTimeUsed == 0);
+ if (!noHomeScreen()) {
+ // At this time the timerReceiver should not fire, even though the activity has shut
+ // down, because we are back to the home screen. Going to the home screen does not
+ // qualify as the user leaving the activity's flow. The time tracking is considered
+ // complete only when the user switches to another activity that is not part of the
+ // tracked flow.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+ } else {
+ // With platforms that have no home screen, focus is returned to something else that is
+ // considered a completion of the tracked activity flow, and hence time tracking is
+ // triggered.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ }
// Issuing now another activity will trigger the timing information release.
final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
@@ -525,9 +550,20 @@
assertEquals(RESULT_PASS, appEndReceiver.waitForActivity());
appEndReceiver.close();
- // At this time the timerReceiver should not fire, even though the activity has shut down.
- assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
- assertTrue(timeReceiver.mTimeUsed == 0);
+ if (!noHomeScreen()) {
+ // At this time the timerReceiver should not fire, even though the activity has shut
+ // down, because we are back to the home screen. Going to the home screen does not
+ // qualify as the user leaving the activity's flow. The time tracking is considered
+ // complete only when the user switches to another activity that is not part of the
+ // tracked flow.
+ assertEquals(RESULT_TIMEOUT, timeReceiver.waitForActivity());
+ assertTrue(timeReceiver.mTimeUsed == 0);
+ } else {
+ // With platforms that have no home screen, focus is returned to something else that is
+ // considered a completion of the tracked activity flow, and hence time tracking is
+ // triggered.
+ assertEquals(RESULT_PASS, timeReceiver.waitForActivity());
+ }
// Issue another activity so that the timing information gets released.
final Intent dummyIntent = new Intent(context, MockApplicationActivity.class);
diff --git a/tests/app/src/android/app/cts/AlertWindowsTests.java b/tests/app/src/android/app/cts/AlertWindowsTests.java
index 6d76d3b..f7c8ff8 100644
--- a/tests/app/src/android/app/cts/AlertWindowsTests.java
+++ b/tests/app/src/android/app/cts/AlertWindowsTests.java
@@ -17,41 +17,48 @@
package android.app.cts;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE_DEPRECATED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
import static android.content.Context.BIND_ALLOW_OOM_MANAGEMENT;
import static android.content.Context.BIND_AUTO_CREATE;
import static android.content.Context.BIND_NOT_FOREGROUND;
+
import static com.android.app2.AlertWindowService.MSG_ADD_ALERT_WINDOW;
import static com.android.app2.AlertWindowService.MSG_ON_ALERT_WINDOW_ADDED;
import static com.android.app2.AlertWindowService.MSG_ON_ALERT_WINDOW_REMOVED;
import static com.android.app2.AlertWindowService.MSG_REMOVE_ALERT_WINDOW;
import static com.android.app2.AlertWindowService.MSG_REMOVE_ALL_ALERT_WINDOWS;
import static com.android.app2.AlertWindowService.NOTIFICATION_MESSENGER_EXTRA;
+
import static org.junit.Assert.assertEquals;
-import android.platform.test.annotations.Presubmit;
-import com.android.app2.AlertWindowService;
-import com.android.compatibility.common.util.SystemUtil;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.runner.RunWith;
-import org.junit.Test;
-
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
+import android.platform.test.annotations.Presubmit;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+import com.android.app2.AlertWindowService;
+import com.android.compatibility.common.util.SystemUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.function.Function;
+
/**
* Build: mmma -j32 cts/tests/app
* Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsAppTestCases android.app.cts.AlertWindowsTests
@@ -61,12 +68,20 @@
public class AlertWindowsTests {
private static final String TAG = "AlertWindowsTests";
+
private static final boolean DEBUG = false;
private static final long WAIT_TIME_MS = 2 * 1000;
+ private static final String SDK25_PACKAGE_NAME = "com.android.appSdk25";
+
private Messenger mService;
private String mServicePackageName;
+ private int mServiceUid;
+
+ private PackageManager mPm;
+
private ActivityManager mAm;
+ private ActivityManager mAm25; // ActivityManager created for an SDK 25 app context.
private final Messenger mMessenger = new Messenger(new IncomingHandler(Looper.getMainLooper()));
private final Object mAddedLock = new Object();
@@ -76,7 +91,12 @@
public void setUp() throws Exception {
if (DEBUG) Log.e(TAG, "setUp");
final Context context = InstrumentationRegistry.getTargetContext();
+
+ mPm = context.getPackageManager();
+
mAm = context.getSystemService(ActivityManager.class);
+ mAm25 = context.createPackageContext(SDK25_PACKAGE_NAME, 0)
+ .getSystemService(ActivityManager.class);
final Intent intent = new Intent();
intent.setClassName(AlertWindowService.class.getPackage().getName(),
@@ -107,27 +127,34 @@
public void testAlertWindowOomAdj() throws Exception {
setAlertWindowPermission(true /* allow */);
- assertImportance(IMPORTANCE_PERCEPTIBLE);
+ assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
+ assertUidImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
+
addAlertWindow();
// Process importance should be increased to visible when the service has an alert window.
- assertImportance(IMPORTANCE_VISIBLE);
+ assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
+
+ // TODO: Somehow getUidImportance still returns 230 (IMPORTANCE_PERCEPTIBLE) instead of
+ // IMPORTANCE_VISIBLE(200)
+ // assertUidImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
+
addAlertWindow();
- assertImportance(IMPORTANCE_VISIBLE);
+ assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
setAlertWindowPermission(false /* allow */);
// Process importance should no longer be visible since its alert windows are not allowed to
// be visible.
- assertImportance(IMPORTANCE_PERCEPTIBLE);
+ assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
setAlertWindowPermission(true /* allow */);
// They can show again so importance should be visible again.
- assertImportance(IMPORTANCE_VISIBLE);
+ assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
removeAlertWindow();
- assertImportance(IMPORTANCE_VISIBLE);
+ assertPackageImportance(IMPORTANCE_VISIBLE, IMPORTANCE_VISIBLE);
removeAlertWindow();
// Process importance should no longer be visible when the service no longer as alert
// windows.
- assertImportance(IMPORTANCE_PERCEPTIBLE);
+ assertPackageImportance(IMPORTANCE_PERCEPTIBLE, IMPORTANCE_PERCEPTIBLE_DEPRECATED);
}
private void addAlertWindow() throws Exception {
@@ -152,7 +179,8 @@
SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(), cmd);
}
- private void assertImportance(int expected) throws Exception {
+ private void assertImportance(Function<ActivityManager, Integer> apiCaller,
+ int expectedForO, int expectedForPreO) throws Exception {
int retry = 3;
int actual;
@@ -161,10 +189,29 @@
// for changes in the uid importance. However, the way it is currently structured
// doesn't really work for this use case right now...
Thread.sleep(500);
- actual = mAm.getPackageImportance(mServicePackageName);
- } while (actual != expected && --retry > 0);
+ actual = apiCaller.apply(mAm);
+ } while (actual != expectedForO && --retry > 0);
- assertEquals(expected, actual);
+ assertEquals(expectedForO, actual);
+
+ // Check the result for pre-O apps.
+ assertEquals(expectedForPreO, (int) apiCaller.apply(mAm25));
+ }
+
+ /**
+ * Make sure {@link ActivityManager#getPackageImportance} returns the expected value.
+ */
+ private void assertPackageImportance(int expectedForO, int expectedForPreO) throws Exception {
+ assertImportance(am -> am.getPackageImportance(mServicePackageName),
+ expectedForO, expectedForPreO);
+ }
+
+ /**
+ * Make sure {@link ActivityManager#getUidImportance(int)} returns the expected value.
+ */
+ private void assertUidImportance(int expectedForO, int expectedForPreO) throws Exception {
+ assertImportance(am -> am.getUidImportance(mServiceUid),
+ expectedForO, expectedForPreO);
}
private final ServiceConnection mConnection = new ServiceConnection() {
@@ -173,6 +220,11 @@
if (DEBUG) Log.e(TAG, "onServiceConnected");
mService = new Messenger(service);
mServicePackageName = name.getPackageName();
+ try {
+ mServiceUid = mPm.getPackageUid(mServicePackageName, 0);
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException("getPackageUid() failed.", e);
+ }
synchronized (mConnection) {
notifyAll();
}
@@ -183,6 +235,7 @@
if (DEBUG) Log.e(TAG, "onServiceDisconnected");
mService = null;
mServicePackageName = null;
+ mServiceUid = 0;
}
};
diff --git a/tests/app/src/android/app/cts/NotificationChannelTest.java b/tests/app/src/android/app/cts/NotificationChannelTest.java
index 74047be..70ec9cf 100644
--- a/tests/app/src/android/app/cts/NotificationChannelTest.java
+++ b/tests/app/src/android/app/cts/NotificationChannelTest.java
@@ -25,6 +25,7 @@
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Parcel;
+import android.provider.Settings;
import android.test.AndroidTestCase;
public class NotificationChannelTest extends AndroidTestCase {
@@ -52,7 +53,7 @@
assertEquals(false, channel.shouldVibrate());
assertEquals(null, channel.getVibrationPattern());
assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
- assertEquals(null, channel.getSound());
+ assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, channel.getSound());
assertTrue(channel.canShowBadge());
assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, channel.getAudioAttributes());
assertEquals(null, channel.getGroup());
diff --git a/tests/autofillservice/AndroidManifest.xml b/tests/autofillservice/AndroidManifest.xml
index 663fe40..32bf5a5 100644
--- a/tests/autofillservice/AndroidManifest.xml
+++ b/tests/autofillservice/AndroidManifest.xml
@@ -51,8 +51,10 @@
</intent-filter>
</activity>
<activity android:name=".EmptyActivity"/>
+ <activity android:name=".DummyActivity"/>
<activity android:name=".OutOfProcessLoginActivity"
android:process="android.autofillservice.cts.outside"/>
+ <activity android:name=".FragmentContainerActivity" />
<service
android:name=".InstrumentedAutoFillService"
diff --git a/tests/autofillservice/res/layout/fragment_container.xml b/tests/autofillservice/res/layout/fragment_container.xml
new file mode 100644
index 0000000..156efad
--- /dev/null
+++ b/tests/autofillservice/res/layout/fragment_container.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/rootContainer" />
diff --git a/tests/autofillservice/res/layout/fragment_with_edittext.xml b/tests/autofillservice/res/layout/fragment_with_edittext.xml
new file mode 100644
index 0000000..e0d4584
--- /dev/null
+++ b/tests/autofillservice/res/layout/fragment_with_edittext.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <EditText android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/editText1" />
+
+ <EditText android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/editText2" />
+</LinearLayout>
diff --git a/tests/autofillservice/res/layout/view_attribute_test_activity.xml b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
index e383d6c..96c0186 100644
--- a/tests/autofillservice/res/layout/view_attribute_test_activity.xml
+++ b/tests/autofillservice/res/layout/view_attribute_test_activity.xml
@@ -19,34 +19,6 @@
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:id="@+id/rootContainer">
- <EditText android:id="@+id/firstLevelDefault" android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <EditText android:id="@+id/firstLevelInherit" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="inherit" />
-
- <EditText android:id="@+id/firstLevelAuto" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="auto" />
-
- <EditText android:id="@+id/firstLevelManual" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="manual" />
-
- <LinearLayout android:id="@+id/manualContainer" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="manual"
- android:orientation="vertical">
- <EditText android:id="@+id/manualContainerDefault" android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <EditText android:id="@+id/manualContainerInherit" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="inherit" />
-
- <EditText android:id="@+id/manualContainerAuto" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="auto" />
-
- <EditText android:id="@+id/manualContainerManual" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:autofillMode="manual" />
- </LinearLayout>
-
<TextView android:id="@+id/textViewNoHint" android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:id="@+id/textViewHintCustom" android:layout_width="wrap_content"
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java
index f0b56d4..efc0b2c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AbstractAutoFillActivity.java
@@ -50,8 +50,8 @@
});
try {
if (!latch.await(timeoutMs, TimeUnit.MILLISECONDS)) {
- throw new AssertionError(
- "action on UI thread timed out after " + timeoutMs + " ms");
+ throw new RetryableException("action on UI thread timed out after %d ms",
+ timeoutMs);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index df61e37..d18e621 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -32,6 +32,7 @@
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.runner.RunWith;
/**
@@ -48,6 +49,9 @@
protected static final Replier sReplier = InstrumentedAutoFillService.getReplier();
+ @Rule
+ public final RetryRule mRetryRule = new RetryRule(2);
+
@BeforeClass
public static void removeLockScreen() {
runShellCommand("input keyevent KEYCODE_WAKEUP");
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
new file mode 100644
index 0000000..4a0e992
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static android.autofillservice.cts.FragmentContainerActivity.FRAGMENT_TAG;
+import static android.autofillservice.cts.Helper.FILL_TIMEOUT_MS;
+import static android.autofillservice.cts.Helper.eventually;
+import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Fragment;
+import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
+import android.content.Intent;
+import android.service.autofill.SaveInfo;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.test.rule.ActivityTestRule;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+/**
+ * Tests that the session finishes when the views and fragments go away
+ */
+public class AutoFinishSessionTest extends AutoFillServiceTestCase {
+ @Rule
+ public final ActivityTestRule<FragmentContainerActivity> mActivityRule =
+ new ActivityTestRule<>(FragmentContainerActivity.class);
+ private FragmentContainerActivity mActivity;
+ private EditText mEditText1;
+ private EditText mEditText2;
+ private Fragment mFragment;
+ private ViewGroup mParent;
+
+ @Before
+ public void initViews() {
+ mActivity = mActivityRule.getActivity();
+ mEditText1 = mActivity.findViewById(R.id.editText1);
+ mEditText2 = mActivity.findViewById(R.id.editText2);
+ mFragment = mActivity.getFragmentManager().findFragmentByTag(FRAGMENT_TAG);
+ mParent = ((ViewGroup) mEditText1.getParent());
+
+ assertThat(mFragment).isNotNull();
+ }
+
+ private void removeViewsBaseTest(@NonNull Runnable firstRemove, @Nullable Runnable firstCheck,
+ @Nullable Runnable secondRemove, String... viewsToSave)
+ throws Exception {
+ enableService();
+ try {
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, viewsToSave).build());
+
+ // Trigger autofill
+ eventually(() -> {
+ mActivity.syncRunOnUiThread(() -> mEditText2.requestFocus());
+ mActivity.syncRunOnUiThread(() -> mEditText1.requestFocus());
+
+ try {
+ sReplier.getNextFillRequest();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }, (int) (FILL_TIMEOUT_MS * 2));
+
+ sUiBot.assertNoDatasets();
+
+ // remove first set of views
+ mActivity.syncRunOnUiThread(() -> {
+ mEditText1.setText("editText1-filled");
+ mEditText2.setText("editText2-filled");
+ });
+ firstRemove.run();
+
+ // Check state between remove operations
+ if (firstCheck != null) {
+ firstCheck.run();
+ }
+
+ // remove second set of views
+ if (secondRemove != null) {
+ secondRemove.run();
+ }
+
+ // Save should be shows after all remove operations were executed
+ sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+ SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ for (String view : viewsToSave) {
+ assertThat(findNodeByResourceId(saveRequest.structure, view)
+ .getAutofillValue().getTextValue().toString()).isEqualTo(view + "-filled");
+ }
+ } finally {
+ disableService();
+ }
+ }
+
+ @Test
+ public void removeBothViewsToFinishSession() throws Exception {
+ removeViewsBaseTest(
+ () -> mActivity.syncRunOnUiThread(
+ () -> ((ViewGroup) mEditText1.getParent()).removeView(mEditText1)),
+ () -> sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC),
+ () -> mActivity.syncRunOnUiThread(
+ () -> ((ViewGroup) mEditText2.getParent()).removeView(mEditText2)),
+ "editText1", "editText2");
+ }
+
+ @Test
+ public void removeOneViewToFinishSession() throws Exception {
+ removeViewsBaseTest(
+ () -> mActivity.syncRunOnUiThread(() -> {
+ // Do not trigger new partition when switching to editText2
+ mEditText2.setFocusable(false);
+
+ mParent.removeView(mEditText1);
+ }),
+ null,
+ null,
+ "editText1");
+ }
+
+ @Test
+ public void hideOneViewToFinishSession() throws Exception {
+ removeViewsBaseTest(
+ () -> mActivity.syncRunOnUiThread(
+ () -> mEditText1.setVisibility(ViewGroup.INVISIBLE)),
+ null,
+ null,
+ "editText1");
+ }
+
+ @Test
+ public void removeFragmentToFinishSession() throws Exception {
+ removeViewsBaseTest(
+ () -> mActivity.syncRunOnUiThread(
+ () -> mActivity.getFragmentManager().beginTransaction().remove(
+ mFragment).commitNow()),
+ null,
+ null,
+ "editText1", "editText2");
+ }
+
+ @Test
+ public void removeParentToFinishSession() throws Exception {
+ removeViewsBaseTest(
+ () -> mActivity.syncRunOnUiThread(
+ () -> ((ViewGroup) mParent.getParent()).removeView(mParent)),
+ null,
+ null,
+ "editText1", "editText2");
+ }
+
+ @Test
+ public void hideParentToFinishSession() throws Exception {
+ removeViewsBaseTest(
+ () -> mActivity.syncRunOnUiThread(() -> mParent.setVisibility(ViewGroup.INVISIBLE)),
+ null,
+ null,
+ "editText1", "editText2");
+ }
+
+ /**
+ * An activity that is currently getting autofilled might go into the background. While the
+ * tracked views are not visible on the screen anymore, this should not trigger a save.
+ */
+ public void activityToBackgroundShouldNotTriggerSave(@Nullable Runnable removeInBackGround,
+ @Nullable Runnable removeInForeGroup) throws Exception {
+ enableService();
+ try {
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setFlags(SaveInfo.FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE)
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText1").build());
+
+ // Trigger autofill
+ eventually(() -> {
+ mActivity.syncRunOnUiThread(() -> mEditText2.requestFocus());
+ mActivity.syncRunOnUiThread(() -> mEditText1.requestFocus());
+
+ try {
+ sReplier.getNextFillRequest();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }, (int) (FILL_TIMEOUT_MS * 2));
+
+ sUiBot.assertNoDatasets();
+
+ mActivity.syncRunOnUiThread(() -> {
+ mEditText1.setText("editText1-filled");
+ mEditText2.setText("editText2-filled");
+ });
+
+ // Start activity on top
+ mActivity.startActivity(new Intent(getContext(),
+ ManualAuthenticationActivity.class));
+ mActivity.waitUntilStopped();
+
+ if (removeInBackGround != null) {
+ removeInBackGround.run();
+ }
+
+ sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC);
+
+ // Remove previously started activity from top
+ sUiBot.selectById("android.autofillservice.cts:id/button");
+ mActivity.waitUntilResumed();
+
+ if (removeInForeGroup != null) {
+ sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC);
+
+ removeInForeGroup.run();
+ }
+
+ // Save should be shows after all remove operations were executed
+ sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+ SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ assertThat(findNodeByResourceId(saveRequest.structure, "editText1")
+ .getAutofillValue().getTextValue().toString()).isEqualTo("editText1-filled");
+ } finally {
+ disableService();
+ }
+ }
+
+ @Test
+ public void removeViewInBackground() throws Exception {
+ activityToBackgroundShouldNotTriggerSave(
+ () -> mActivity.syncRunOnUiThread(() -> {
+ // Do not trigger new partition when switching to editText2
+ mEditText2.setFocusable(false);
+
+ mParent.removeView(mEditText1);
+ }),
+ null);
+ }
+
+ @Test
+ public void hideViewInBackground() throws Exception {
+ activityToBackgroundShouldNotTriggerSave(
+ () -> mActivity.syncRunOnUiThread(() -> {
+ // Do not trigger new partition when switching to editText2
+ mEditText2.setFocusable(false);
+
+ mEditText1.setVisibility(ViewGroup.INVISIBLE);
+ }),
+ null);
+ }
+
+ @Test
+ public void hideParentInBackground() throws Exception {
+ activityToBackgroundShouldNotTriggerSave(
+ () -> mActivity.syncRunOnUiThread(() -> mParent.setVisibility(ViewGroup.INVISIBLE)),
+ null);
+ }
+
+ @Test
+ public void removeParentInBackground() throws Exception {
+ activityToBackgroundShouldNotTriggerSave(
+ () -> mActivity.syncRunOnUiThread(
+ () -> ((ViewGroup) mParent.getParent()).removeView(mParent)),
+ null);
+ }
+
+ @Test
+ public void removeViewAfterBackground() throws Exception {
+ activityToBackgroundShouldNotTriggerSave(
+ () -> mActivity.syncRunOnUiThread(() -> {
+ // Do not trigger new fill request when closing activity
+ mEditText1.setFocusable(false);
+ mEditText2.setFocusable(false);
+ }),
+ () -> mActivity.syncRunOnUiThread(() -> {
+ mParent.removeView(mEditText1);
+ }));
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index 2fa29ce..b4f5f06 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -66,6 +66,7 @@
private final String[] mAuthenticationIds;
private final CharSequence mNegativeActionLabel;
private final IntentSender mNegativeActionListener;
+ private final int mFlags;
private CannedFillResponse(Builder builder) {
mDatasets = builder.mDatasets;
@@ -79,6 +80,7 @@
mAuthenticationIds = builder.mAuthenticationIds;
mNegativeActionLabel = builder.mNegativeActionLabel;
mNegativeActionListener = builder.mNegativeActionListener;
+ mFlags = builder.mFlags;
}
/**
@@ -101,8 +103,17 @@
}
}
if (mRequiredSavableIds != null) {
- final SaveInfo.Builder saveInfo = new SaveInfo.Builder(mSaveType,
- getAutofillIds(structure, mRequiredSavableIds));
+ final SaveInfo.Builder saveInfo;
+
+ if (mRequiredSavableIds == null) {
+ saveInfo = new SaveInfo.Builder(mSaveType, null);
+ } else {
+ saveInfo = new SaveInfo.Builder(mSaveType,
+ getAutofillIds(structure, mRequiredSavableIds));
+ }
+
+ saveInfo.setFlags(mFlags);
+
if (mOptionalSavableIds != null) {
saveInfo.setOptionalIds(getAutofillIds(structure, mOptionalSavableIds));
}
@@ -126,6 +137,7 @@
return "CannedFillResponse: [datasets=" + mDatasets
+ ", requiredSavableIds=" + Arrays.toString(mRequiredSavableIds)
+ ", optionalSavableIds=" + Arrays.toString(mOptionalSavableIds)
+ + ", mFlags=" + mFlags
+ ", saveDescription=" + mSaveDescription
+ ", hasPresentation=" + (mPresentation != null)
+ ", hasAuthentication=" + (mAuthentication != null)
@@ -145,6 +157,7 @@
private String[] mAuthenticationIds;
private CharSequence mNegativeActionLabel;
private IntentSender mNegativeActionListener;
+ private int mFlags;
public Builder addDataset(CannedDataset dataset) {
mDatasets.add(dataset);
@@ -160,6 +173,11 @@
return this;
}
+ public Builder setFlags(int flags) {
+ mFlags = flags;
+ return this;
+ }
+
/**
* Sets the optional savable ids based on they {@code resourceId}.
*/
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DummyActivity.java b/tests/autofillservice/src/android/autofillservice/cts/DummyActivity.java
new file mode 100644
index 0000000..a1f5bd9
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/DummyActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class DummyActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView text = new TextView(this);
+ text.setText("foo");
+ setContentView(text);
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FragmentContainerActivity.java b/tests/autofillservice/src/android/autofillservice/cts/FragmentContainerActivity.java
new file mode 100644
index 0000000..7be4496
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/FragmentContainerActivity.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Activity containing an fragment
+ */
+public class FragmentContainerActivity extends AbstractAutoFillActivity {
+ static final String FRAGMENT_TAG =
+ FragmentContainerActivity.class.getName() + "#FRAGMENT_TAG";
+ private CountDownLatch mResumed = new CountDownLatch(1);
+ private CountDownLatch mStopped = new CountDownLatch(0);
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.fragment_container);
+
+ // have to manually add fragment as we cannot remove it otherwise
+ getFragmentManager().beginTransaction().add(R.id.rootContainer,
+ new FragmentWithEditText(), FRAGMENT_TAG).commitNow();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+
+ mStopped = new CountDownLatch(1);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ mResumed.countDown();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+
+ mResumed = new CountDownLatch(1);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+
+ mStopped.countDown();
+ }
+
+ public boolean waitUntilResumed() throws InterruptedException {
+ return mResumed.await(Helper.UI_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+
+ public boolean waitUntilStopped() throws InterruptedException {
+ return mStopped.await(Helper.UI_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FragmentWithEditText.java b/tests/autofillservice/src/android/autofillservice/cts/FragmentWithEditText.java
new file mode 100644
index 0000000..963daff
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/FragmentWithEditText.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.support.annotation.Nullable;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+
+/**
+ * A fragment with containing a single {@link EditText}
+ */
+public class FragmentWithEditText extends Fragment {
+ @Override
+ @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_with_edittext, null);
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java b/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
index 6df6f10..c9b6d30 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/GridActivity.java
@@ -113,7 +113,7 @@
onCell(row, column, (c) -> queue.offer(c.getText().toString()));
final String text = queue.poll(100, TimeUnit.MILLISECONDS);
if (text == null) {
- throw new AssertionError("text not set in 100ms");
+ throw new RetryableException("text not set in 100ms");
}
return text;
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index c78a6e1..bd69587 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -107,7 +107,7 @@
final String state = sConnectionStates.poll(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (state == null) {
dumpAutofillService();
- throw new AssertionError("not connected in " + CONNECTION_TIMEOUT_MS + " ms");
+ throw new RetryableException("not connected in %d ms", CONNECTION_TIMEOUT_MS);
}
assertWithMessage("Invalid connection state").that(state).isEqualTo(STATE_CONNECTED);
}
@@ -122,7 +122,7 @@
final String state = sConnectionStates.poll(2 * IDLE_UNBIND_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
if (state == null) {
- throw new AssertionError("not disconnected in " + IDLE_UNBIND_TIMEOUT_MS + " ms");
+ throw new RetryableException("not disconnected in %d ms", IDLE_UNBIND_TIMEOUT_MS);
}
assertWithMessage("Invalid connection state").that(state).isEqualTo(STATE_DISCONNECTED);
}
@@ -221,8 +221,8 @@
FillRequest getNextFillRequest() throws InterruptedException {
final FillRequest request = mFillRequests.poll(FILL_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (request == null) {
- throw new AssertionError(
- "onFillRequest() not called in " + FILL_TIMEOUT_MS + " ms");
+ throw new RetryableException("onFillRequest() not called in %s ms",
+ FILL_TIMEOUT_MS);
}
return request;
}
@@ -245,8 +245,8 @@
SaveRequest getNextSaveRequest() throws InterruptedException {
final SaveRequest request = mSaveRequests.poll(SAVE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (request == null) {
- throw new AssertionError(
- "onSaveRequest() not called in " + SAVE_TIMEOUT_MS + " ms");
+ throw new RetryableException(
+ "onSaveRequest() not called in %d ms", SAVE_TIMEOUT_MS);
}
return request;
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index e294c33..635af0c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -39,7 +39,6 @@
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_USERNAME;
import static android.text.InputType.TYPE_NULL;
import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
-import static android.view.View.AUTOFILL_MODE_MANUAL;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.autofill.AutofillManager.FLAG_MANUAL_REQUEST;
@@ -64,6 +63,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeProvider;
import android.view.autofill.AutofillManager;
+import android.widget.RemoteViews;
import org.junit.After;
import org.junit.Before;
@@ -1216,14 +1216,13 @@
assertThat(usernameContainer.getChildCount()).isEqualTo(2);
}
- @Test
public void testAutofillManuallyOneDataset() throws Exception {
// Set service.
enableService();
// And activity.
mActivity.onUsername((v) -> {
- v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+ // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
// TODO(b/33197203, b/33802548): setting an empty text, otherwise longPress() does not
// display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
v.setText("");
@@ -1250,12 +1249,10 @@
mActivity.assertAutoFilled();
}
- @Test
public void testAutofillManuallyTwoDatasetsPickFirst() throws Exception {
autofillManuallyTwoDatasets(true);
}
- @Test
public void testAutofillManuallyTwoDatasetsPickSecond() throws Exception {
autofillManuallyTwoDatasets(false);
}
@@ -1266,7 +1263,7 @@
// And activity.
mActivity.onUsername((v) -> {
- v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+ //v.setAutofillMode(AUTOFILL_MODE_MANUAL);
// TODO(b/33197203, b/33802548): setting an empty text, otherwise longPress() does not
// display the AUTOFILL context menu. Need to fix it, but it's a test case issue...
v.setText("");
@@ -1460,4 +1457,47 @@
setUserRestrictionForAutofill(false);
}
}
+
+ @Test
+ public void testClickCustomButton() throws Exception {
+ // Set service.
+ enableService();
+
+ Intent intent = new Intent(getContext(), EmptyActivity.class);
+ IntentSender sender = PendingIntent.getActivity(getContext(), 0, intent,
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT)
+ .getIntentSender();
+
+ RemoteViews presentation = new RemoteViews(getContext().getPackageName(),
+ R.layout.list_item);
+ presentation.setTextViewText(R.id.text1, "Poke");
+ Intent firstIntent = new Intent(getContext(), DummyActivity.class);
+ presentation.setOnClickPendingIntent(R.id.text1, PendingIntent.getActivity(
+ getContext(), 0, firstIntent, PendingIntent.FLAG_ONE_SHOT
+ | PendingIntent.FLAG_CANCEL_CURRENT));
+
+ // Set expectations.
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setAuthentication(sender)
+ .setPresentation(presentation)
+ .build());
+
+ // Trigger auto-fill.
+ mActivity.onUsername(View::requestFocus);
+
+ // Wait for onFill() before proceeding.
+ sReplier.getNextFillRequest();
+
+ // Click on the custom button
+ sUiBot.selectByText("Poke");
+
+ // Make sure the click worked
+ sUiBot.selectByText("foo");
+
+ // Go back to the filled app.
+ sUiBot.pressBack();
+
+ // The session should be gone
+ assertNoDanglingSessions();
+ }
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
index c2af4cc1..32844d4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
@@ -49,25 +49,24 @@
setContentView(R.layout.single_button_activity);
findViewById(R.id.button).setOnClickListener((v) -> {
- // We should get the assist structure
AssistStructure structure = getIntent().getParcelableExtra(
AutofillManager.EXTRA_ASSIST_STRUCTURE);
- assertWithMessage("structure not called").that(structure).isNotNull();
+ if (structure != null) {
+ Parcelable result;
+ if (sResponse != null) {
+ result = sResponse.asFillResponse(structure);
+ } else if (sDataset != null) {
+ result = sDataset.asDataset(structure);
+ } else {
+ throw new IllegalStateException("no dataset or response");
+ }
- Parcelable result = null;
- if (sResponse != null) {
- result = sResponse.asFillResponse(structure);
- } else if (sDataset != null) {
- result = sDataset.asDataset(structure);
- } else {
- throw new IllegalStateException("no dataset or response");
+ // Pass on the auth result
+ Intent intent = new Intent();
+ intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
+ setResult(RESULT_OK, intent);
}
- // Pass on the auth result
- Intent intent = new Intent();
- intent.putExtra(AutofillManager.EXTRA_AUTHENTICATION_RESULT, result);
- setResult(RESULT_OK, intent);
-
// Done
finish();
});
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java b/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java
index 13887fa..48b0c2f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MyAutofillCallback.java
@@ -50,7 +50,7 @@
MyEvent getEvent() throws InterruptedException {
final MyEvent event = mEvents.poll(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
if (event == null) {
- throw new AssertionError("no event in " + CONNECTION_TIMEOUT_MS + " ms");
+ throw new RetryableException("no event in %d ms", CONNECTION_TIMEOUT_MS);
}
return event;
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java b/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
new file mode 100644
index 0000000..a4db0f4
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryRule.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.util.Log;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Custom JUnit4 rule that retry tests when they fail due to a {@link RetryableException}.
+ */
+public class RetryRule implements TestRule {
+
+ private static final String TAG = "RetryRule";
+ private final int mMaxAttempts;
+
+ public RetryRule(int maxAttempts) {
+ if (maxAttempts < 2) {
+ throw new IllegalArgumentException(
+ "Must retry at least once; otherwise, what's the point?");
+ }
+ mMaxAttempts = maxAttempts;
+ }
+
+ @Override
+ public Statement apply(Statement base, Description description) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ RetryableException caught = null;
+ for (int i = 1; i <= mMaxAttempts; i++) {
+ try {
+ base.evaluate();
+ return;
+ } catch (RetryableException e) {
+ caught = e;
+ Log.w(TAG,
+ description.getDisplayName() + ": attempt " + i + " failed: " + e);
+ }
+ }
+ throw caught;
+ }
+ };
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryRuleTest.java b/tests/autofillservice/src/android/autofillservice/cts/RetryRuleTest.java
new file mode 100644
index 0000000..50ae8c8
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryRuleTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.Statement;
+
+@RunWith(AndroidJUnit4.class)
+public class RetryRuleTest {
+
+ private final Description mDescription = Description.createSuiteDescription("Whatever");
+
+ private static final RetryableException sRetryableException =
+ new RetryableException("Y U NO RETRY?");
+
+ private static class RetryableStatement extends Statement {
+ private final int mNumberFailures;
+ private int mNumberCalls;
+
+ RetryableStatement(int numberFailures) {
+ mNumberFailures = numberFailures;
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ mNumberCalls ++;
+ if (mNumberCalls <= mNumberFailures) {
+ throw sRetryableException;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "RetryableStatement: failures=" + mNumberFailures + ", calls=" + mNumberCalls;
+ }
+ }
+
+ @Test
+ public void testPass() throws Throwable {
+ final RetryRule rule = new RetryRule(2);
+ rule.apply(new RetryableStatement(1), mDescription).evaluate();
+ }
+
+ @Test
+ public void testFail() throws Throwable {
+ final RetryRule rule = new RetryRule(2);
+ try {
+ rule.apply(new RetryableStatement(2), mDescription).evaluate();
+ throw new AssertionError("2ND CALL, Y U NO FAIL?");
+ } catch (RetryableException e) {
+ assertThat(e).isSameAs(sRetryableException);
+ }
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/RetryableException.java b/tests/autofillservice/src/android/autofillservice/cts/RetryableException.java
new file mode 100644
index 0000000..9b9d651
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/RetryableException.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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;
+
+/**
+ * Exception that cause the {@link RetryRule} to re-try a test.
+ */
+public class RetryableException extends RuntimeException {
+
+ public RetryableException(String msg) {
+ super(msg);
+ }
+
+ public RetryableException(String format, Object...args) {
+ this(String.format(format, args));
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 1f98171..deba8b7 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -92,7 +92,7 @@
// not showing...
return;
}
- throw new AssertionError("floating ui is shown: " + ui);
+ throw new RetryableException("floating ui is shown: %s", ui);
}
/**
@@ -202,6 +202,13 @@
}
/**
+ * Presses the back button.
+ */
+ void pressBack() {
+ mDevice.pressBack();
+ }
+
+ /**
* Asserts the save snackbar is not showing and returns it.
*/
void assertSaveNotShowing(int type) {
@@ -212,7 +219,7 @@
// not showing (in which case it wouldn't need a type as parameter).
return;
}
- throw new AssertionError("snack bar is showing");
+ throw new RetryableException("snack bar is showing");
}
private String getSaveTypeString(int type) {
@@ -328,7 +335,7 @@
}
menuNames.append("'").append(menuName).append("' ");
}
- throw new AssertionError("no '" + expectedText + "' on " + menuNames);
+ throw new RetryableException("no '%s' on '%s'", expectedText, menuNames);
}
/**
@@ -375,8 +382,8 @@
}
SystemClock.sleep(napTime);
}
- throw new AssertionError("Object with selector " + selector + " not found in "
- + mTimeout + " ms");
+ throw new RetryableException("Object with selector '%s' not found in %d ms",
+ selector, mTimeout);
}
/**
@@ -405,9 +412,10 @@
}
SystemClock.sleep(napTime);
}
- throw new AssertionError("Objects with selector " + selector + " not found in "
- + mTimeout + " ms");
+ throw new RetryableException("Objects with selector '%s' not found in %d ms",
+ selector, mTimeout);
}
+
private UiObject2 findDatasetPicker() {
final UiObject2 picker = waitForObject(By.res("android", RESOURCE_ID_DATASET_PICKER));
@@ -429,6 +437,6 @@
return;
}
}
- throw new AssertionError("Title (" + expectedTitle + ") not found for " + object);
+ throw new RetryableException("Title '%s' not found for %s", expectedTitle, object);
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
index 54b474e..763c57f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
@@ -18,16 +18,9 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.testng.Assert.assertThrows;
-
-import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
-import android.support.annotation.NonNull;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-import android.widget.EditText;
-import android.widget.LinearLayout;
-import android.widget.TextView;
import org.junit.Before;
import org.junit.Rule;
@@ -41,227 +34,10 @@
new ActivityTestRule<>(ViewAttributesTestActivity.class);
private ViewAttributesTestActivity mActivity;
- private EditText mFirstLevelDefault;
- private EditText mFirstLevelManual;
- private EditText mFirstLevelAuto;
- private EditText mFirstLevelInherit;
- private EditText mManualContainerInherit;
- private EditText mManualContainerDefault;
- private EditText mManualContainerManual;
- private EditText mManualContainerAuto;
- private OneTimeTextWatcher mFirstLevelDefaultTextWatcher;
@Before
public void setActivity() {
mActivity = mActivityRule.getActivity();
- mFirstLevelDefault = (EditText) mActivity.findViewById(R.id.firstLevelDefault);
- mFirstLevelManual = (EditText) mActivity.findViewById(R.id.firstLevelManual);
- mFirstLevelAuto = (EditText) mActivity.findViewById(R.id.firstLevelAuto);
- mFirstLevelInherit = (EditText) mActivity.findViewById(R.id.firstLevelInherit);
- mManualContainerDefault = (EditText) mActivity.findViewById(R.id.manualContainerDefault);
- mManualContainerManual = (EditText) mActivity.findViewById(R.id.manualContainerManual);
- mManualContainerAuto = (EditText) mActivity.findViewById(R.id.manualContainerAuto);
- mManualContainerInherit = (EditText) mActivity.findViewById(R.id.manualContainerInherit);
- }
-
- private void runOnUiThreadSync(@NonNull Runnable r) throws InterruptedException {
- RuntimeException exceptionOnUiThread[] = {null};
-
- synchronized (this) {
- mActivity.runOnUiThread(() -> {
- synchronized (this) {
- try {
- r.run();
- } catch (RuntimeException e) {
- exceptionOnUiThread[0] = e;
- }
- this.notify();
- }
- });
-
- wait();
- }
-
- if (exceptionOnUiThread[0] != null) {
- throw exceptionOnUiThread[0];
- }
- }
-
- /**
- * Sets the expectation for an auto-fill request, so it can be asserted through
- * {@link #assertAutoFilled()} later.
- */
- void expectAutoFill() {
- mFirstLevelDefaultTextWatcher = new OneTimeTextWatcher("firstLevelDefault",
- mFirstLevelDefault, "filled");
- mFirstLevelDefault.addTextChangedListener(mFirstLevelDefaultTextWatcher);
- }
-
- /**
- * Asserts the activity was auto-filled with the values passed to
- * {@link #expectAutoFill()}.
- */
- void assertAutoFilled() throws Exception {
- mFirstLevelDefaultTextWatcher.assertAutoFilled();
- }
-
- /**
- * Try to auto-fill by moving the focus to {@code field}. If the field should trigger an
- * auto-fill the auto-fill UI should show up.
- *
- * @param field The field to move the focus to
- * @param expectUI If the auto-fill UI is expected to show up
- *
- * @throws Exception If something unexpected happened
- */
- private void checkFieldBehavior(@NonNull EditText field, boolean expectUI) throws Exception {
- if (expectUI) {
- assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
- } else {
- assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
- }
-
- // Make sure the requestFocus triggers a change
- if (field == mFirstLevelManual) {
- runOnUiThreadSync(() -> mFirstLevelDefault.requestFocus());
- } else {
- runOnUiThreadSync(() -> mFirstLevelManual.requestFocus());
- }
-
- enableService();
-
- try {
- sReplier.addResponse(new CannedFillResponse.Builder()
- .addDataset(new CannedFillResponse.CannedDataset.Builder()
- .setField("firstLevelDefault", "filled")
- .setField("firstLevelManual", "filled")
- .setField("firstLevelAuto", "filled")
- .setField("firstLevelInherit", "filled")
- .setField("manualContainerDefault", "filled")
- .setField("manualContainerManual", "filled")
- .setField("manualContainerAuto", "filled")
- .setField("manualContainerInherit", "filled")
- .setPresentation(createPresentation("dataset"))
- .build())
- .build());
-
- expectAutoFill();
-
- runOnUiThreadSync(() -> field.requestFocus());
-
- Throwable exceptionDuringAutoFillTrigger = null;
- try {
- sReplier.getNextFillRequest();
- sUiBot.selectDataset("dataset");
- } catch (Throwable e) {
- if (expectUI) {
- throw e;
- } else {
- exceptionDuringAutoFillTrigger = e;
- }
- }
-
- if (expectUI) {
- assertAutoFilled();
- } else {
- assertThat(exceptionDuringAutoFillTrigger).isNotNull();
- }
- } finally {
- disableService();
- }
- }
-
- @Test
- public void checkDefaultValue() {
- assertThat(mFirstLevelDefault.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
- }
-
- @Test
- public void checkInheritValue() {
- assertThat(mFirstLevelInherit.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
- }
-
- @Test
- public void checkAutoValue() {
- assertThat(mFirstLevelAuto.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
- }
-
- @Test
- public void checkManualValue() {
- assertThat(mFirstLevelManual.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
- }
-
- @Test
- public void checkNestedDefaultValue() {
- assertThat(mManualContainerDefault.getAutofillMode()).isEqualTo(
- View.AUTOFILL_MODE_INHERIT);
- }
-
- @Test
- public void checkNestedInheritValue() {
- assertThat(mManualContainerInherit.getAutofillMode()).isEqualTo(
- View.AUTOFILL_MODE_INHERIT);
- }
-
- @Test
- public void checkNestedAutoValue() {
- assertThat(mManualContainerAuto.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
- }
-
- @Test
- public void checkNestedManualValue() {
- assertThat(mManualContainerManual.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
- }
-
- @Test
- public void checkDefaultBehavior() throws Exception {
- checkFieldBehavior(mFirstLevelDefault, true);
- }
-
- @Test
- public void checkInheritBehavior() throws Exception {
- checkFieldBehavior(mFirstLevelInherit, true);
- }
-
- @Test
- public void checkAutoBehavior() throws Exception {
- checkFieldBehavior(mFirstLevelAuto, true);
- }
-
- @Test
- public void checkManualBehavior() throws Exception {
- checkFieldBehavior(mFirstLevelManual, false);
- }
-
- @Test
- public void checkNestedDefaultBehavior() throws Exception {
- checkFieldBehavior(mManualContainerDefault, false);
- }
-
- @Test
- public void checkNestedInheritBehavior() throws Exception {
- checkFieldBehavior(mManualContainerInherit, false);
- }
-
- @Test
- public void checkNestedAutoBehavior() throws Exception {
- checkFieldBehavior(mManualContainerAuto, true);
- }
-
- @Test
- public void checkNestedManualBehavior() throws Exception {
- checkFieldBehavior(mManualContainerManual, false);
- }
-
- @Test
- public void checksetAutofillMode() {
- mFirstLevelDefault.setAutofillMode(View.AUTOFILL_MODE_MANUAL);
- assertThat(mFirstLevelDefault.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
- }
-
- @Test
- public void checkIllegalAutoFillModeSet() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> mFirstLevelDefault.setAutofillMode(-1));
}
@Test
@@ -317,85 +93,4 @@
assertThat(v.getAutofillHints()).isEqualTo(new String[]{View.AUTOFILL_HINT_PASSWORD,
View.AUTOFILL_HINT_EMAIL_ADDRESS});
}
-
- @Test
- public void attachViewToManualContainer() throws Exception {
- runOnUiThreadSync(() -> mFirstLevelManual.requestFocus());
- enableService();
-
- try {
- View view = new TextView(mActivity);
-
- view.setLayoutParams(
- new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.WRAP_CONTENT));
-
- assertThat(view.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
- assertThat(view.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-
- // Requesting focus should not trigger any mishaps
- runOnUiThreadSync(() -> view.requestFocus());
-
- LinearLayout attachmentPoint = (LinearLayout) mActivity.findViewById(
- R.id.manualContainer);
- runOnUiThreadSync(() -> attachmentPoint.addView(view));
-
- assertThat(view.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_MANUAL);
- } finally {
- disableService();
- }
- }
-
- @Test
- public void attachNestedViewToContainer() throws Exception {
- runOnUiThreadSync(() -> mFirstLevelManual.requestFocus());
- enableService();
-
- try {
- // Create view and viewGroup but do not attach to window
- LinearLayout container = (LinearLayout) mActivity.getLayoutInflater().inflate(
- R.layout.nested_layout, null);
- EditText field = container.findViewById(R.id.field);
-
- assertThat(field.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
- assertThat(container.getAutofillMode()).isEqualTo(View.AUTOFILL_MODE_INHERIT);
-
- // Resolved mode for detached views should behave as documented
- assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
- assertThat(container.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-
- // Requesting focus should not trigger any mishaps
- runOnUiThreadSync(() -> field.requestFocus());
-
- // Set up auto-fill service and response
- sReplier.addResponse(new CannedFillResponse.Builder()
- .addDataset(new CannedFillResponse.CannedDataset.Builder()
- .setField("field", "filled")
- .setPresentation(createPresentation("dataset"))
- .build())
- .build());
-
- OneTimeTextWatcher mViewWatcher = new OneTimeTextWatcher("field", field, "filled");
- field.addTextChangedListener(mViewWatcher);
-
- // As the focus is set to "field", attaching "container" should trigger an auto-fill
- // request on "field"
- LinearLayout attachmentPoint = (LinearLayout) mActivity.findViewById(
- R.id.rootContainer);
- runOnUiThreadSync(() -> attachmentPoint.addView(container));
-
- // Now the resolved auto-fill modes make sense, hence check them
- assertThat(field.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
- assertThat(container.getResolvedAutofillMode()).isEqualTo(View.AUTOFILL_MODE_AUTO);
-
- // We should now be able to select the data set
- sReplier.getNextFillRequest();
- sUiBot.selectDataset("dataset");
-
- // Check if auto-fill operation worked
- mViewWatcher.assertAutoFilled();
- } finally {
- disableService();
- }
- }
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index 6b97195..0344830 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -127,7 +127,7 @@
try {
VirtualContainerView.assertHtmlInfo(username);
VirtualContainerView.assertHtmlInfo(password);
- } catch (AssertionError e) {
+ } catch (AssertionError | RuntimeException e) {
dumpStructure("HtmlInfo failed", request.structure);
throw e;
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 6ae3011..b51e338 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -1649,10 +1649,6 @@
checkMeteringRect(afRegions);
}
}
- // ZSL must default to OFF
- if (request.get(CONTROL_ENABLE_ZSL) != null) {
- mCollector.expectKeyValueEquals(request, CONTROL_ENABLE_ZSL, false);
- }
}
// Sensor settings.
@@ -1915,6 +1911,13 @@
}
}
+ // Enable ZSL
+ if (template != CameraDevice.TEMPLATE_STILL_CAPTURE) {
+ if (mStaticInfo.areKeysAvailable(CONTROL_ENABLE_ZSL)) {
+ mCollector.expectKeyValueEquals(request, CONTROL_ENABLE_ZSL, false);
+ }
+ }
+
int[] outputFormats = mStaticInfo.getAvailableFormats(
StaticMetadata.StreamDirection.Output);
boolean supportRaw = false;
diff --git a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
index 6c48418..e011131 100644
--- a/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -1262,7 +1262,11 @@
private long getExposureValue(CaptureResult result) throws Exception {
int expTimeUs = (int) (getValueNotNull(result, CaptureResult.SENSOR_EXPOSURE_TIME) / 1000);
int sensitivity = getValueNotNull(result, CaptureResult.SENSOR_SENSITIVITY);
- return expTimeUs * sensitivity;
+ Integer postRawSensitivity = result.get(CaptureResult.CONTROL_POST_RAW_SENSITIVITY_BOOST);
+ if (postRawSensitivity != null) {
+ return (long) sensitivity * postRawSensitivity / 100 * expTimeUs;
+ }
+ return (long) sensitivity * expTimeUs;
}
private long getMaxExposureValue(CaptureRequest.Builder request, long maxExposureTimeUs,
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index e4ca5af..655621c 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -296,5 +296,12 @@
"android.telecom.cts.WiredHeadsetTest"
],
bug: 26149528
+},
+{
+ desciption: "Seems to be failing on X86, flaky on arm. Root cause to be investigated",
+ names: [
+ "android.webkit.cts.WebViewClientTest#testOnRenderProcessGone"
+ ],
+ bug: 37281280
}
]
diff --git a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
index b5e9cad..f234155 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentAnimatorTest.java
@@ -59,11 +59,8 @@
public ActivityTestRule<FragmentTestActivity> mActivityRule =
new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
- private Instrumentation mInstrumentation;
-
@Before
public void setupContainer() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
}
@@ -365,12 +362,12 @@
.replace(R.id.fragmentContainer, fragment2, "2")
.addToBackStack(null)
.commit();
- mInstrumentation.runOnMainSync(fm1::executePendingTransactions);
+ mActivityRule.runOnUiThread(fm1::executePendingTransactions);
FragmentTestUtil.waitForExecution(mActivityRule);
fm1.popBackStack();
- mInstrumentation.runOnMainSync(fm1::executePendingTransactions);
+ mActivityRule.runOnUiThread(fm1::executePendingTransactions);
FragmentTestUtil.waitForExecution(mActivityRule);
// Now fragment2 should be animating away
assertFalse(fragment2.isAdded());
diff --git a/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java b/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java
index 7d65b8c..6e6cda9 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentExecuteTests.java
@@ -41,11 +41,8 @@
public ActivityTestRule<FragmentTestActivity> mActivityRule =
new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
- private Instrumentation mInstrumentation;
-
@Before
public void setupContentView() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
}
@@ -58,7 +55,7 @@
final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
final StrictViewFragment fragment = new StrictViewFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
fm.beginTransaction()
diff --git a/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java b/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java
index f91eb65..bbd8d10 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentOptimizationTest.java
@@ -15,11 +15,11 @@
*/
package android.fragment.cts;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.app.FragmentManager;
-import android.app.Instrumentation;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -39,14 +39,12 @@
private ViewGroup mContainer;
private FragmentManager mFM;
- private Instrumentation mInstrumentation;
@Before
public void setup() {
FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
mContainer = (ViewGroup) mActivityRule.getActivity().findViewById(R.id.fragmentContainer);
mFM = mActivityRule.getActivity().getFragmentManager();
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
}
// Test that when you add and replace a fragment that only the replace's add
@@ -55,7 +53,7 @@
public void addReplace() throws Throwable {
final CountCallsFragment fragment1 = new CountCallsFragment();
final StrictViewFragment fragment2 = new StrictViewFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction().add(R.id.fragmentContainer, fragment1).addToBackStack(null).commit();
@@ -69,7 +67,7 @@
assertEquals(0, fragment1.onCreateViewCount);
FragmentTestUtil.assertChildren(mContainer, fragment2);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.popBackStack();
@@ -92,7 +90,7 @@
FragmentTestUtil.assertChildren(mContainer, fragment1);
// Now pop and add
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.popBackStack();
@@ -116,7 +114,7 @@
public void middlePop() throws Throwable {
final CountCallsFragment fragment1 = new CountCallsFragment();
final CountCallsFragment fragment2 = new CountCallsFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
@@ -146,7 +144,7 @@
public void optimizeRemove() throws Throwable {
final CountCallsFragment fragment1 = new CountCallsFragment();
final int[] id = new int[1];
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
id[0] = mFM.beginTransaction()
@@ -186,7 +184,7 @@
FragmentTestUtil.executePendingTransactions(mActivityRule);
assertEquals(1, fragment1.onCreateViewCount);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
@@ -224,7 +222,7 @@
assertEquals(1, fragment1.onAttachCount);
FragmentTestUtil.assertChildren(mContainer, fragment1);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction().detach(fragment1).addToBackStack(null).commit();
@@ -274,7 +272,7 @@
assertEquals(0, fragment1.onCreateViewCount);
FragmentTestUtil.assertChildren(mContainer);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction().attach(fragment1).addToBackStack(null).commit();
@@ -318,7 +316,7 @@
assertEquals(1, fragment1.onHideCount);
FragmentTestUtil.assertChildren(mContainer, fragment1);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
@@ -353,7 +351,7 @@
assertEquals(0, fragment1.onShowCount);
assertEquals(1, fragment1.onHideCount);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction().show(fragment1).addToBackStack(null).commit();
@@ -373,7 +371,7 @@
assertEquals(0, fragment1.onShowCount);
assertEquals(1, fragment1.onHideCount);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction().show(fragment1).addToBackStack(null).commit();
@@ -408,7 +406,7 @@
assertEquals(0, fragment1.onHideCount);
FragmentTestUtil.assertChildren(mContainer, fragment1);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction().hide(fragment1).addToBackStack(null).commit();
@@ -445,7 +443,7 @@
final CountCallsFragment fragment2 = new CountCallsFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
@@ -470,7 +468,7 @@
@Test
public void addPopBackStack() throws Throwable {
final CountCallsFragment fragment1 = new CountCallsFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
@@ -493,7 +491,7 @@
public void popNonBackStack() throws Throwable {
final CountCallsFragment fragment1 = new CountCallsFragment();
final CountCallsFragment fragment2 = new CountCallsFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
@@ -519,7 +517,7 @@
public void noOptimization() throws Throwable {
final CountCallsFragment fragment1 = new CountCallsFragment();
final CountCallsFragment fragment2 = new CountCallsFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFM.beginTransaction()
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java b/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
index c175164..62c4906 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTestUtil.java
@@ -23,10 +23,8 @@
import android.app.FragmentController;
import android.app.FragmentManager;
import android.app.FragmentManagerNonConfig;
-import android.app.Instrumentation;
import android.os.Looper;
import android.os.Parcelable;
-import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ActivityTestRule;
import android.util.Pair;
import android.view.View;
@@ -42,9 +40,14 @@
// the UI thread and then the execution will be added onto the queue after that.
// The two-cycle wait makes sure fragments have the opportunity to complete both
// before returning.
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- instrumentation.runOnMainSync(() -> {});
- instrumentation.runOnMainSync(() -> {});
+ try {
+ rule.runOnUiThread(() -> {
+ });
+ rule.runOnUiThread(() -> {
+ });
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
}
private static void runOnUiThreadRethrow(ActivityTestRule<? extends Activity> rule,
diff --git a/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java b/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
index 43a9590..7421377 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentTransitionTest.java
@@ -15,7 +15,8 @@
*/
package android.fragment.cts;
-import static junit.framework.Assert.*;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -23,22 +24,20 @@
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
-import com.android.compatibility.common.util.transition.TargetTracking;
-import com.android.compatibility.common.util.transition.TrackingTransition;
-
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
-import android.app.Instrumentation;
import android.app.SharedElementCallback;
import android.graphics.Rect;
import android.os.Bundle;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.transition.TransitionSet;
import android.view.View;
+import com.android.compatibility.common.util.transition.TargetTracking;
+import com.android.compatibility.common.util.transition.TrackingTransition;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -68,7 +67,6 @@
public ActivityTestRule<FragmentTestActivity> mActivityRule =
new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
- private Instrumentation mInstrumentation;
private FragmentManager mFragmentManager;
public FragmentTransitionTest(final boolean optimize) {
@@ -77,7 +75,6 @@
@Before
public void setup() throws Throwable {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
mFragmentManager = mActivityRule.getActivity().getFragmentManager();
FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
}
@@ -163,7 +160,7 @@
final TransitionFragment fragment2 = new TransitionFragment();
fragment2.setLayoutId(R.layout.scene2);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mFragmentManager.beginTransaction()
@@ -966,7 +963,7 @@
final View startRed = findRed();
final Rect startSharedRect = getBoundsOnScreen(startBlue);
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
for (int i = 0; i < numPops; i++) {
mFragmentManager.popBackStack();
}
diff --git a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
index 6f96811..e9c80e0 100644
--- a/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
+++ b/tests/fragment/src/android/fragment/cts/FragmentViewTests.java
@@ -46,13 +46,6 @@
public ActivityTestRule<FragmentTestActivity> mActivityRule =
new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
- private Instrumentation mInstrumentation;
-
- @Before
- public void setupInstrumentation() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- }
-
// Test that adding a fragment adds the Views in the proper order. Popping the back stack
// should remove the correct Views.
@Test
@@ -156,7 +149,7 @@
fm.beginTransaction().add(R.id.fragmentContainer, fragment1).commit();
FragmentTestUtil.executePendingTransactions(mActivityRule);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
try {
@@ -917,7 +910,7 @@
final StrictViewFragment fragment2 = new StrictViewFragment();
final StrictViewFragment fragment3 = new StrictViewFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
fm.popBackStack();
diff --git a/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java b/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
index a3c43aa..2b89bc2 100644
--- a/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
+++ b/tests/fragment/src/android/fragment/cts/PostponedTransitionTest.java
@@ -26,10 +26,8 @@
import android.app.FragmentController;
import android.app.FragmentManager;
import android.app.FragmentManagerNonConfig;
-import android.app.Instrumentation;
import android.os.Bundle;
import android.os.Parcelable;
-import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
@@ -50,12 +48,10 @@
public ActivityTestRule<FragmentTestActivity> mActivityRule =
new ActivityTestRule<FragmentTestActivity>(FragmentTestActivity.class);
- private Instrumentation mInstrumentation;
private PostponedFragment1 mBeginningFragment;
@Before
public void setupContainer() throws Throwable {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
FragmentTestUtil.setContentView(mActivityRule, R.layout.simple_container);
final FragmentManager fm = mActivityRule.getActivity().getFragmentManager();
mBeginningFragment = new PostponedFragment1();
@@ -119,7 +115,7 @@
final int commit[] = new int[1];
// Need to run this on the UI thread so that the transaction doesn't start
// between the two
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
commit[0] = fm.beginTransaction()
@@ -489,7 +485,7 @@
final TransitionFragment fragment4 = new PostponedFragment2();
final StrictFragment strictFragment2 = new StrictFragment();
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
fm.beginTransaction()
@@ -539,7 +535,7 @@
final View startBlue2 = fragment2.getView().findViewById(R.id.blueSquare);
- mInstrumentation.runOnMainSync(new Runnable() {
+ mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
fm.beginTransaction()
@@ -664,7 +660,7 @@
assertTrue(fragment2.isAdded());
assertTrue(fragment2.getView().isAttachedToWindow());
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
assertTrue(fm2.popBackStackImmediate());
});
diff --git a/tests/pdf/Android.mk b/tests/pdf/Android.mk
new file mode 100644
index 0000000..1e4a1ca
--- /dev/null
+++ b/tests/pdf/Android.mk
@@ -0,0 +1,44 @@
+# Copyright (C) 2017 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_MULTILIB := both
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES += \
+ android-support-test \
+ mockito-target-minus-junit4 \
+ compatibility-device-util \
+ ctstestrunner \
+ android-support-annotations \
+ junit \
+ legacy-android-test
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsPdfTestCases
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
+
diff --git a/tests/pdf/AndroidManifest.xml b/tests/pdf/AndroidManifest.xml
new file mode 100644
index 0000000..495b5da
--- /dev/null
+++ b/tests/pdf/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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="android.graphics.pdf.cts">
+
+ <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.graphics.pdf.cts"
+ android:label="CTS tests of android.graphics.pdf">
+ <meta-data android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+</manifest>
+
diff --git a/tests/pdf/AndroidTest.xml b/tests/pdf/AndroidTest.xml
new file mode 100644
index 0000000..e7c0794
--- /dev/null
+++ b/tests/pdf/AndroidTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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="Config for CTS Pdf test cases">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsPdfTestCases.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.graphics.pdf.cts" />
+ <option name="runtime-hint" value="5m" />
+ </test>
+</configuration>
diff --git a/tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf b/tests/pdf/res/raw/a4_portrait_rgbb.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a4_portrait_rgbb.pdf
rename to tests/pdf/res/raw/a4_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf b/tests/pdf/res/raw/a5_portrait_rgbb.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a5_portrait_rgbb.pdf
rename to tests/pdf/res/raw/a5_portrait_rgbb.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf b/tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
rename to tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_default.pdf
Binary files differ
diff --git a/tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf b/tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
rename to tests/pdf/res/raw/a5_portrait_rgbb_1_6_printscaling_none.pdf
Binary files differ
diff --git a/tests/pdf/res/raw/testimage.jpg b/tests/pdf/res/raw/testimage.jpg
new file mode 100644
index 0000000..d3dae03
--- /dev/null
+++ b/tests/pdf/res/raw/testimage.jpg
Binary files differ
diff --git a/tests/tests/graphics/res/raw/two_pages.pdf b/tests/pdf/res/raw/two_pages.pdf
similarity index 100%
rename from tests/tests/graphics/res/raw/two_pages.pdf
rename to tests/pdf/res/raw/two_pages.pdf
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfDocumentTest.java b/tests/pdf/src/android/graphics/pdf/cts/PdfDocumentTest.java
similarity index 100%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/PdfDocumentTest.java
rename to tests/pdf/src/android/graphics/pdf/cts/PdfDocumentTest.java
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java b/tests/pdf/src/android/graphics/pdf/cts/PdfRendererTest.java
similarity index 99%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
rename to tests/pdf/src/android/graphics/pdf/cts/PdfRendererTest.java
index 530ac1b..2f0158e 100644
--- a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTest.java
+++ b/tests/pdf/src/android/graphics/pdf/cts/PdfRendererTest.java
@@ -34,7 +34,7 @@
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Rect;
-import android.graphics.cts.R;
+import android.graphics.pdf.cts.R;
import android.graphics.pdf.PdfRenderer;
import android.graphics.pdf.PdfRenderer.Page;
import android.os.ParcelFileDescriptor;
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java b/tests/pdf/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
similarity index 100%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
rename to tests/pdf/src/android/graphics/pdf/cts/PdfRendererTransformTest.java
diff --git a/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java b/tests/pdf/src/android/graphics/pdf/cts/Utils.java
similarity index 98%
rename from tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
rename to tests/pdf/src/android/graphics/pdf/cts/Utils.java
index 2e2de3e..4d43e09 100644
--- a/tests/tests/graphics/src/android/graphics/pdf/cts/Utils.java
+++ b/tests/pdf/src/android/graphics/pdf/cts/Utils.java
@@ -53,8 +53,8 @@
static final int A4_WIDTH_PTS = 595;
static final int A4_HEIGHT_PTS = 841;
- static final int A4_PORTRAIT = android.graphics.cts.R.raw.a4_portrait_rgbb;
- static final int A5_PORTRAIT = android.graphics.cts.R.raw.a5_portrait_rgbb;
+ static final int A4_PORTRAIT = android.graphics.pdf.cts.R.raw.a4_portrait_rgbb;
+ static final int A5_PORTRAIT = android.graphics.pdf.cts.R.raw.a5_portrait_rgbb;
/**
* Create a {@link PdfRenderer} pointing to a file copied from a resource.
diff --git a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
index 547f44c..8866a39 100644
--- a/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
+++ b/tests/sensor/src/android/hardware/cts/SensorDirectReportTest.java
@@ -40,7 +40,6 @@
*
* This testcase tests operation of:
* - SensorManager.createDirectChannel()
- * - SensorManager.configureDirectReport()
* - SensorDirectChannel.*
* - Sensor.getHighestDirectReportRateLevel()
* - Sensor.isDirectChannelTypeSupported()
@@ -89,7 +88,7 @@
protected void setUp() throws Exception {
mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
- mNeedMemoryFile = isMemoryTypeNeeded(SensorDirectChannel.TYPE_ASHMEM);
+ mNeedMemoryFile = isMemoryTypeNeeded(SensorDirectChannel.TYPE_MEMORY_FILE);
mNeedHardwareBuffer = isMemoryTypeNeeded(SensorDirectChannel.TYPE_HARDWARE_BUFFER);
if (mNeedMemoryFile) {
@@ -129,28 +128,28 @@
public void testAccelerometerAshmemNormal() {
runSensorDirectReportTest(
Sensor.TYPE_ACCELEROMETER,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_NORMAL);
}
public void testGyroscopeAshmemNormal() {
runSensorDirectReportTest(
Sensor.TYPE_GYROSCOPE,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_NORMAL);
}
public void testMagneticFieldAshmemNormal() {
runSensorDirectReportTest(
Sensor.TYPE_MAGNETIC_FIELD,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_NORMAL);
}
public void testAccelerometerAshmemFast() {
runSensorDirectReportTest(
Sensor.TYPE_ACCELEROMETER,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_FAST);
}
@@ -158,21 +157,21 @@
public void testGyroscopeAshmemFast() {
runSensorDirectReportTest(
Sensor.TYPE_GYROSCOPE,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_FAST);
}
public void testMagneticFieldAshmemFast() {
runSensorDirectReportTest(
Sensor.TYPE_MAGNETIC_FIELD,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_FAST);
}
public void testAccelerometerAshmemVeryFast() {
runSensorDirectReportTest(
Sensor.TYPE_ACCELEROMETER,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_VERY_FAST);
}
@@ -180,14 +179,14 @@
public void testGyroscopeAshmemVeryFast() {
runSensorDirectReportTest(
Sensor.TYPE_GYROSCOPE,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_VERY_FAST);
}
public void testMagneticFieldAshmemVeryFast() {
runSensorDirectReportTest(
Sensor.TYPE_MAGNETIC_FIELD,
- SensorDirectChannel.TYPE_ASHMEM,
+ SensorDirectChannel.TYPE_MEMORY_FILE,
SensorDirectChannel.RATE_VERY_FAST);
}
@@ -263,39 +262,40 @@
return;
}
- mChannel = null;
try {
switch(memType) {
- case SensorDirectChannel.TYPE_ASHMEM:
+ case SensorDirectChannel.TYPE_MEMORY_FILE:
assertTrue("MemoryFile is null", mMemoryFile != null);
mChannel = mSensorManager.createDirectChannel(mMemoryFile);
- assertTrue("createDirectChannel(MemoryFile) failed", mChannel != null);
break;
case SensorDirectChannel.TYPE_HARDWARE_BUFFER:
assertTrue("HardwareBuffer is null", mHardwareBuffer != null);
mChannel = mSensorManager.createDirectChannel(mHardwareBuffer);
- assertTrue("createDirectChannel(HardwareBuffer) failed", mChannel != null);
break;
default:
Log.e(TAG, "Specified illegal memory type " + memType);
return;
}
+ } catch (IllegalStateException e) {
+ mChannel = null;
+ }
+ assertTrue("createDirectChannel failed", mChannel != null);
+
+ try {
assertTrue("Shared memory is not formatted", isSharedMemoryFormatted(memType));
waitBeforeStartSensor();
- int token = mSensorManager.configureDirectChannel(mChannel, s, rateLevel);
+ int token = mChannel.configure(s, rateLevel);
assertTrue("configure direct mChannel failed", token > 0);
waitSensorCollection();
//stop sensor and analyze content
- mSensorManager.configureDirectChannel(mChannel, s, SensorDirectChannel.RATE_STOP);
+ mChannel.configure(s, SensorDirectChannel.RATE_STOP);
checkSharedMemoryContent(s, memType, rateLevel, token);
} finally {
- if (mChannel != null) {
- mChannel.close();
- mChannel = null;
- }
+ mChannel.close();
+ mChannel = null;
}
}
@@ -348,7 +348,7 @@
}
private boolean isSharedMemoryFormatted(int memType) {
- if (memType == SensorDirectChannel.TYPE_ASHMEM) {
+ if (memType == SensorDirectChannel.TYPE_MEMORY_FILE) {
if (!readMemoryFileContent()) {
Log.e(TAG, "Read MemoryFile content fail");
return false;
@@ -369,7 +369,7 @@
}
private void checkSharedMemoryContent(Sensor s, int memType, int rateLevel, int token) {
- if (memType == SensorDirectChannel.TYPE_ASHMEM) {
+ if (memType == SensorDirectChannel.TYPE_MEMORY_FILE) {
assertTrue("read MemoryFile content failed", readMemoryFileContent());
} else {
assertTrue("read HardwareBuffer content failed", readHardwareBufferContent());
diff --git a/tests/signature/Android.mk b/tests/signature/Android.mk
index 6a8dcf9..8502c59 100644
--- a/tests/signature/Android.mk
+++ b/tests/signature/Android.mk
@@ -27,7 +27,9 @@
LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner \
+ compatibility-device-util \
+ android-support-test
include $(BUILD_CTS_PACKAGE)
diff --git a/tests/signature/AndroidManifest.xml b/tests/signature/AndroidManifest.xml
index 52090ce..41a4233 100644
--- a/tests/signature/AndroidManifest.xml
+++ b/tests/signature/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.signature.cts">
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application>
@@ -27,4 +28,4 @@
android:targetPackage="android.signature.cts"
android:label="API Signature Test"/>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/signature/AndroidTest.xml b/tests/signature/AndroidTest.xml
index 038d0d0..6d23620 100644
--- a/tests/signature/AndroidTest.xml
+++ b/tests/signature/AndroidTest.xml
@@ -14,6 +14,11 @@
limitations under the License.
-->
<configuration description="Config for CTS Signature test cases">
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
+ <option name="target" value="device" />
+ <option name="config-filename" value="CtsSignatureTestCases" />
+ <option name="version" value="1.0" />
+ </target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="mkdir -p /data/local/tmp/signature-test-packages" />
<option name='run-command'
diff --git a/tests/signature/DynamicConfig.xml b/tests/signature/DynamicConfig.xml
new file mode 100644
index 0000000..e078476
--- /dev/null
+++ b/tests/signature/DynamicConfig.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 Google Inc.
+
+ 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.
+-->
+<!--
+ Bug: 33305737 android.intent.action.ACTION_CARRIER_SETUP
+ Bug: 36980009 android.intent.action.QUICKBOOT_POWERON
+ Bug: 36977779 android.intent.action.MASTER_CLEAR
+-->
+<dynamicConfig>
+ <entry key ="intent_whitelist">
+ <value>android.intent.action.ACTION_CARRIER_SETUP</value>
+ <value>android.intent.action.QUICKBOOT_POWERON</value>
+ </entry>
+</dynamicConfig>
diff --git a/tests/signature/src/android/signature/cts/IntentTest.java b/tests/signature/src/android/signature/cts/IntentTest.java
index c0d3e84..3d674ab 100644
--- a/tests/signature/src/android/signature/cts/IntentTest.java
+++ b/tests/signature/src/android/signature/cts/IntentTest.java
@@ -57,6 +57,8 @@
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
+
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
@@ -90,19 +92,21 @@
new File("/data/local/tmp/signature-test-packages");
private static final String ANDROID_INTENT_PREFIX = "android.intent.action";
private static final String ACTION_LINE_PREFIX = " Action: ";
- private static final Set<String> INTENT_WHITELIST = getIntentWhitelist();
+ private static final String MODULE_NAME = "CtsSignatureTestCases";
private PackageManager mPackageManager;
+ private Set<String> intentWhitelist;
@Before
- public void setupPackageManager() {
+ public void setupPackageManager() throws Exception {
mPackageManager = InstrumentationRegistry.getContext().getPackageManager();
+ intentWhitelist = getIntentWhitelist();
}
@Test
public void shouldNotFindUnexpectedIntents() throws Exception {
Set<String> platformIntents = lookupPlatformIntents();
- platformIntents.addAll(INTENT_WHITELIST);
+ platformIntents.addAll(intentWhitelist);
Set<String> allInvalidIntents = new HashSet<>();
@@ -268,9 +272,18 @@
}
}
- private static Set<String> getIntentWhitelist() {
+ private static Set<String> getIntentWhitelist() throws Exception {
Set<String> whitelist = new HashSet<>();
+ DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(MODULE_NAME);
+ List<String> intentWhitelist = dcds.getValues("intent_whitelist");
+
+ // Log the whitelist Intent
+ for (String intent : intentWhitelist) {
+ Log.d(TAG, String.format("whitelist add: %s", intent));
+ whitelist.add(intent);
+ }
+
return whitelist;
}
}
diff --git a/tests/tests/bluetooth/Android.mk b/tests/tests/bluetooth/Android.mk
index d980e37..c02b23d 100644
--- a/tests/tests/bluetooth/Android.mk
+++ b/tests/tests/bluetooth/Android.mk
@@ -25,6 +25,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JAVA_LIBRARIES += android.test.runner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
index fd1c7d2..066de74 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
@@ -28,6 +28,7 @@
import android.content.pm.PackageManager;
import android.os.ParcelUuid;
import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
@@ -85,6 +86,9 @@
if (!mLocationOn) {
TestUtils.enableLocation(getContext());
}
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().executeShellCommand(
+ "pm grant android.bluetooth.cts android.permission.ACCESS_COARSE_LOCATION"
+ );
}
@Override
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index 0ceda3a..e5e8fe4 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -24,7 +24,6 @@
import android.content.res.AssetFileDescriptor;
import android.database.ContentObserver;
import android.database.Cursor;
-import android.database.PageViewCursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -35,6 +34,7 @@
import android.util.Log;
import com.android.compatibility.common.util.PollingCheck;
+import com.android.internal.util.ArrayUtils;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -419,41 +419,10 @@
}
/**
- * Verifies that paging arguments are handled correctly
- * when the provider supports paging.
+ * Verifies that paging information is correctly relayed, and that
+ * honored arguments from a supporting client are returned correctly.
*/
- public void testQuery_InProcessProvider_NoAutoPaging() {
-
- mContentResolver.delete(TABLE1_URI, null, null);
- ContentValues values = new ContentValues();
-
- for (int i = 0; i < 100; i++) {
- values.put(COLUMN_KEY_NAME, i);
- mContentResolver.insert(TABLE1_URI, values);
- }
-
- Bundle queryArgs = new Bundle();
- queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
- queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3);
-
- mCursor = mContentResolver.query(TABLE1_URI, null, queryArgs, null);
- int col = mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME);
-
- Bundle extras = mCursor.getExtras();
- extras = extras != null ? extras : Bundle.EMPTY;
-
- assertEquals(100, mCursor.getCount());
- assertFalse(extras.containsKey(PageViewCursor.EXTRA_AUTO_PAGED));
- assertFalse(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
-
- mCursor.close();
- }
-
- /**
- * Verifies that paging arguments are handled correctly
- * when the provider supports paging.
- */
- public void testQuery_OutOfProcessProvider_AutoPaging() {
+ public void testQuery_PagedResults() {
Bundle queryArgs = new Bundle();
queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
@@ -461,88 +430,30 @@
queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 100);
mCursor = mContentResolver.query(
- TestPagingContentProvider.UNPAGED_DATA_URI, null, queryArgs, null);
-
- Bundle extras = mCursor.getExtras();
- extras = extras != null ? extras : Bundle.EMPTY;
-
- assertEquals(3, mCursor.getCount());
- assertTrue(extras.getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
- assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
- assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
-
- int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS);
-
- mCursor.moveToNext();
- assertEquals(10, mCursor.getInt(col));
- mCursor.moveToNext();
- assertEquals(11, mCursor.getInt(col));
- mCursor.moveToNext();
- assertEquals(12, mCursor.getInt(col));
-
- assertFalse(mCursor.moveToNext());
-
- mCursor.close();
- }
-
- /**
- * Verifies that paging arguments are handled correctly
- * when the provider supports paging.
- */
- public void testQuery_OutOfProcessProvider_AutoPaging_OffsetOutOfBounds() {
-
- Bundle queryArgs = new Bundle();
- queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
- queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3);
- queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 100);
-
- mCursor = mContentResolver.query(
- TestPagingContentProvider.UNPAGED_DATA_URI, null, queryArgs, null);
-
- Bundle extras = mCursor.getExtras();
- extras = extras != null ? extras : Bundle.EMPTY;
-
- assertEquals(3, mCursor.getCount());
- assertTrue(extras.getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
- assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
- assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
-
- int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS);
-
- mCursor.moveToNext();
- assertEquals(10, mCursor.getInt(col));
- mCursor.moveToNext();
- assertEquals(11, mCursor.getInt(col));
- mCursor.moveToNext();
- assertEquals(12, mCursor.getInt(col));
-
- assertFalse(mCursor.moveToNext());
-
- mCursor.close();
- }
-
- /**
- * Verifies that auto-paging isn't applied when the underlying remote
- * provider has already applied paging.
- */
- public void testQuery_OutOfProcessProvider_NoAutoPagingForAlreadyPagedResults() {
-
- Bundle queryArgs = new Bundle();
- queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 20);
- queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 2);
- queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 500);
-
- mCursor = mContentResolver.query(
TestPagingContentProvider.PAGED_DATA_URI, null, queryArgs, null);
Bundle extras = mCursor.getExtras();
extras = extras != null ? extras : Bundle.EMPTY;
- assertFalse(extras.getBoolean(PageViewCursor.EXTRA_AUTO_PAGED));
+ assertEquals(3, mCursor.getCount());
+ assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
+ assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
- // we don't test the contents of the self-paged cursor
- // because that's provided by TestPagingContentProvider
- // a test-only test support class.
+ String[] honoredArgs = extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
+ assertNotNull(honoredArgs);
+ assertTrue(ArrayUtils.contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET));
+ assertTrue(ArrayUtils.contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT));
+
+ int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS);
+
+ mCursor.moveToNext();
+ assertEquals(10, mCursor.getInt(col));
+ mCursor.moveToNext();
+ assertEquals(11, mCursor.getInt(col));
+ mCursor.moveToNext();
+ assertEquals(12, mCursor.getInt(col));
+
+ assertFalse(mCursor.moveToNext());
mCursor.close();
}
diff --git a/tests/tests/dpi/AndroidManifest.xml b/tests/tests/dpi/AndroidManifest.xml
index 118050e..8b02670 100644
--- a/tests/tests/dpi/AndroidManifest.xml
+++ b/tests/tests/dpi/AndroidManifest.xml
@@ -18,6 +18,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.dpi.cts">
+ <uses-sdk
+ android:minSdkVersion="23"
+ android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/tests/tests/graphics/assets/red-adobergb.png b/tests/tests/graphics/assets/red-adobergb.png
new file mode 100644
index 0000000..adbff91
--- /dev/null
+++ b/tests/tests/graphics/assets/red-adobergb.png
Binary files differ
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
index 5012e1c..8fc7a3b 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
@@ -38,6 +38,7 @@
import java.util.Arrays;
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;
@@ -520,6 +521,22 @@
}
@Test
+ public void guessAdobeRGB() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inJustDecodeBounds = true;
+
+ try (InputStream in = mResources.getAssets().open("red-adobergb.png")) {
+ Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+ ColorSpace cs = opts.outColorSpace;
+ assertNull(b);
+ assertNotNull(cs);
+ assertSame(ColorSpace.get(ColorSpace.Named.ADOBE_RGB), cs);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test
public void guessUnknown() {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
@@ -552,6 +569,99 @@
}
@Test
+ public void inColorSpaceP3ToSRGB() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+
+ try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+ Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+ ColorSpace cs = b.getColorSpace();
+ assertNotNull(cs);
+ assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs);
+ assertEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+
+ verifyGetPixel(b, 0x3ff00ff, 0xff00ff00);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void inColorSpaceSRGBToP3() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+
+ try (InputStream in = mResources.getAssets().open("green-srgb.png")) {
+ Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+ ColorSpace cs = b.getColorSpace();
+ assertNotNull(cs);
+ assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), cs);
+ assertEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+
+ verifyGetPixel(b, 0x75fb4cff, 0xff00ff00);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void inColorSpaceRGBA16F() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+
+ try (InputStream in = mResources.getAssets().open("prophoto-rgba16f.png")) {
+ Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+ ColorSpace cs = b.getColorSpace();
+ assertNotNull(cs);
+ assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), cs);
+ assertNotEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void inColorSpace565() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+ opts.inPreferredConfig = Bitmap.Config.RGB_565;
+
+ try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+ Bitmap b = BitmapFactory.decodeStream(in, null, opts);
+ ColorSpace cs = b.getColorSpace();
+ assertNotNull(cs);
+ assertSame(ColorSpace.get(ColorSpace.Named.SRGB), cs);
+ assertNotEquals(opts.inPreferredColorSpace, opts.outColorSpace);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void inColorSpaceNotRGB() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.CIE_LAB);
+
+ try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+ BitmapFactory.decodeStream(in, null, opts);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void inColorSpaceNoTransferParameters() {
+ BitmapFactory.Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
+
+ try (InputStream in = mResources.getAssets().open("green-p3.png")) {
+ BitmapFactory.decodeStream(in, null, opts);
+ } catch (IOException e) {
+ fail();
+ }
+ }
+
+ @Test
public void copy() {
Bitmap b = BitmapFactory.decodeResource(mResources, R.drawable.robot);
Bitmap c = b.copy(Bitmap.Config.ARGB_8888, false);
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
index 04b4aba..aea201c 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapRegionDecoderTest.java
@@ -31,9 +31,11 @@
import android.graphics.BitmapRegionDecoder;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.ColorSpace;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -63,9 +65,33 @@
R.drawable.gif_test, R.drawable.bmp_test
};
private static final String[] NAMES_TEMP_FILES = new String[] {
- "baseline_temp.jpg", "progressive_temp.jpg", "baseline_restart_temp.jpg",
- "progressive_restart_temp.jpg", "png_temp.png", "webp_temp.webp",
- "gif_temp.gif", "bmp_temp.bmp"
+ "baseline_temp.jpg", "progressive_temp.jpg", "baseline_restart_temp.jpg",
+ "progressive_restart_temp.jpg", "png_temp.png", "webp_temp.webp",
+ "gif_temp.gif", "bmp_temp.bmp"
+ };
+
+ // Do not change the order!
+ private static final String[] ASSET_NAMES = {
+ "prophoto-rgba16f.png",
+ "green-p3.png",
+ "red-adobergb.png",
+ "green-srgb.png",
+ };
+ private static final ColorSpace.Named[][] ASSET_COLOR_SPACES = {
+ // ARGB8888
+ {
+ ColorSpace.Named.LINEAR_EXTENDED_SRGB,
+ ColorSpace.Named.DISPLAY_P3,
+ ColorSpace.Named.ADOBE_RGB,
+ ColorSpace.Named.SRGB
+ },
+ // RGB565
+ {
+ ColorSpace.Named.SRGB,
+ ColorSpace.Named.SRGB,
+ ColorSpace.Named.SRGB,
+ ColorSpace.Named.SRGB
+ }
};
// The width and height of the above image.
@@ -78,6 +104,7 @@
private static final int NUM_TEST_IMAGES = 6;
private static final int TILE_SIZE = 256;
+ private static final int SMALL_TILE_SIZE = 16;
// Configurations for BitmapFactory.Options
private static final Config[] COLOR_CONFIGS = new Config[] {Config.ARGB_8888,
@@ -171,6 +198,7 @@
}
}
+ @LargeTest
@Test
public void testDecodeRegionInputStream() throws IOException {
Options opts = new BitmapFactory.Options();
@@ -197,6 +225,7 @@
}
}
+ @LargeTest
@Test
public void testDecodeRegionInputStreamInBitmap() throws IOException {
Options opts = new BitmapFactory.Options();
@@ -228,6 +257,7 @@
}
}
+ @LargeTest
@Test
public void testDecodeRegionByteArray() throws IOException {
Options opts = new BitmapFactory.Options();
@@ -255,6 +285,7 @@
}
}
+ @LargeTest
@Test
public void testDecodeRegionStringAndFileDescriptor() throws IOException {
Options opts = new BitmapFactory.Options();
@@ -327,6 +358,7 @@
// (2) The width, height, and Config of inBitmap are never changed.
// (3) All of the pixels decoded into inBitmap exactly match the pixels
// of a decode where inBitmap is NULL.
+ @LargeTest
@Test
public void testInBitmapReuse() throws IOException {
Options defaultOpts = new BitmapFactory.Options();
@@ -409,6 +441,145 @@
assertEquals(Config.HARDWARE, hardwareBitmap.getConfig());
}
+ @Test
+ public void testOutColorType() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
+ for (int j = 0; j < SAMPLESIZES.length; ++j) {
+ for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
+ opts.inSampleSize = SAMPLESIZES[j];
+ opts.inPreferredConfig = COLOR_CONFIGS[k];
+
+ InputStream is1 = obtainInputStream(RES_IDS[i]);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(
+ new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+ decoder.recycle();
+
+ assertSame(opts.inPreferredConfig, opts.outConfig);
+ assertSame(opts.outConfig, region.getConfig());
+ region.recycle();
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testOutColorSpace() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ for (int i = 0; i < ASSET_NAMES.length; i++) {
+ for (int j = 0; j < SAMPLESIZES.length; ++j) {
+ for (int k = 0; k < COLOR_CONFIGS.length; ++k) {
+ opts.inPreferredConfig = COLOR_CONFIGS[k];
+
+ String assetName = ASSET_NAMES[i];
+ InputStream is1 = obtainInputStream(assetName);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(
+ new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+ decoder.recycle();
+
+ ColorSpace expected = ColorSpace.get(ASSET_COLOR_SPACES[k][i]);
+ assertSame(expected, opts.outColorSpace);
+ assertSame(expected, region.getColorSpace());
+ region.recycle();
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testReusedColorSpace() throws IOException {
+ Bitmap b = Bitmap.createBitmap(SMALL_TILE_SIZE, SMALL_TILE_SIZE, Config.ARGB_8888,
+ false, ColorSpace.get(ColorSpace.Named.ADOBE_RGB));
+
+ Options opts = new BitmapFactory.Options();
+ opts.inBitmap = b;
+
+ // sRGB
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
+ obtainInputStream(ASSET_NAMES[3]), false);
+ Bitmap region = decoder.decodeRegion(
+ new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+ decoder.recycle();
+
+ assertEquals(ColorSpace.get(ColorSpace.Named.SRGB), region.getColorSpace());
+
+ // DisplayP3
+ decoder = BitmapRegionDecoder.newInstance(obtainInputStream(ASSET_NAMES[1]), false);
+ region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+ decoder.recycle();
+
+ assertEquals(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), region.getColorSpace());
+ }
+
+ @Test
+ public void testInColorSpace() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ for (int i = 0; i < NUM_TEST_IMAGES; ++i) {
+ for (int j = 0; j < SAMPLESIZES.length; ++j) {
+ opts.inSampleSize = SAMPLESIZES[j];
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+
+ InputStream is1 = obtainInputStream(RES_IDS[i]);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+ decoder.recycle();
+
+ assertSame(ColorSpace.get(ColorSpace.Named.DISPLAY_P3), opts.outColorSpace);
+ assertSame(opts.outColorSpace, region.getColorSpace());
+ region.recycle();
+ }
+ }
+ }
+
+ @Test
+ public void testInColorSpaceRGBA16F() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+
+ InputStream is1 = obtainInputStream(ASSET_NAMES[0]); // ProPhoto 16 bit
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+ decoder.recycle();
+
+ assertSame(ColorSpace.get(ColorSpace.Named.LINEAR_EXTENDED_SRGB), region.getColorSpace());
+ region.recycle();
+ }
+
+ @Test
+ public void testInColorSpace565() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ opts.inPreferredConfig = Config.RGB_565;
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.ADOBE_RGB);
+
+ InputStream is1 = obtainInputStream(ASSET_NAMES[1]); // Display P3
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(new Rect(0, 0, SMALL_TILE_SIZE, SMALL_TILE_SIZE), opts);
+ decoder.recycle();
+
+ assertSame(ColorSpace.get(ColorSpace.Named.SRGB), region.getColorSpace());
+ region.recycle();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInColorSpaceNotRgb() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.CIE_LAB);
+ InputStream is1 = obtainInputStream(RES_IDS[0]);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInColorSpaceNoTransferParameters() throws IOException {
+ Options opts = new BitmapFactory.Options();
+ opts.inPreferredColorSpace = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
+ InputStream is1 = obtainInputStream(RES_IDS[0]);
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is1, false);
+ Bitmap region = decoder.decodeRegion(new Rect(0, 0, TILE_SIZE, TILE_SIZE), opts);
+ }
+
private void compareRegionByRegion(BitmapRegionDecoder decoder,
Options opts, int mseMargin, Bitmap wholeImage) {
int width = decoder.getWidth();
@@ -459,6 +630,10 @@
return mRes.openRawResource(resId);
}
+ private InputStream obtainInputStream(String assetName) throws IOException {
+ return mRes.getAssets().open(assetName);
+ }
+
private byte[] obtainByteArray(int resId) throws IOException {
InputStream is = obtainInputStream(resId);
ByteArrayOutputStream os = new ByteArrayOutputStream();
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java
index 1cc81bf..0b4f29f 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapShaderTest.java
@@ -161,35 +161,4 @@
Assert.assertArrayEquals(new int[] { Color.RED, Color.BLUE, Color.BLUE, Color.RED },
pixels);
}
-
- @Test
- public void testSetTileMode() {
- Bitmap bitmap = Bitmap.createBitmap(2, 1, Config.ARGB_8888);
- bitmap.setPixel(0, 0, Color.RED);
- bitmap.setPixel(1, 0, Color.BLUE);
- Bitmap dstBitmap = Bitmap.createBitmap(4, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(dstBitmap);
- Paint paint = new Paint();
- int[] pixels = new int[4];
-
-
- // use clamp, verify
- BitmapShader shader = new BitmapShader(bitmap,
- Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
- paint.setShader(shader);
- canvas.drawRect(0, 0, 4, 1, paint);
-
- dstBitmap.getPixels(pixels, 0, 4, 0, 0, 4, 1);
- Assert.assertArrayEquals(new int[] { Color.RED, Color.BLUE, Color.BLUE, Color.BLUE },
- pixels);
-
- // set to use mirror, verify
- // Note: we don't need to re-apply shader on paint, it's picked up automatically.
- shader.set(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
- canvas.drawRect(0, 0, 4, 1, paint);
-
- dstBitmap.getPixels(pixels, 0, 4, 0, 0, 4, 1);
- Assert.assertArrayEquals(new int[] { Color.RED, Color.BLUE, Color.BLUE, Color.RED },
- pixels);
- }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
index 69dbcd8..a113afa 100644
--- a/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/CanvasTest.java
@@ -1112,6 +1112,19 @@
}
@Test
+ public void testClipInversePath() {
+ final Path p = new Path();
+ p.addRoundRect(new RectF(0, 0, 10, 10), 0.5f, 0.5f, Direction.CW);
+ p.setFillType(Path.FillType.INVERSE_WINDING);
+ assertTrue(mCanvas.clipPath(p, Op.INTERSECT));
+
+ mCanvas.drawColor(PAINT_COLOR);
+
+ assertEquals(Color.TRANSPARENT, mMutableBitmap.getPixel(0, 0));
+ assertEquals(PAINT_COLOR, mMutableBitmap.getPixel(0, 20));
+ }
+
+ @Test
public void testGetDrawFilter() {
assertNull(mCanvas.getDrawFilter());
final DrawFilter dF = new DrawFilter();
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
index f8714ee..61d46b2 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
@@ -15,7 +15,6 @@
*/
package android.graphics.cts;
-import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import android.graphics.Bitmap;
@@ -98,55 +97,5 @@
canvas.drawPoint(0, 0, paint);
ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(0, 0));
}
-
- @Test
- public void testGetSetMatrix() {
- ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix());
- ColorMatrix getMatrix = new ColorMatrix();
- filter.getColorMatrix(getMatrix);
- assertEquals(new ColorMatrix(), getMatrix);
-
- ColorMatrix scaleTranslate = new ColorMatrix(new float[] {
- 2, 0, 0, 0, 5,
- 0, 2, 0, 0, 5,
- 0, 0, 2, 0, 5,
- 0, 0, 0, 2, 5
- });
-
- filter.setColorMatrix(scaleTranslate);
-
- filter.getColorMatrix(getMatrix);
- assertEquals(scaleTranslate, getMatrix);
- assertArrayEquals(scaleTranslate.getArray(), getMatrix.getArray(), 0);
-
- filter.setColorMatrixArray(null);
- filter.getColorMatrix(getMatrix);
- assertEquals(new ColorMatrix(), getMatrix);
- }
-
- @Test
- public void testSetMatrixDraw() {
- ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix(new float[] {
- 2, 0, 0, 0, 5,
- 0, 2, 0, 0, 5,
- 0, 0, 2, 0, 5,
- 0, 0, 0, 1, 0
- }));
-
- Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Paint paint = new Paint();
- paint.setColorFilter(filter);
-
-
- paint.setColor(0xFF101010);
- canvas.drawPaint(paint);
- ColorUtils.verifyColor(0xFF252525, bitmap.getPixel(0, 0));
-
-
- filter.setColorMatrix(null);
- canvas.drawPaint(paint);
- ColorUtils.verifyColor(0xFF101010, bitmap.getPixel(0, 0));
- }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java b/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
index 2e76b85..f7893c7 100644
--- a/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/Color_ColorLongTest.java
@@ -84,6 +84,11 @@
assertEquals(p3, colorSpace(pack(0.5f, 0.7f, 1.0f, 1.0f, p3)));
}
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidColorSpace() {
+ colorSpace(0xffffffffffffffffL);
+ }
+
@Test
public void testIsSrgb() {
ColorSpace p3 = ColorSpace.get(Named.DISPLAY_P3);
diff --git a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
index 2a83f32..8c8911e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ComposeShaderTest.java
@@ -101,72 +101,6 @@
}
@Test
- public void testSet() {
- Bitmap redBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- redBitmap.eraseColor(Color.RED);
- Bitmap cyanBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- cyanBitmap.eraseColor(Color.CYAN);
-
- BitmapShader redShader = new BitmapShader(redBitmap, TileMode.CLAMP, TileMode.CLAMP);
- BitmapShader cyanShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
-
- PorterDuffXfermode xferMode = new PorterDuffXfermode(PorterDuff.Mode.ADD);
-
- ComposeShader shader = new ComposeShader(redShader, cyanShader, xferMode);
-
- Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Paint paint = new Paint();
- paint.setShader(shader);
- canvas.drawPaint(paint);
-
- // red + cyan = white
- assertEquals(Color.WHITE, bitmap.getPixel(0, 0));
-
- // set to be multiply mode, and immediately redraw
- shader.set(redShader, cyanShader, PorterDuff.Mode.MULTIPLY);
- canvas.drawPaint(paint);
-
- // red * cyan = black
- assertEquals(Color.BLACK, bitmap.getPixel(0, 0));
- }
-
- @Test
- public void testInnerShaderMutate() {
- // verify that calling a setter on a child shader updates this shader
- Bitmap redBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- redBitmap.eraseColor(Color.RED);
- Bitmap cyanBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- cyanBitmap.eraseColor(Color.CYAN);
- Bitmap greenBitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- greenBitmap.eraseColor(Color.GREEN);
-
- BitmapShader redShader = new BitmapShader(redBitmap, TileMode.CLAMP, TileMode.CLAMP);
- BitmapShader cyanShader = new BitmapShader(cyanBitmap, TileMode.CLAMP, TileMode.CLAMP);
-
- ComposeShader shader = new ComposeShader(redShader, cyanShader, PorterDuff.Mode.ADD);
-
-
- Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Paint paint = new Paint();
- paint.setShader(shader);
- canvas.drawPaint(paint);
-
- // red + cyan = white
- assertEquals(Color.WHITE, bitmap.getPixel(0, 0));
-
- // update one of the child shaders to point at a different bitmap
- cyanShader.set(greenBitmap, TileMode.CLAMP, TileMode.CLAMP);
-
- // and verify the change is picked up immediately by next paint
- canvas.drawPaint(paint);
-
- // red + green = yellow
- assertEquals(Color.YELLOW, bitmap.getPixel(0, 0));
- }
-
- @Test
public void testChildLocalMatrix() {
Matrix translate1x1 = new Matrix();
translate1x1.setTranslate(1, 1);
diff --git a/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java b/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java
index 929cd96..8aeefba 100644
--- a/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/FontVariationAxisTest.java
@@ -37,19 +37,18 @@
@Test
public void testConstruction() throws FontVariationAxis.InvalidFormatException {
- new FontVariationAxis("abcd", 1.0f);
- new FontVariationAxis(" ", 0.0f);
- new FontVariationAxis("A X ", -1.0f);
+ new FontVariationAxis("wght", 1.0f);
+ new FontVariationAxis("PRIV", -1.0f);
}
@Test
public void testGetterTest() throws FontVariationAxis.InvalidFormatException {
- FontVariationAxis axis = new FontVariationAxis("abcd", 1.0f);
- assertEquals("abcd", axis.getTag());
+ FontVariationAxis axis = new FontVariationAxis("wght", 1.0f);
+ assertEquals("wght", axis.getTag());
assertEquals(1.0f, axis.getStyleValue(), FLOT_EQUALITY_PREC);
- axis = new FontVariationAxis(" ", -1.0f);
- assertEquals(" ", axis.getTag());
+ axis = new FontVariationAxis("PRIV", -1.0f);
+ assertEquals("PRIV", axis.getTag());
assertEquals(-1.0f, axis.getStyleValue(), FLOT_EQUALITY_PREC);
}
@@ -94,36 +93,36 @@
assertEquals("wdth", axes[0].getTag());
assertEquals(0.5f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- axes = FontVariationAxis.fromFontVariationSettings("'AX ' 1");
+ axes = FontVariationAxis.fromFontVariationSettings("'PRIV' 1");
assertEquals(1, axes.length);
- assertEquals("AX ", axes[0].getTag());
+ assertEquals("PRIV", axes[0].getTag());
assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- axes = FontVariationAxis.fromFontVariationSettings("'AX '\t1");
+ axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\t1");
assertEquals(1, axes.length);
- assertEquals("AX ", axes[0].getTag());
+ assertEquals("PRIV", axes[0].getTag());
assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- axes = FontVariationAxis.fromFontVariationSettings("'AX '\n1");
+ axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\n1");
assertEquals(1, axes.length);
- assertEquals("AX ", axes[0].getTag());
+ assertEquals("PRIV", axes[0].getTag());
assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- axes = FontVariationAxis.fromFontVariationSettings("'AX '\r1");
+ axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\r1");
assertEquals(1, axes.length);
- assertEquals("AX ", axes[0].getTag());
+ assertEquals("PRIV", axes[0].getTag());
assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- axes = FontVariationAxis.fromFontVariationSettings("'AX '\r\t\n 1");
+ axes = FontVariationAxis.fromFontVariationSettings("'PRIV'\r\t\n 1");
assertEquals(1, axes.length);
- assertEquals("AX ", axes[0].getTag());
+ assertEquals("PRIV", axes[0].getTag());
assertEquals(1.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- axes = FontVariationAxis.fromFontVariationSettings("'wdth' 10,'AX '\r1");
+ axes = FontVariationAxis.fromFontVariationSettings("'wdth' 10,'PRIV'\r1");
assertEquals(2, axes.length);
assertEquals("wdth", axes[0].getTag());
assertEquals(10.0f, axes[0].getStyleValue(), FLOT_EQUALITY_PREC);
- assertEquals("AX ", axes[1].getTag());
+ assertEquals("PRIV", axes[1].getTag());
assertEquals(1.0f, axes[1].getStyleValue(), FLOT_EQUALITY_PREC);
}
@@ -155,8 +154,7 @@
final FontVariationAxis[] axes = {
new FontVariationAxis("wght", 1.0f),
- new FontVariationAxis(" ", 2.0f),
- new FontVariationAxis("AX ", 3.0f)
+ new FontVariationAxis("PRIV", 3.0f)
};
String stringData = FontVariationAxis.toFontVariationSettings(axes);
diff --git a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
index e4ba072..da2b934 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
@@ -16,8 +16,6 @@
package android.graphics.cts;
-import static org.junit.Assert.assertEquals;
-
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
@@ -91,51 +89,4 @@
private void verifyColor(int expected, int actual) {
ColorUtils.verifyColor(expected, actual, TOLERANCE);
}
-
- @Test
- public void testGetSet() {
- LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
- assertEquals(Color.WHITE, filter.getColorMultiply());
- assertEquals(Color.BLACK, filter.getColorAdd());
-
- filter.setColorMultiply(Color.RED);
- filter.setColorAdd(Color.BLUE);
-
- assertEquals(Color.RED, filter.getColorMultiply());
- assertEquals(Color.BLUE, filter.getColorAdd());
- }
-
- @Test
- public void testSetDraw() {
- LightingColorFilter filter = new LightingColorFilter(Color.CYAN, Color.BLACK);
-
- Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Paint paint = new Paint();
- paint.setColorFilter(filter);
-
- // test initial state
- paint.setColor(Color.YELLOW);
- canvas.drawPaint(paint);
- // Cyan * yellow = green
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0));
-
-
- // test set color multiply
- filter.setColorMultiply(Color.MAGENTA);
- paint.setColor(Color.YELLOW);
- canvas.drawPaint(paint);
- // Magenta * yellow = red
- ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0));
-
-
- // test set color add
- filter.setColorMultiply(Color.WHITE);
- filter.setColorAdd(Color.MAGENTA);
- paint.setColor(Color.GREEN);
- canvas.drawPaint(paint);
- // Magenta + green = white
- ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(0, 0));
-
- }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
index 8555193..185e6a1 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LinearGradientTest.java
@@ -84,35 +84,6 @@
}
@Test
- public void testSet() {
- // only using 2 pixel wide gradient since we don't care about interpolation here.
- // Note: we align start/end to be center pixel so colors at those pixels are exact.
- LinearGradient gradient = new LinearGradient(0.5f, 0, 1.5f, 0,
- Color.RED, Color.BLUE, TileMode.CLAMP);
-
- Bitmap bitmap = Bitmap.createBitmap(3, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
-
- Paint paint = new Paint();
- paint.setShader(gradient);
- canvas.drawPaint(paint);
-
-
- // red, blue, clamped to blue
- ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0), 5);
- ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(1, 0), 5);
- ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(2, 0), 5);
-
- gradient.set(0.5f, 0, 1.5f, 0, Color.GREEN, Color.WHITE, TileMode.MIRROR);
- canvas.drawPaint(paint);
-
- // green, white, mirrored to green
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0), 5);
- ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(1, 0), 5);
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(2, 0), 5);
- }
-
- @Test
public void testZeroScaleMatrix() {
LinearGradient gradient = new LinearGradient(0.5f, 0, 1.5f, 0,
Color.RED, Color.BLUE, TileMode.CLAMP);
diff --git a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
index f5c7aa3..22fa7c3 100644
--- a/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/MovieTest.java
@@ -28,7 +28,7 @@
import android.graphics.Movie;
import android.graphics.Paint;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.WidgetTestUtils;
@@ -44,7 +44,7 @@
import java.io.InputStream;
import java.io.OutputStream;
-@MediumTest
+@SmallTest
@RunWith(AndroidJUnit4.class)
public class MovieTest {
private final int MOVIE = R.drawable.animated;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
index a2438ee..0beadae 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PorterDuffColorFilterTest.java
@@ -27,8 +27,6 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
-import com.android.compatibility.common.util.ColorUtils;
-
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -83,52 +81,4 @@
assertEquals(Color.CYAN, target.getPixel(width / 4, height * 3 / 4));
assertEquals(Color.CYAN, target.getPixel(width * 3 / 4, height * 3 / 4));
}
-
- @Test
- public void testGetSet() {
- PorterDuffColorFilter filter = new PorterDuffColorFilter(
- Color.RED, PorterDuff.Mode.MULTIPLY);
-
- assertEquals(Color.RED, filter.getColor());
- assertEquals(PorterDuff.Mode.MULTIPLY, filter.getMode());
-
- filter.setColor(Color.GREEN);
- filter.setMode(PorterDuff.Mode.ADD);
-
- assertEquals(Color.GREEN, filter.getColor());
- assertEquals(PorterDuff.Mode.ADD, filter.getMode());
- }
-
- @Test
- public void testSetDraw() {
- PorterDuffColorFilter filter = new PorterDuffColorFilter(
- Color.CYAN, PorterDuff.Mode.MULTIPLY);
-
- Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Paint paint = new Paint();
- paint.setColorFilter(filter);
-
- // test initial state
- paint.setColor(Color.YELLOW);
- canvas.drawPaint(paint);
- // Cyan * yellow = green
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0));
-
-
- // test set color
- filter.setColor(Color.MAGENTA);
- paint.setColor(Color.YELLOW);
- canvas.drawPaint(paint);
- // Magenta * yellow = red
- ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0));
-
-
- // test set mode
- filter.setMode(PorterDuff.Mode.ADD);
- paint.setColor(Color.GREEN);
- canvas.drawPaint(paint);
- // Magenta + green = white
- ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(0, 0));
- }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java
index e8a0cbc..d133bb9 100644
--- a/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/RadialGradientTest.java
@@ -35,34 +35,6 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RadialGradientTest {
- @Test
- public void testSet() {
- // only using 1 pixel radius gradient since we don't care about interpolation here.
- // Note: we align start/end to be center pixel so colors at those pixels are exact.
- RadialGradient gradient = new RadialGradient(0.5f, 0.5f, 1,
- Color.RED, Color.BLUE, TileMode.CLAMP);
-
- Bitmap bitmap = Bitmap.createBitmap(3, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
-
- Paint paint = new Paint();
- paint.setShader(gradient);
- canvas.drawPaint(paint);
-
-
- // red, blue, clamped to blue
- ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0), 5);
- ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(1, 0), 5);
- ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(2, 0), 5);
-
- gradient.set(0.5f, 0.5f, 1, Color.GREEN, Color.WHITE, TileMode.MIRROR);
- canvas.drawPaint(paint);
-
- // green, white, mirrored to green
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(0, 0), 5);
- ColorUtils.verifyColor(Color.WHITE, bitmap.getPixel(1, 0), 5);
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(2, 0), 5);
- }
@Test
public void testZeroScaleMatrix() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java b/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java
index ceea7a7..cb7ec0a 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SweepGradientTest.java
@@ -22,7 +22,6 @@
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -148,33 +147,6 @@
}
@Test
- public void testSet() {
- // Only use two pixel wide bitmap since we don't care about interpolation here.
- // Note: we place the gradient in between the two pixels, so both are solid colors.
- SweepGradient gradient = new SweepGradient(1, 0.5f,
- new int[] {Color.BLUE, Color.RED, Color.BLUE}, null);
-
- Bitmap bitmap = Bitmap.createBitmap(2, 1, Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
-
- Paint paint = new Paint();
- paint.setShader(gradient);
- canvas.drawPaint(paint);
-
- // red to left, blue to right
- ColorUtils.verifyColor(Color.RED, bitmap.getPixel(0, 0), 5);
- ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(1, 0), 5);
-
- gradient.set(1, 0.5f,
- new int[] {Color.GREEN, Color.YELLOW, Color.GREEN}, null);
- canvas.drawPaint(paint);
-
- // yellow to left, green to right
- ColorUtils.verifyColor(Color.YELLOW, bitmap.getPixel(0, 0), 5);
- ColorUtils.verifyColor(Color.GREEN, bitmap.getPixel(1, 0), 5);
- }
-
- @Test
public void testZeroScaleMatrix() {
SweepGradient gradient = new SweepGradient(1, 0.5f,
new int[] {Color.BLUE, Color.RED, Color.BLUE}, null);
diff --git a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
index b0adf26..3a1c1cf 100644
--- a/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/TypefaceTest.java
@@ -21,11 +21,13 @@
import static org.junit.Assert.assertNotEquals;
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 static org.junit.Assert.fail;
import android.content.Context;
+import android.content.res.AssetManager;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.fonts.FontVariationAxis;
@@ -357,6 +359,88 @@
}
@Test
+ public void testTypefaceBuilder_fallback() throws IOException {
+ final File validFile = new File(obtainPath());
+ final File invalidFile = new File("/some/invalid/path/to/font/file");
+ final AssetManager assets = mContext.getAssets();
+ // By default, returns null if no fallback font is specified.
+ assertNull(new Typeface.Builder(invalidFile).build());
+
+ assertNull(new Typeface.Builder(validFile)
+ .setTtcIndex(100 /* non-existing ttc index */).build());
+
+ assertNull(new Typeface.Builder(assets, "invalid path").build());
+
+ assertNull(new Typeface.Builder(assets, "samplefont.ttf")
+ .setTtcIndex(100 /* non-existing ttc index */).build());
+
+ // If fallback is set, the builder never returns null.
+ assertNotNull(new Typeface.Builder(invalidFile).setFallback("").build());
+
+ assertNotNull(new Typeface.Builder(invalidFile).setFallback("invalid name").build());
+
+ Typeface sansSerifTypeface = new Typeface.Builder(invalidFile)
+ .setFallback("sans-serif").build();
+ assertNotNull(sansSerifTypeface);
+
+ Typeface serifTypeface = new Typeface.Builder(invalidFile).setFallback("serif").build();
+ assertNotNull(serifTypeface);
+
+ Typeface boldSansSerifTypeface = new Typeface.Builder(invalidFile)
+ .setFallback("sans-serif").setWeight(700).build();
+ assertNotNull(boldSansSerifTypeface);
+
+ Typeface boldSerifTypeface = new Typeface.Builder(invalidFile)
+ .setFallback("serif").setWeight(700).build();
+ assertNotNull(boldSerifTypeface);
+
+ Typeface italicSansSerifTypeface = new Typeface.Builder(invalidFile)
+ .setFallback("sans-serif").setItalic(true).build();
+ assertNotNull(italicSansSerifTypeface);
+
+ Typeface italicSerifTypeface = new Typeface.Builder(invalidFile)
+ .setFallback("serif").setItalic(true).build();
+ assertNotNull(italicSerifTypeface);
+
+ // All fallbacks should be different each other.
+ assertNotSame(sansSerifTypeface, serifTypeface);
+ assertNotSame(sansSerifTypeface, boldSansSerifTypeface);
+ assertNotSame(sansSerifTypeface, boldSerifTypeface);
+ assertNotSame(sansSerifTypeface, italicSansSerifTypeface);
+ assertNotSame(sansSerifTypeface, italicSerifTypeface);
+ assertNotSame(serifTypeface, boldSansSerifTypeface);
+ assertNotSame(serifTypeface, boldSerifTypeface);
+ assertNotSame(serifTypeface, italicSansSerifTypeface);
+ assertNotSame(serifTypeface, italicSerifTypeface);
+ assertNotSame(boldSansSerifTypeface, boldSerifTypeface);
+ assertNotSame(boldSansSerifTypeface, italicSansSerifTypeface);
+ assertNotSame(boldSansSerifTypeface, italicSerifTypeface);
+ assertNotSame(boldSerifTypeface, italicSansSerifTypeface);
+ assertNotSame(boldSerifTypeface, italicSerifTypeface);
+ assertNotSame(italicSansSerifTypeface, italicSerifTypeface);
+
+ // Cache should work for the same fallback.
+ assertSame(sansSerifTypeface,
+ new Typeface.Builder(assets, "samplefont.ttf").setFallback("sans-serif")
+ .setTtcIndex(100 /* non-existing ttc index */).build());
+ assertSame(serifTypeface,
+ new Typeface.Builder(assets, "samplefont.ttf").setFallback("serif")
+ .setTtcIndex(100 /* non-existing ttc index */).build());
+ assertSame(boldSansSerifTypeface,
+ new Typeface.Builder(assets, "samplefont.ttf").setFallback("sans-serif")
+ .setTtcIndex(100 /* non-existing ttc index */).setWeight(700).build());
+ assertSame(boldSerifTypeface,
+ new Typeface.Builder(assets, "samplefont.ttf").setFallback("serif")
+ .setTtcIndex(100 /* non-existing ttc index */).setWeight(700).build());
+ assertSame(italicSansSerifTypeface,
+ new Typeface.Builder(assets, "samplefont.ttf").setFallback("sans-serif")
+ .setTtcIndex(100 /* non-existing ttc index */).setItalic(true).build());
+ assertSame(italicSerifTypeface,
+ new Typeface.Builder(assets, "samplefont.ttf").setFallback("serif")
+ .setTtcIndex(100 /* non-existing ttc index */).setItalic(true).build());
+ }
+
+ @Test
public void testTypefaceBuilder_FileSourceFD() {
try (FileInputStream fis = new FileInputStream(obtainPath())) {
assertNotNull(new Typeface.Builder(fis.getFD()).build());
@@ -392,4 +476,27 @@
assertNotEquals(widthDefaultTypeface, widthCustomTypeface, 1.0f);
}
}
+
+ @Test
+ public void testTypefaceBuilder_customFallback() {
+ final String fontPath = "samplefont2.ttf";
+ final Typeface regularTypeface = new Typeface.Builder(mContext.getAssets(), fontPath)
+ .setWeight(400).build();
+ final Typeface blackTypeface = new Typeface.Builder(mContext.getAssets(), fontPath)
+ .setWeight(900).build();
+
+ // W is not supported by samplefont2.ttf
+ final String testString = "WWWWWWWWWWWWWWWWWWWWW";
+
+ final Paint p = new Paint();
+ p.setTextSize(128);
+
+ p.setTypeface(regularTypeface);
+ final float widthFromRegular = p.measureText(testString);
+
+ p.setTypeface(blackTypeface);
+ final float widthFromBlack = p.measureText(testString);
+
+ assertTrue(Math.abs(widthFromRegular - widthFromBlack) > 1.0f);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
index f8cd816..2e986cb 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedStateListDrawableTest.java
@@ -204,9 +204,11 @@
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final StateListDrawable halfDrawable =
(StateListDrawable) cs.newDrawable(res);
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+ final float approxHalf = (float)(densityDpi / 2) / densityDpi;
for (int i = 0; i < count; i++) {
halfDrawable.selectDrawable(i);
- assertEquals(Math.round(origWidth[i] / 2f), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origWidth[i] * approxHalf), halfDrawable.getIntrinsicWidth());
}
// Set density to double original.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
index 1c9f9b3..29da030 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableParameterizedTest.java
@@ -30,7 +30,9 @@
import android.graphics.cts.R;
import android.graphics.drawable.AnimatedVectorDrawable;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.util.Log;
import android.view.View;
@@ -50,7 +52,7 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-@MediumTest
+@LargeTest
@RunWith(Parameterized.class)
public class AnimatedVectorDrawableParameterizedTest {
@Rule
@@ -183,6 +185,7 @@
return frameLatch.await(timeout, TimeUnit.MILLISECONDS);
}
+ @SmallTest
@Test
public void testSingleFrameAnimation() throws Throwable {
int resId = R.drawable.avd_single_frame;
@@ -208,6 +211,7 @@
});
}
+ @MediumTest
@Test
public void testEmptyAnimatorSet() throws Throwable {
int resId = R.drawable.avd_empty_animator;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index 65aad83..d1f6282 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -36,7 +36,8 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Drawable.ConstantState;
-import android.support.test.filters.MediumTest;
+import android.support.test.filters.LargeTest;
+import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.util.AttributeSet;
@@ -50,7 +51,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-@MediumTest
+@LargeTest
@RunWith(AndroidJUnit4.class)
public class AnimatedVectorDrawableTest {
private static final int IMAGE_WIDTH = 64;
@@ -75,6 +76,7 @@
mResources = mActivity.getResources();
}
+ @SmallTest
@Test
public void testInflate() throws Exception {
// Setup AnimatedVectorDrawable from xml file
@@ -144,6 +146,7 @@
assertEquals(1, constantState.getChangingConfigurations());
}
+ @SmallTest
@Test
public void testMutate() {
AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
@@ -178,6 +181,7 @@
}
}
+ @SmallTest
@Test
public void testGetOpacity() {
AnimatedVectorDrawable d1 = (AnimatedVectorDrawable) mResources.getDrawable(mResId);
@@ -186,6 +190,7 @@
assertEquals("Still translucent", PixelFormat.TRANSLUCENT, d1.getOpacity());
}
+ @SmallTest
@Test
public void testColorFilter() {
PorterDuffColorFilter filter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
index 136ae2d..abba96e 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/CustomAnimationScaleListDrawableTest.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.DrawableContainer;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
+import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import org.junit.After;
@@ -39,7 +40,7 @@
* on animation duration scale. When the scale is 0, it is a static drawable, otherwise, it is an
* animatable drawable.
*/
-@MediumTest
+@SmallTest
@RunWith(AndroidJUnit4.class)
public class CustomAnimationScaleListDrawableTest {
private static final int DRAWABLE_ID = R.drawable.custom_animation_scale_list_drawable;
@@ -58,7 +59,6 @@
ValueAnimator.setDurationScale(mOriginalScale);
}
- @MediumTest
@Test
public void testNonZeroDurationScale() {
// Set the duration scale to a non-zero value will cause the AnimationScaleListDrawable's
@@ -69,7 +69,6 @@
assertTrue(dr.getCurrent() instanceof Animatable);
}
- @MediumTest
@Test
public void testZeroDurationScale() {
// Set the duration scale to zero will cause the AnimationScaleListDrawable's current
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DefaultFocusHighlightTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DefaultFocusHighlightTest.java
new file mode 100644
index 0000000..c8d057a
--- /dev/null
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DefaultFocusHighlightTest.java
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2017 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.graphics.drawable.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.NinePatch;
+import android.graphics.Picture;
+import android.graphics.cts.R;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.DrawableContainer;
+import android.graphics.drawable.DrawableContainer.DrawableContainerState;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LevelListDrawable;
+import android.graphics.drawable.NinePatchDrawable;
+import android.graphics.drawable.PaintDrawable;
+import android.graphics.drawable.PictureDrawable;
+import android.graphics.drawable.RippleDrawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.StateListDrawable;
+import android.graphics.drawable.shapes.RectShape;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.StateSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DefaultFocusHighlightTest {
+
+ // The target context.
+ private Context mContext;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getTargetContext();
+ }
+
+ private static final int A_COLOR = 0x920424;
+ private static final int[] NO_STATE_FOCUSED = new int[] { android.R.attr.state_enabled };
+ private static final int[] ONLY_STATE_FOCUSED = new int[] { android.R.attr.state_focused };
+ private static final int[] STATE_FOCUSED_WITH_POS =
+ new int[] { android.R.attr.state_focused, android.R.attr.state_hovered };
+ private static final int[] STATE_FOCUSED_WITH_NEG =
+ new int[] { android.R.attr.state_focused, -android.R.attr.state_hovered };
+ private static final int[] STATE_FOCUSED_WITH_ENABLED =
+ new int[] { android.R.attr.state_focused, android.R.attr.state_enabled };
+
+ final static int[] FOCUSED_STATE =
+ new int[] { android.R.attr.state_focused, android.R.attr.state_enabled };
+
+ @UiThreadTest
+ @Test
+ public void testStateListDrawable() {
+ Drawable d;
+ // Empty state spec
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] {}
+ );
+ d.setState(FOCUSED_STATE);
+ assertFalse(d.hasFocusStateSpecified());
+
+ // Wild card
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] { StateSet.WILD_CARD }
+ );
+ d.setState(FOCUSED_STATE);
+ assertFalse(d.hasFocusStateSpecified());
+
+ // No state spec of state_focused=true
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] { NO_STATE_FOCUSED }
+ );
+ d.setState(FOCUSED_STATE);
+ assertFalse(d.hasFocusStateSpecified());
+
+ // One state spec of only state_focused=true
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] { ONLY_STATE_FOCUSED }
+ );
+ d.setState(FOCUSED_STATE);
+ assertTrue(d.hasFocusStateSpecified());
+
+ // One state spec of state_focused=true and something=true, but no state spec of
+ // state_focused=true and something=false (something is not enabled)
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] { STATE_FOCUSED_WITH_POS }
+ );
+ d.setState(FOCUSED_STATE);
+ assertTrue(d.hasFocusStateSpecified());
+
+ // One state spec of state_focused=true and something=true, and one spec of
+ // state_focused=true and something=false (something is not enabled)
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG }
+ );
+ d.setState(FOCUSED_STATE);
+ assertTrue(d.hasFocusStateSpecified());
+
+ // One state spec of state_focused=true and enabled=true
+ d = DrawableFactory.createStateListDrawable(
+ new int[][] { STATE_FOCUSED_WITH_ENABLED }
+ );
+ d.setState(FOCUSED_STATE);
+ assertTrue(d.hasFocusStateSpecified());
+ }
+
+ @UiThreadTest
+ @Test
+ public void testRippleDrawable() {
+ Drawable d = DrawableFactory.createRippleDrawable();
+ d.setState(FOCUSED_STATE);
+ assertTrue(d.hasFocusStateSpecified());
+ }
+
+ @UiThreadTest
+ @Test
+ public void testPictureDrawable() {
+ Drawable d = DrawableFactory.createPictureDrawable(null);
+ d.setState(FOCUSED_STATE);
+ assertFalse(d.hasFocusStateSpecified());
+
+ d = DrawableFactory.createPictureDrawable(new Picture());
+ d.setState(FOCUSED_STATE);
+ assertFalse(d.hasFocusStateSpecified());
+ }
+
+ @UiThreadTest
+ @Test
+ public void testColorStateListHandledDrawable() {
+ final Drawable[] drawables = new Drawable[] {
+ DrawableFactory.createShapeDrawable(),
+ DrawableFactory.createPaintDrawable(),
+ DrawableFactory.createBitmapDrawable(mContext),
+ DrawableFactory.createColorDrawable(),
+ DrawableFactory.createGradientDrawable(),
+ DrawableFactory.createNinePatchDrawable(mContext),
+ };
+ final ColorStateList[] stateLists = new ColorStateList[] {
+ // Empty state spec
+ new ColorStateList(
+ new int[][] { },
+ new int[] { }),
+ // Wild card
+ new ColorStateList(
+ new int[][] { StateSet.WILD_CARD },
+ new int[] { A_COLOR }),
+ // No state spec of state_focused=true
+ new ColorStateList(
+ new int[][] { NO_STATE_FOCUSED },
+ new int[] { A_COLOR }),
+ // One state spec of only state_focused=true
+ new ColorStateList(
+ new int[][] { ONLY_STATE_FOCUSED },
+ new int[] { A_COLOR }),
+ // One state spec of state_focused=true and something=true,
+ // but no state spec of state_focused=true and something=false
+ new ColorStateList(
+ new int[][] { STATE_FOCUSED_WITH_POS },
+ new int[] { A_COLOR }),
+ // One state spec of state_focused=true and something=true,
+ // and one spec of state_focused=true and something=false
+ new ColorStateList(
+ new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG },
+ new int[] { A_COLOR, A_COLOR }),
+ };
+ final boolean[] expectedResults = new boolean[] {
+ // Empty state spec
+ false,
+ // Wild card
+ false,
+ // No state spec of state_focused=true
+ false,
+ // One state spec of only state_focused=true
+ true,
+ // One state spec of state_focused=true and something=true,
+ // but no state spec of state_focused=true and something=false
+ true,
+ // One state spec of state_focused=true and something=true,
+ // and one spec of state_focused=true and something=false
+ true
+ };
+ assertEquals(stateLists.length, expectedResults.length);
+ for (Drawable drawable : drawables) {
+ // No ColorStateList set
+ String drawableName = drawable.getClass().toString();
+ String errorMsg = "[" + drawableName + "] Testing no ColorStateList failed.";
+ drawable.setState(FOCUSED_STATE);
+ assertFalse(errorMsg, drawable.hasFocusStateSpecified());
+ // With ColorStateList set
+ for (int i = 0; i < stateLists.length; i++) {
+ ColorStateList stateList = stateLists[i];
+ boolean expectedResult = expectedResults[i];
+ drawable.setTintList(stateList);
+ errorMsg = "[" + drawableName + "] Testing ColorStateList No." + i + " failed.";
+
+ drawable.setState(FOCUSED_STATE);
+ if (expectedResult) {
+ assertTrue(errorMsg, drawable.hasFocusStateSpecified());
+ } else {
+ assertFalse(errorMsg, drawable.hasFocusStateSpecified());
+ }
+ }
+ }
+ }
+
+ @UiThreadTest
+ @Test
+ public void testDrawableContainer() {
+ MockDrawableContainer container;
+ DrawableContainerState containerState;
+
+ // Empty
+ container = new MockDrawableContainer();
+ containerState = (DrawableContainerState) new LevelListDrawable().getConstantState();
+ assertNotNull(containerState);
+ container.setConstantState(containerState);
+ container.setState(FOCUSED_STATE);
+ assertFalse(container.hasFocusStateSpecified());
+
+ // No drawable of state_focused=true
+ container = new MockDrawableContainer();
+ containerState = (DrawableContainerState) new LevelListDrawable().getConstantState();
+ assertNotNull(containerState);
+ container.setConstantState(containerState);
+ containerState.addChild(DrawableFactory.createPaintDrawable());
+ containerState.addChild(DrawableFactory.createBitmapDrawable(mContext));
+ containerState.addChild(DrawableFactory.createColorDrawable());
+ container.selectDrawable(0);
+ container.setState(FOCUSED_STATE);
+ assertFalse(container.hasFocusStateSpecified());
+ container.selectDrawable(1);
+ container.setState(FOCUSED_STATE);
+ assertFalse(container.hasFocusStateSpecified());
+ container.selectDrawable(2);
+ container.setState(FOCUSED_STATE);
+ assertFalse(container.hasFocusStateSpecified());
+
+ // Only drawables of state_focused=true
+ container = new MockDrawableContainer();
+ containerState = (DrawableContainerState) new LevelListDrawable().getConstantState();
+ assertNotNull(containerState);
+ container.setConstantState(containerState);
+ containerState.addChild(DrawableFactory.createRippleDrawable());
+ containerState.addChild(
+ DrawableFactory.createStateListDrawable(
+ new int[][] { STATE_FOCUSED_WITH_POS, STATE_FOCUSED_WITH_NEG }
+ )
+ );
+ container.selectDrawable(0);
+ container.setState(FOCUSED_STATE);
+ assertTrue(container.hasFocusStateSpecified());
+ container.selectDrawable(1);
+ container.setState(FOCUSED_STATE);
+ assertTrue(container.hasFocusStateSpecified());
+
+ // Both drawables of state_focused=true and state_focused=false
+ containerState.addChild(DrawableFactory.createColorDrawable());
+ container.selectDrawable(2);
+ container.setState(FOCUSED_STATE);
+ assertFalse(container.hasFocusStateSpecified());
+ container.selectDrawable(1);
+ container.setState(FOCUSED_STATE);
+ assertTrue(container.hasFocusStateSpecified());
+ container.selectDrawable(0);
+ container.setState(FOCUSED_STATE);
+ assertTrue(container.hasFocusStateSpecified());
+ }
+
+ static class DrawableFactory {
+ static ShapeDrawable createShapeDrawable() {
+ return new ShapeDrawable(new RectShape());
+ }
+ static PaintDrawable createPaintDrawable() {
+ PaintDrawable paintDrawable = new PaintDrawable();
+ paintDrawable.setCornerRadius(1.5f);
+ return paintDrawable;
+ }
+ static BitmapDrawable createBitmapDrawable(Context context) {
+ Bitmap bitmap = Bitmap.createBitmap(200, 300, Config.ARGB_8888);
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(context.getResources(), bitmap);
+ return bitmapDrawable;
+ }
+ static ColorDrawable createColorDrawable() {
+ return new ColorDrawable(A_COLOR);
+ }
+ static GradientDrawable createGradientDrawable() {
+ GradientDrawable gradientDrawable = new GradientDrawable();
+ gradientDrawable.setColor(A_COLOR);
+ gradientDrawable.setCornerRadius(10f);
+ return gradientDrawable;
+ }
+ static NinePatchDrawable createNinePatchDrawable(Context context) {
+ Resources res = context.getResources();
+ Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.ninepatch_0);
+ NinePatch np = new NinePatch(bitmap, bitmap.getNinePatchChunk(), null);
+ NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(res, np);
+ return ninePatchDrawable;
+ }
+ static RippleDrawable createRippleDrawable() {
+ RippleDrawable rippleDrawable =
+ new RippleDrawable(ColorStateList.valueOf(A_COLOR), null, null);
+ return rippleDrawable;
+ }
+ static PictureDrawable createPictureDrawable(Picture picture) {
+ PictureDrawable pictureDrawable = new PictureDrawable(picture);
+ return pictureDrawable;
+ }
+ static StateListDrawable createStateListDrawable(int[][] stateList) {
+ StateListDrawable drawable = new StateListDrawable();
+ ColorDrawable colorDrawable = DrawableFactory.createColorDrawable();
+ for (int i = 0; i < stateList.length; i++) {
+ drawable.addState(stateList[i], colorDrawable);
+ }
+ return drawable;
+ }
+ }
+
+ // We're calling protected methods in DrawableContainer.
+ // So we have to extend it here to make it accessible.
+ private class MockDrawableContainer extends DrawableContainer {
+ @Override
+ protected void setConstantState(DrawableContainerState state) {
+ super.setConstantState(state);
+ }
+ }
+
+}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
index eb660f3..b798fb8 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/GradientDrawableTest.java
@@ -52,6 +52,7 @@
import java.io.IOException;
import java.util.Arrays;
+@SmallTest
@RunWith(AndroidJUnit4.class)
public class GradientDrawableTest {
private Resources mResources;
@@ -61,7 +62,6 @@
mResources = InstrumentationRegistry.getTargetContext().getResources();
}
- @SmallTest
@Test
public void testConstructor() {
int[] color = new int[] {1, 2, 3};
@@ -71,7 +71,6 @@
new GradientDrawable(null, null);
}
- @SmallTest
@Test
public void testGetOpacity() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -105,7 +104,6 @@
}
- @SmallTest
@Test
public void testSetOrientation() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -117,7 +115,6 @@
orientation, gradientDrawable.getOrientation());
}
- @SmallTest
@Test
public void testSetCornerRadii() {
float[] radii = new float[] {1.0f, 2.0f, 3.0f};
@@ -136,7 +133,6 @@
gradientDrawable.setCornerRadii(null);
}
- @SmallTest
@Test
public void testSetCornerRadius() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -145,7 +141,6 @@
gradientDrawable.setCornerRadius(-2.5f);
}
- @SmallTest
@Test
public void testGetCornerRadius() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -160,7 +155,6 @@
assertEquals(0, gradientDrawable.getCornerRadius(), 0);
}
- @SmallTest
@Test
public void testSetStroke() {
helpTestSetStroke(2, Color.RED);
@@ -174,7 +168,6 @@
// TODO: Verify stroke properties.
}
- @SmallTest
@Test
public void testSetStroke_WidthGap() {
verifySetStroke_WidthGap(2, Color.RED, 3.4f, 5.5f);
@@ -189,7 +182,6 @@
// TODO: Verify stroke properties.
}
- @SmallTest
@Test
public void testSetStrokeList() {
verifySetStrokeList(2, ColorStateList.valueOf(Color.RED));
@@ -204,7 +196,6 @@
// TODO: Verify stroke properties.
}
- @SmallTest
@Test
public void testSetStrokeList_WidthGap() {
verifySetStrokeList_WidthGap(2, ColorStateList.valueOf(Color.RED), 3.4f, 5.5f);
@@ -219,7 +210,6 @@
// TODO: Verify stroke properties.
}
- @SmallTest
@Test
public void testSetSize() {
verifySetSize(6, 4);
@@ -235,7 +225,6 @@
assertEquals(height, gradientDrawable.getIntrinsicHeight());
}
- @SmallTest
@Test
public void testSetShape() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -252,7 +241,6 @@
shape, gradientDrawable.getShape());
}
- @SmallTest
@Test
public void testSetGradientType() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -269,7 +257,6 @@
gradientType, gradientDrawable.getGradientType());
}
- @SmallTest
@Test
public void testSetGradientCenter() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -294,7 +281,6 @@
assertEquals(centerY, gradientDrawable.getGradientCenterY(), 0.01f);
}
- @SmallTest
@Test
public void testSetGradientRadius() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -303,7 +289,6 @@
gradientDrawable.setGradientRadius(-3.6f);
}
- @SmallTest
@Test
public void testSetUseLevel() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -322,7 +307,6 @@
useLevel, gradientDrawable.getUseLevel());
}
- @SmallTest
@Test
public void testDraw() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -333,7 +317,6 @@
gradientDrawable.draw(null);
}
- @SmallTest
@Test
public void testSetColor() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -350,7 +333,6 @@
gradientDrawable.getColor().getDefaultColor());
}
- @SmallTest
@Test
public void testSetColors() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -367,7 +349,6 @@
colors, gradientDrawable.getColors());
}
- @SmallTest
@Test
public void testSetColorList() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -382,7 +363,6 @@
assertEquals("Color was set to null (TRANSPARENT)", color, gradientDrawable.getColor());
}
- @SmallTest
@Test
public void testGetChangingConfigurations() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -395,7 +375,6 @@
assertEquals(-20, gradientDrawable.getChangingConfigurations());
}
- @SmallTest
@Test
public void testSetAlpha() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -404,7 +383,6 @@
gradientDrawable.setAlpha(-1);
}
- @SmallTest
@Test
public void testSetDither() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -413,7 +391,6 @@
gradientDrawable.setDither(false);
}
- @SmallTest
@Test
public void testSetColorFilter() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -424,7 +401,6 @@
gradientDrawable.setColorFilter(null);
}
- @SmallTest
@Test
public void testInflate() throws XmlPullParserException, IOException {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -469,7 +445,6 @@
}
}
- @SmallTest
@Test
public void testInflateGradientRadius() throws XmlPullParserException, IOException {
Rect parentBounds = new Rect(0, 0, 100, 100);
@@ -490,7 +465,6 @@
assertEquals(50.0f, radius, 0.0f);
}
- @SmallTest
@Test
public void testGetIntrinsicWidth() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -501,7 +475,6 @@
assertEquals(-10, gradientDrawable.getIntrinsicWidth());
}
- @SmallTest
@Test
public void testGetIntrinsicHeight() {
GradientDrawable gradientDrawable = new GradientDrawable();
@@ -512,14 +485,12 @@
assertEquals(-15, gradientDrawable.getIntrinsicHeight());
}
- @SmallTest
@Test
public void testGetConstantState() {
GradientDrawable gradientDrawable = new GradientDrawable();
assertNotNull(gradientDrawable.getConstantState());
}
- @SmallTest
@Test
public void testMutate() {
GradientDrawable d1 =
@@ -555,17 +526,28 @@
assertEquals(40, d3.getIntrinsicWidth());
}
- @MediumTest
@Test
public void testPreloadDensity() throws XmlPullParserException, IOException {
final int densityDpi = mResources.getConfiguration().densityDpi;
try {
+ DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
verifyPreloadDensityInner(mResources, densityDpi);
} finally {
DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
}
}
+ @Test
+ public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+ final int densityDpi = mResources.getConfiguration().densityDpi;
+ try {
+ DrawableTestUtils.setResourcesDensity(mResources, 213);
+ verifyPreloadDensityInner(mResources, 213);
+ } finally {
+ DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+ }
+ }
+
private void verifyPreloadDensityInner(Resources res, int densityDpi)
throws XmlPullParserException, IOException {
final Rect tempPadding = new Rect();
@@ -581,15 +563,17 @@
final Rect origPadding = new Rect();
preloadedDrawable.getPadding(origPadding);
- // Set density to half of original. Unlike offsets, which are
+ // Set density to approximately half of original. Unlike offsets, which are
// truncated, dimensions are rounded to the nearest pixel.
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final GradientDrawable halfDrawable =
(GradientDrawable) preloadedConstantState.newDrawable(res);
- assertEquals(Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
- assertEquals(Math.round(origHeight / 2f), halfDrawable.getIntrinsicHeight());
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+ final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+ assertEquals(Math.round(origWidth * approxHalf), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origHeight * approxHalf), halfDrawable.getIntrinsicHeight());
assertTrue(halfDrawable.getPadding(tempPadding));
- assertEquals((int) (origPadding.left / 2f), tempPadding.left);
+ assertEquals((int) (origPadding.left * approxHalf), tempPadding.left);
// Set density to double original.
DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
@@ -609,20 +593,21 @@
assertTrue(origDrawable.getPadding(tempPadding));
assertEquals(origPadding, tempPadding);
- // Some precision is lost when scaling the half-density
- // drawable back up to the original density. Padding is
- // always truncated, rather than rounded.
+ // Reproduce imprecise truncated scale down, and back up. Note these aren't rounded.
+ final float approxDouble = 1 / approxHalf;
final Rect sloppyOrigPadding = new Rect();
- sloppyOrigPadding.left = 2 * (origPadding.left / 2);
- sloppyOrigPadding.top = 2 * (origPadding.top / 2);
- sloppyOrigPadding.right = 2 * (origPadding.right / 2);
- sloppyOrigPadding.bottom = 2 * (origPadding.bottom / 2);
+ sloppyOrigPadding.left = (int)(approxDouble * ((int)(origPadding.left * approxHalf)));
+ sloppyOrigPadding.top = (int)(approxDouble * ((int)(origPadding.top * approxHalf)));
+ sloppyOrigPadding.right = (int)(approxDouble * ((int)(origPadding.right * approxHalf)));
+ sloppyOrigPadding.bottom = (int)(approxDouble * ((int)(origPadding.bottom * approxHalf)));
// Ensure theme density is applied correctly.
final Theme t = res.newTheme();
halfDrawable.applyTheme(t);
- assertEquals(2 * Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
- assertEquals(2 * Math.round(origHeight / 2f), halfDrawable.getIntrinsicHeight());
+ assertEquals(Math.round(approxDouble * Math.round(origWidth * approxHalf)),
+ halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(approxDouble * Math.round(origHeight * approxHalf)),
+ halfDrawable.getIntrinsicHeight());
assertTrue(halfDrawable.getPadding(tempPadding));
assertEquals(sloppyOrigPadding, tempPadding);
doubleDrawable.applyTheme(t);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
index 3fcdf82..5eb89fc 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/InsetDrawableTest.java
@@ -342,12 +342,25 @@
final Resources res = mContext.getResources();
final int densityDpi = res.getConfiguration().densityDpi;
try {
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
verifyPreloadDensityInner(res, densityDpi);
} finally {
DrawableTestUtils.setResourcesDensity(res, densityDpi);
}
}
+ @Test
+ public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+ final Resources res = mContext.getResources();
+ final int densityDpi = res.getConfiguration().densityDpi;
+ try {
+ DrawableTestUtils.setResourcesDensity(res, 213);
+ verifyPreloadDensityInner(res, 213);
+ } finally {
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ }
+ }
+
private void verifyPreloadDensityInner(Resources res, int densityDpi)
throws XmlPullParserException, IOException {
// Capture initial state at default density.
@@ -359,12 +372,14 @@
final int origInsetHoriz = preloadedDrawable.getIntrinsicWidth()
- preloadedDrawable.getDrawable().getIntrinsicWidth();
- // Set density to half of original. Unlike offsets, which are
+ // Set density to approximately half of original. Unlike offsets, which are
// truncated, dimensions are rounded to the nearest pixel.
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final InsetDrawable halfDrawable =
(InsetDrawable) preloadedConstantState.newDrawable(res);
- assertEquals(Math.round(origInsetHoriz / 2f), halfDrawable.getIntrinsicWidth()
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+ final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+ assertEquals(Math.round(origInsetHoriz * approxHalf), halfDrawable.getIntrinsicWidth()
- halfDrawable.getDrawable().getIntrinsicWidth());
// Set density to double original.
@@ -384,8 +399,10 @@
// Ensure theme density is applied correctly.
final Theme t = res.newTheme();
halfDrawable.applyTheme(t);
- assertEquals(origInsetHoriz, halfDrawable.getIntrinsicWidth()
- - halfDrawable.getDrawable().getIntrinsicWidth());
+ float approxDouble = 1 / approxHalf;
+ // Reproduce imprecise truncated scale down, and back up. Note that we don't round.
+ assertEquals((int)(approxDouble * ((int)(origInsetHoriz * approxHalf))),
+ halfDrawable.getIntrinsicWidth() - halfDrawable.getDrawable().getIntrinsicWidth());
doubleDrawable.applyTheme(t);
assertEquals(origInsetHoriz, doubleDrawable.getIntrinsicWidth()
- doubleDrawable.getDrawable().getIntrinsicWidth());
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
index 22491ee..ed9a187 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -1678,12 +1678,25 @@
final Resources res = mContext.getResources();
final int densityDpi = res.getConfiguration().densityDpi;
try {
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
verifyPreloadDensityInner(res, densityDpi);
} finally {
DrawableTestUtils.setResourcesDensity(res, densityDpi);
}
}
+ @Test
+ public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+ final Resources res = mContext.getResources();
+ final int densityDpi = res.getConfiguration().densityDpi;
+ try {
+ DrawableTestUtils.setResourcesDensity(res, 213);
+ verifyPreloadDensityInner(res, 213);
+ } finally {
+ DrawableTestUtils.setResourcesDensity(res, densityDpi);
+ }
+ }
+
private void verifyPreloadDensityInner(Resources res, int densityDpi)
throws XmlPullParserException, IOException {
// Capture initial state at default density.
@@ -1714,11 +1727,13 @@
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final LayerDrawable halfDrawable =
(LayerDrawable) preloadedConstantState.newDrawable(res);
- final int halfContentWidth = Math.round(initialContentWidth / 2f);
- final int halfLeftPadding = initialLeftPadding / 2;
- final int halfRightPadding = initialRightPadding / 2;
- final int halfContentInsetL = initialContentInsetL / 2;
- final int halfContentInsetR = initialContentInsetR / 2;
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+ final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+ final int halfContentWidth = Math.round(initialContentWidth * approxHalf);
+ final int halfLeftPadding = (int) (initialLeftPadding * approxHalf);
+ final int halfRightPadding = (int) (initialRightPadding * approxHalf);
+ final int halfContentInsetL = (int) (initialContentInsetL * approxHalf);
+ final int halfContentInsetR = (int) (initialContentInsetR * approxHalf);
final int halfIntrinsicWidth = halfContentWidth + halfContentInsetL + halfContentInsetR;
assertEquals(halfLeftPadding, halfDrawable.getLeftPadding());
assertEquals(halfRightPadding, halfDrawable.getRightPadding());
@@ -1726,14 +1741,18 @@
assertEquals(halfContentInsetR, halfDrawable.getLayerInsetLeft(0));
assertEquals(halfContentWidth, halfDrawable.getLayerWidth(0));
assertEquals(halfIntrinsicWidth, halfDrawable.getIntrinsicWidth());
- assertEquals(initialBottomPadding / 2, halfDrawable.getBottomPadding());
- assertEquals(initialTopPadding / 2, halfDrawable.getTopPadding());
- assertEquals(initialLayerInsetLeft / 2,halfDrawable.getLayerInsetLeft(0));
- assertEquals(initialLayerInsetRight / 2, halfDrawable.getLayerInsetRight(0));
- assertEquals(initialLayerInsetTop / 2, halfDrawable.getLayerInsetTop(0));
- assertEquals(initialLayerInsetBottom / 2, halfDrawable.getLayerInsetBottom(0));
- assertEquals(Math.round(initialLayerWidth / 2f), halfDrawable.getLayerWidth(0));
- assertEquals(Math.round(initialLayerHeight / 2f), halfDrawable.getLayerHeight(0));
+ assertEquals((int) (initialBottomPadding * approxHalf), halfDrawable.getBottomPadding());
+ assertEquals((int) (initialTopPadding * approxHalf), halfDrawable.getTopPadding());
+ assertEquals((int) (initialLayerInsetLeft * approxHalf),
+ halfDrawable.getLayerInsetLeft(0));
+ assertEquals((int) (initialLayerInsetRight * approxHalf),
+ halfDrawable.getLayerInsetRight(0));
+ assertEquals((int) (initialLayerInsetTop * approxHalf),
+ halfDrawable.getLayerInsetTop(0));
+ assertEquals((int) (initialLayerInsetBottom * approxHalf),
+ halfDrawable.getLayerInsetBottom(0));
+ assertEquals(Math.round(initialLayerWidth * approxHalf), halfDrawable.getLayerWidth(0));
+ assertEquals(Math.round(initialLayerHeight * approxHalf), halfDrawable.getLayerHeight(0));
// Set density to double original.
DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
@@ -1779,20 +1798,31 @@
// The half-density drawable will scale-up all of the values that were
// previously scaled-down, so we need to capture the rounding errors.
halfDrawable.applyTheme(t);
- assertEquals(halfLeftPadding * 2, halfDrawable.getLeftPadding());
- assertEquals(halfRightPadding * 2, halfDrawable.getRightPadding());
- assertEquals(halfContentInsetL * 2, halfDrawable.getLayerInsetRight(0));
- assertEquals(halfContentInsetR * 2, halfDrawable.getLayerInsetLeft(0));
- assertEquals(halfContentWidth * 2, halfDrawable.getLayerWidth(0));
+
+ // Reproduce imprecise truncated scale down, and back up. Note that we don't round.
+ float approxDouble = 1 / approxHalf;
+ assertEquals((int) (halfLeftPadding * approxDouble), halfDrawable.getLeftPadding());
+ assertEquals((int) (halfRightPadding * approxDouble), halfDrawable.getRightPadding());
+ assertEquals((int) (halfContentInsetL * approxDouble), halfDrawable.getLayerInsetRight(0));
+ assertEquals((int) (halfContentInsetR * approxDouble), halfDrawable.getLayerInsetLeft(0));
+ assertEquals((int) (halfContentWidth * approxDouble), halfDrawable.getLayerWidth(0));
assertEquals(halfIntrinsicWidth * 2, halfDrawable.getIntrinsicWidth());
- assertEquals(2 * (initialBottomPadding / 2), halfDrawable.getBottomPadding());
- assertEquals(2 * (initialTopPadding / 2), halfDrawable.getTopPadding());
- assertEquals(2 * (initialLayerInsetLeft / 2), halfDrawable.getLayerInsetLeft(0));
- assertEquals(2 * (initialLayerInsetRight / 2), halfDrawable.getLayerInsetRight(0));
- assertEquals(2 * (initialLayerInsetTop / 2), halfDrawable.getLayerInsetTop(0));
- assertEquals(2 * (initialLayerInsetBottom / 2), halfDrawable.getLayerInsetBottom(0));
- assertEquals(2 * Math.round(initialLayerWidth / 2f), halfDrawable.getLayerWidth(0));
- assertEquals(2 * Math.round(initialLayerHeight / 2f), halfDrawable.getLayerHeight(0));
+ assertEquals((int) ((int) (initialBottomPadding * approxHalf) * approxDouble),
+ halfDrawable.getBottomPadding());
+ assertEquals((int) ((int) (initialTopPadding * approxHalf) * approxDouble),
+ halfDrawable.getTopPadding());
+ assertEquals((int) ((int) (initialLayerInsetLeft * approxHalf) * approxDouble),
+ halfDrawable.getLayerInsetLeft(0));
+ assertEquals((int) ((int) (initialLayerInsetRight * approxHalf) * approxDouble),
+ halfDrawable.getLayerInsetRight(0));
+ assertEquals((int) ((int) (initialLayerInsetTop * approxHalf) * approxDouble),
+ halfDrawable.getLayerInsetTop(0));
+ assertEquals((int) ((int) (initialLayerInsetBottom * approxHalf) * approxDouble),
+ halfDrawable.getLayerInsetBottom(0));
+ assertEquals(Math.round(Math.round(initialLayerWidth * approxHalf) * approxDouble),
+ halfDrawable.getLayerWidth(0));
+ assertEquals(Math.round(Math.round(initialLayerHeight * approxHalf) * approxDouble),
+ halfDrawable.getLayerHeight(0));
// The double-density drawable will scale-down all of the values that
// were previously scaled-up, so we don't need to worry about rounding.
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
index 80d604e..d563102 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ShapeDrawableTest.java
@@ -36,6 +36,7 @@
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.graphics.cts.R;
@@ -219,6 +220,18 @@
assertNull(shapeDrawable.getShaderFactory());
}
+ @Test
+ public void testSetXfermode() {
+ ShapeDrawable shapeDrawable = new ShapeDrawable();
+
+ PorterDuffXfermode xfermode = new PorterDuffXfermode(Mode.SRC_OVER);
+ shapeDrawable.setXfermode(xfermode);
+ assertSame(xfermode, shapeDrawable.getPaint().getXfermode());
+
+ shapeDrawable.setXfermode(null);
+ assertNull(shapeDrawable.getPaint().getXfermode());
+ }
+
public static class MockShaderFactory extends ShaderFactory {
public Shader resize(int width, int height) {
return null;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
index fb3445e..6499594 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/StateListDrawableTest.java
@@ -229,10 +229,12 @@
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final StateListDrawable halfDrawable =
(StateListDrawable) preloadedConstantState.newDrawable(res);
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+ final float approxHalf = (float)(densityDpi / 2) / densityDpi;
halfDrawable.selectDrawable(0);
- assertEquals(Math.round(origWidth0 / 2f), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origWidth0 * approxHalf), halfDrawable.getIntrinsicWidth());
halfDrawable.selectDrawable(1);
- assertEquals(Math.round(origWidth1 / 2f), halfDrawable.getIntrinsicWidth());
+ assertEquals(Math.round(origWidth1 * approxHalf), halfDrawable.getIntrinsicWidth());
// Set density to double original.
DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
index 16c6961..276bf50 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/VectorDrawableTest.java
@@ -33,7 +33,6 @@
import android.graphics.drawable.Drawable.ConstantState;
import android.graphics.drawable.VectorDrawable;
import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.util.AttributeSet;
@@ -50,6 +49,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
+@SmallTest
@RunWith(AndroidJUnit4.class)
public class VectorDrawableTest {
private static final String LOGTAG = "VectorDrawableTest";
@@ -200,31 +200,26 @@
mResources = InstrumentationRegistry.getTargetContext().getResources();
}
- @MediumTest
@Test
public void testBasicVectorDrawables() throws XmlPullParserException, IOException {
verifyVectorDrawables(BASIC_ICON_RES_IDS, BASIC_GOLDEN_IMAGES, null);
}
- @MediumTest
@Test
public void testLMVectorDrawables() throws XmlPullParserException, IOException {
verifyVectorDrawables(L_M_ICON_RES_IDS, L_M_GOLDEN_IMAGES, null);
}
- @MediumTest
@Test
public void testNVectorDrawables() throws XmlPullParserException, IOException {
verifyVectorDrawables(N_ICON_RES_IDS, N_GOLDEN_IMAGES, null);
}
- @MediumTest
@Test
public void testVectorDrawableGradient() throws XmlPullParserException, IOException {
verifyVectorDrawables(GRADIENT_ICON_RES_IDS, GRADIENT_GOLDEN_IMAGES, null);
}
- @MediumTest
@Test
public void testColorStateList() throws XmlPullParserException, IOException {
for (int i = 0; i < STATEFUL_STATE_SETS.length; i++) {
@@ -344,7 +339,6 @@
return builder.toString();
}
- @SmallTest
@Test
public void testGetChangingConfigurations() {
VectorDrawable vectorDrawable = new VectorDrawable();
@@ -369,7 +363,6 @@
assertEquals(0xffff, vectorDrawable.getChangingConfigurations());
}
- @SmallTest
@Test
public void testGetConstantState() {
VectorDrawable vectorDrawable = new VectorDrawable();
@@ -383,7 +376,6 @@
assertEquals(1, constantState.getChangingConfigurations());
}
- @SmallTest
@Test
public void testMutate() {
// d1 and d2 will be mutated, while d3 will not.
@@ -419,7 +411,6 @@
}
}
- @SmallTest
@Test
public void testColorFilter() {
PorterDuffColorFilter filter = new PorterDuffColorFilter(Color.RED, Mode.SRC_IN);
@@ -429,18 +420,6 @@
assertEquals(filter, vectorDrawable.getColorFilter());
}
- @SmallTest
- @Test
- public void testPreloadDensity() throws XmlPullParserException, IOException {
- final int densityDpi = mResources.getConfiguration().densityDpi;
- try {
- verifyPreloadDensityInner(mResources, densityDpi);
- } finally {
- DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
- }
- }
-
- @SmallTest
@Test
public void testGetOpacity () throws XmlPullParserException, IOException {
VectorDrawable vectorDrawable = new VectorDrawable();
@@ -455,6 +434,28 @@
vectorDrawable.getOpacity());
}
+ @Test
+ public void testPreloadDensity() throws XmlPullParserException, IOException {
+ final int densityDpi = mResources.getConfiguration().densityDpi;
+ try {
+ DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+ verifyPreloadDensityInner(mResources, densityDpi);
+ } finally {
+ DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+ }
+ }
+
+ @Test
+ public void testPreloadDensity_tvdpi() throws XmlPullParserException, IOException {
+ final int densityDpi = mResources.getConfiguration().densityDpi;
+ try {
+ DrawableTestUtils.setResourcesDensity(mResources, 213);
+ verifyPreloadDensityInner(mResources, 213);
+ } finally {
+ DrawableTestUtils.setResourcesDensity(mResources, densityDpi);
+ }
+ }
+
private void verifyPreloadDensityInner(Resources res, int densityDpi)
throws XmlPullParserException, IOException {
// Capture initial state at default density.
@@ -470,7 +471,9 @@
DrawableTestUtils.setResourcesDensity(res, densityDpi / 2);
final VectorDrawable halfDrawable =
(VectorDrawable) preloadedConstantState.newDrawable(res);
- assertEquals(Math.round(origWidth / 2f), halfDrawable.getIntrinsicWidth());
+ // NOTE: densityDpi may not be an even number, so account for *actual* scaling in asserts
+ final float approxHalf = (float)(densityDpi / 2) / densityDpi;
+ assertEquals(Math.round(origWidth * approxHalf), halfDrawable.getIntrinsicWidth());
// Set density to double original.
DrawableTestUtils.setResourcesDensity(res, densityDpi * 2);
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index f01b833..b7f7c8e 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -109,6 +109,7 @@
.compile("([0-9]{4})-([0-9]{2})-[0-9]{2}");
private static final int KM_ERROR_INVALID_INPUT_LENGTH = -21;
+ private static final int KM_ERROR_PERMISSION_DENIED = 6;
public void testVersionParser() throws Exception {
// Non-numerics/empty give version 0
@@ -211,6 +212,29 @@
}
}
+ public void testEcAttestation_KeyStoreExceptionWhenRequestingUniqueId() throws Exception {
+ String keystoreAlias = "test_key";
+ KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
+ .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+ .setDigests(DIGEST_NONE, DIGEST_SHA256, DIGEST_SHA512)
+ .setAttestationChallenge(new byte[128])
+ .setUniqueIdIncluded(true)
+ .build();
+
+ try {
+ generateKeyPair(KEY_ALGORITHM_EC, spec);
+ fail("Attestation should have failed.");
+ } catch (ProviderException e) {
+ // Attestation is expected to fail because of lack of permissions.
+ KeyStoreException cause = (KeyStoreException) e.getCause();
+ assertEquals(KM_ERROR_PERMISSION_DENIED, cause.getErrorCode());
+ } finally {
+ KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ keyStore.load(null);
+ keyStore.deleteEntry(keystoreAlias);
+ }
+ }
+
public void testRsaAttestation() throws Exception {
int[] keySizes = { // Smallish sizes to keep test runtimes down.
512, 768, 1024
diff --git a/tests/tests/location/src/android/location/cts/LocationTest.java b/tests/tests/location/src/android/location/cts/LocationTest.java
index bec6350..3e291cf 100644
--- a/tests/tests/location/src/android/location/cts/LocationTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationTest.java
@@ -282,10 +282,6 @@
location.setVerticalAccuracyMeters(1.0f);
assertEquals(1.0, location.getVerticalAccuracyMeters(), DELTA);
assertTrue(location.hasVerticalAccuracy());
-
- location.removeVerticalAccuracy();
- assertEquals(0.0, location.getVerticalAccuracyMeters(), DELTA);
- assertFalse(location.hasVerticalAccuracy());
}
public void testAccessSpeedAccuracy() {
@@ -295,10 +291,6 @@
location.setSpeedAccuracyMetersPerSecond(1.0f);
assertEquals(1.0, location.getSpeedAccuracyMetersPerSecond(), DELTA);
assertTrue(location.hasSpeedAccuracy());
-
- location.removeSpeedAccuracy();
- assertEquals(0.0, location.getSpeedAccuracyMetersPerSecond(), DELTA);
- assertFalse(location.hasSpeedAccuracy());
}
public void testAccessBearingAccuracy() {
@@ -308,10 +300,6 @@
location.setBearingAccuracyDegrees(1.0f);
assertEquals(1.0, location.getBearingAccuracyDegrees(), DELTA);
assertTrue(location.hasBearingAccuracy());
-
- location.removeBearingAccuracy();
- assertEquals(0.0, location.getBearingAccuracyDegrees(), DELTA);
- assertFalse(location.hasBearingAccuracy());
}
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
index 0cbbe7e..99c0ac1 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
@@ -36,13 +36,63 @@
"android.media.cts", "android.media.cts.StubMediaBrowserService");
private final Object mWaitLock = new Object();
- private final ConnectionCallback mConnectionCallback = new ConnectionCallback();
- private final SubscriptionCallback mSubscriptionCallback = new SubscriptionCallback();
- private final ItemCallback mItemCallback = new ItemCallback();
- private final SearchCallback mSearchCallback = new SearchCallback();
+ private final MediaBrowser.ConnectionCallback mConnectionCallback =
+ new MediaBrowser.ConnectionCallback() {
+ @Override
+ public void onConnected() {
+ synchronized (mWaitLock) {
+ mMediaBrowserService = StubMediaBrowserService.sInstance;
+ mWaitLock.notify();
+ }
+ }
+ };
+
+ private final MediaBrowser.SubscriptionCallback mSubscriptionCallback =
+ new MediaBrowser.SubscriptionCallback() {
+ @Override
+ public void onChildrenLoaded(String parentId, List<MediaItem> children) {
+ synchronized (mWaitLock) {
+ mOnChildrenLoaded = true;
+ if (children != null) {
+ for (MediaItem item : children) {
+ assertRootHints(item);
+ }
+ }
+ mWaitLock.notify();
+ }
+ }
+
+ @Override
+ public void onChildrenLoaded(String parentId, List<MediaItem> children,
+ Bundle options) {
+ synchronized (mWaitLock) {
+ mOnChildrenLoadedWithOptions = true;
+ if (children != null) {
+ for (MediaItem item : children) {
+ assertRootHints(item);
+ }
+ }
+ mWaitLock.notify();
+ }
+ }
+ };
+
+ private final MediaBrowser.ItemCallback mItemCallback = new MediaBrowser.ItemCallback() {
+ @Override
+ public void onItemLoaded(MediaItem item) {
+ synchronized (mWaitLock) {
+ mOnItemLoaded = true;
+ assertRootHints(item);
+ mWaitLock.notify();
+ }
+ }
+ };
private MediaBrowser mMediaBrowser;
private StubMediaBrowserService mMediaBrowserService;
+ private boolean mOnChildrenLoaded;
+ private boolean mOnChildrenLoadedWithOptions;
+ private boolean mOnItemLoaded;
private Bundle mRootHints;
@Override
@@ -72,15 +122,14 @@
public void testNotifyChildrenChanged() throws Exception {
synchronized (mWaitLock) {
- mSubscriptionCallback.reset();
mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_ROOT, mSubscriptionCallback);
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+ assertTrue(mOnChildrenLoaded);
- mSubscriptionCallback.reset();
+ mOnChildrenLoaded = false;
mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserService.MEDIA_ID_ROOT);
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+ assertTrue(mOnChildrenLoaded);
}
}
@@ -92,54 +141,53 @@
options.putInt(MediaBrowser.EXTRA_PAGE_SIZE, pageSize);
options.putInt(MediaBrowser.EXTRA_PAGE, page);
- mSubscriptionCallback.reset();
mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_ROOT, options,
mSubscriptionCallback);
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mSubscriptionCallback.mOnChildrenLoadedWithOptions);
+ assertTrue(mOnChildrenLoadedWithOptions);
- mSubscriptionCallback.reset();
+ mOnChildrenLoadedWithOptions = false;
mMediaBrowserService.notifyChildrenChanged(StubMediaBrowserService.MEDIA_ID_ROOT);
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mSubscriptionCallback.mOnChildrenLoadedWithOptions);
+ assertTrue(mOnChildrenLoadedWithOptions);
}
}
public void testDelayedNotifyChildrenChanged() throws Exception {
synchronized (mWaitLock) {
- mSubscriptionCallback.reset();
+ mOnChildrenLoaded = false;
mMediaBrowser.subscribe(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED,
mSubscriptionCallback);
mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
- assertFalse(mSubscriptionCallback.mOnChildrenLoaded);
+ assertFalse(mOnChildrenLoaded);
mMediaBrowserService.sendDelayedNotifyChildrenChanged();
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+ assertTrue(mOnChildrenLoaded);
- mSubscriptionCallback.reset();
+ mOnChildrenLoaded = false;
mMediaBrowserService.notifyChildrenChanged(
StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED);
mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
- assertFalse(mSubscriptionCallback.mOnChildrenLoaded);
+ assertFalse(mOnChildrenLoaded);
mMediaBrowserService.sendDelayedNotifyChildrenChanged();
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mSubscriptionCallback.mOnChildrenLoaded);
+ assertTrue(mOnChildrenLoaded);
}
}
public void testDelayedItem() throws Exception {
synchronized (mWaitLock) {
- mItemCallback.reset();
- mMediaBrowser.getItem(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED, mItemCallback);
+ mOnItemLoaded = false;
+ mMediaBrowser.getItem(StubMediaBrowserService.MEDIA_ID_CHILDREN_DELAYED,
+ mItemCallback);
mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
- assertFalse(mItemCallback.mOnItemLoaded);
+ assertFalse(mOnItemLoaded);
- mItemCallback.reset();
mMediaBrowserService.sendDelayedItemLoaded();
mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mItemCallback.mOnItemLoaded);
+ assertTrue(mOnItemLoaded);
}
}
@@ -155,60 +203,6 @@
assertEquals(val, browserRoot.getExtras().getString(key));
}
- public void testSearch() throws Exception {
- final String key = "test-key";
- final String val = "test-val";
-
- final MediaBrowser.SearchCallback searchCallback =
- (MediaBrowser.SearchCallback) mSearchCallback;
- final MediaBrowserService mediaBrowserService = (MediaBrowserService) mMediaBrowserService;
-
- synchronized (mWaitLock) {
- mSearchCallback.reset();
- mMediaBrowser.search(StubMediaBrowserService.SEARCH_QUERY_FOR_NO_RESULT, null,
- mSearchCallback);
- mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
- assertTrue(mSearchCallback.mOnSearchResult);
- assertTrue(mSearchCallback.mSearchResults != null
- && mSearchCallback.mSearchResults.size() == 0);
- assertEquals(null, mSearchCallback.mSearchExtras);
- // just call the callback once directly so it's marked as tested
- mediaBrowserService.onSearch(
- StubMediaBrowserService.SEARCH_QUERY_FOR_NO_RESULT, null, null);
- searchCallback.onSearchResult(StubMediaBrowserService.SEARCH_QUERY_FOR_NO_RESULT,
- mSearchCallback.mSearchExtras, mSearchCallback.mSearchResults);
-
- mSearchCallback.reset();
- mMediaBrowser.search(StubMediaBrowserService.SEARCH_QUERY_FOR_ERROR, null,
- mSearchCallback);
- mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
- assertTrue(mSearchCallback.mOnSearchResult);
- assertNull(mSearchCallback.mSearchResults);
- assertEquals(null, mSearchCallback.mSearchExtras);
- // just call the callback once directly so it's marked as tested
- mediaBrowserService.onSearch(
- StubMediaBrowserService.SEARCH_QUERY_FOR_ERROR, null, null);
- searchCallback.onError(StubMediaBrowserService.SEARCH_QUERY_FOR_ERROR, null);
-
- mSearchCallback.reset();
- Bundle extras = new Bundle();
- extras.putString(key, val);
- mMediaBrowser.search(StubMediaBrowserService.SEARCH_QUERY, extras, mSearchCallback);
- mWaitLock.wait(WAIT_TIME_FOR_NO_RESPONSE_MS);
- assertTrue(mSearchCallback.mOnSearchResult);
- assertNotNull(mSearchCallback.mSearchResults);
- for (MediaItem item : mSearchCallback.mSearchResults) {
- assertTrue(item.getMediaId().contains(StubMediaBrowserService.SEARCH_QUERY));
- }
- assertNotNull(mSearchCallback.mSearchExtras);
- assertEquals(val, mSearchCallback.mSearchExtras.getString(key));
- // just call the callback once directly so it's marked as tested
- mediaBrowserService.onSearch(StubMediaBrowserService.SEARCH_QUERY, extras, null);
- searchCallback.onSearchResult(StubMediaBrowserService.SEARCH_QUERY,
- mSearchCallback.mSearchExtras, mSearchCallback.mSearchResults);
- }
- }
-
private void assertRootHints(MediaItem item) {
Bundle rootHints = item.getDescription().getExtras();
assertNotNull(rootHints);
@@ -219,100 +213,4 @@
assertEquals(mRootHints.getBoolean(BrowserRoot.EXTRA_SUGGESTED),
rootHints.getBoolean(BrowserRoot.EXTRA_SUGGESTED));
}
-
- private class ConnectionCallback extends MediaBrowser.ConnectionCallback {
- @Override
- public void onConnected() {
- synchronized (mWaitLock) {
- mMediaBrowserService = StubMediaBrowserService.sInstance;
- mWaitLock.notify();
- }
- }
- }
-
- private class SubscriptionCallback extends MediaBrowser.SubscriptionCallback {
- boolean mOnChildrenLoaded;
- boolean mOnChildrenLoadedWithOptions;
-
- @Override
- public void onChildrenLoaded(String parentId, List<MediaItem> children) {
- synchronized (mWaitLock) {
- mOnChildrenLoaded = true;
- if (children != null) {
- for (MediaItem item : children) {
- assertRootHints(item);
- }
- }
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onChildrenLoaded(String parentId, List<MediaItem> children,
- Bundle options) {
- synchronized (mWaitLock) {
- mOnChildrenLoadedWithOptions = true;
- if (children != null) {
- for (MediaItem item : children) {
- assertRootHints(item);
- }
- }
- mWaitLock.notify();
- }
- }
-
- public void reset() {
- mOnChildrenLoaded = false;
- mOnChildrenLoadedWithOptions = false;
- }
- }
-
- private class ItemCallback extends MediaBrowser.ItemCallback {
- boolean mOnItemLoaded;
-
- @Override
- public void onItemLoaded(MediaItem item) {
- synchronized (mWaitLock) {
- mOnItemLoaded = true;
- assertRootHints(item);
- mWaitLock.notify();
- }
- }
-
- public void reset() {
- mOnItemLoaded = false;
- }
- }
-
- private class SearchCallback extends MediaBrowser.SearchCallback {
- boolean mOnSearchResult;
- Bundle mSearchExtras;
- List<MediaItem> mSearchResults;
-
- @Override
- public void onSearchResult(String query, Bundle extras, List<MediaItem> items) {
- synchronized (mWaitLock) {
- mOnSearchResult = true;
- mSearchResults = items;
- mSearchExtras = extras;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onError(String query, Bundle extras) {
- synchronized (mWaitLock) {
- mOnSearchResult = true;
- mSearchResults = null;
- mSearchExtras = extras;
- mWaitLock.notify();
- }
- }
-
- public void reset() {
- mOnSearchResult = false;
- mSearchExtras = null;
- mSearchResults = null;
- }
- }
}
diff --git a/tests/tests/media/src/android/media/cts/MediaCasTest.java b/tests/tests/media/src/android/media/cts/MediaCasTest.java
index d2ae849..a3cdefc 100644
--- a/tests/tests/media/src/android/media/cts/MediaCasTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCasTest.java
@@ -18,6 +18,7 @@
import android.media.MediaCas;
import android.media.MediaCas.PluginDescriptor;
+import android.media.MediaCas.Session;
import android.media.MediaCasException;
import android.media.MediaCasException.UnsupportedCasException;
import android.media.MediaCasStateException;
@@ -181,10 +182,10 @@
}, null);
} finally {
if (mediaCas != null) {
- mediaCas.release();
+ mediaCas.close();
}
if (descrambler != null) {
- descrambler.release();
+ descrambler.close();
}
}
}
@@ -213,10 +214,10 @@
}
} finally {
if (unsupportedCAS != null) {
- unsupportedCAS.release();
+ unsupportedCAS.close();
}
if (unsupportedDescrambler != null) {
- unsupportedDescrambler.release();
+ unsupportedDescrambler.close();
}
}
}
@@ -247,24 +248,22 @@
byte[] pvtData = new byte[256];
mediaCas.setPrivateData(pvtData);
- int program_number = 72849;
- int elementary_PID = 256;
- byte[] sessionId = mediaCas.openSession(72849);
- if (sessionId == null || sessionId.length == 0) {
+ Session session = mediaCas.openSession();
+ if (session == null) {
fail("Can't open session for program");
}
- mediaCas.setSessionPrivateData(sessionId, pvtData);
+ session.setPrivateData(pvtData);
- byte[] streamSessionId = mediaCas.openSession(72849, 256);
- if (streamSessionId == null || streamSessionId.length == 0) {
+ Session streamSession = mediaCas.openSession();
+ if (streamSession == null) {
fail("Can't open session for stream");
}
- mediaCas.setSessionPrivateData(streamSessionId, pvtData);
+ streamSession.setPrivateData(pvtData);
- descrambler.setMediaCasSession(sessionId);
+ descrambler.setMediaCasSession(session);
- descrambler.setMediaCasSession(streamSessionId);
+ descrambler.setMediaCasSession(streamSession);
mediaCas.refreshEntitlements(3, null);
@@ -291,8 +290,8 @@
mediaCas.processEmm(emmData);
byte[] ecmData = loadByteArrayFromString(sEcmBufferStr);
- mediaCas.processEcm(sessionId, ecmData);
- mediaCas.processEcm(streamSessionId, ecmData);
+ session.processEcm(ecmData);
+ streamSession.processEcm(ecmData);
ByteBuffer outputBuf = descrambleTestInputBuffer(descrambler);
ByteBuffer expectedOutputBuf = ByteBuffer.wrap(
@@ -300,14 +299,14 @@
assertTrue("Incorrect decryption result",
expectedOutputBuf.compareTo(outputBuf) == 0);
- mediaCas.closeSession(sessionId);
- mediaCas.closeSession(streamSessionId);
+ session.close();
+ streamSession.close();
} finally {
if (mediaCas != null) {
- mediaCas.release();
+ mediaCas.close();
}
if (descrambler != null) {
- descrambler.release();
+ descrambler.close();
}
}
}
@@ -324,28 +323,28 @@
descrambler = new MediaDescrambler(sClearKeySystemId);
mediaCas.provision(sProvisionStr);
- byte[] sessionId = mediaCas.openSession(72849);
- if (sessionId == null || sessionId.length == 0) {
+ Session session = mediaCas.openSession();
+ if (session == null) {
fail("Can't open session for program");
}
- byte[] streamSessionId = mediaCas.openSession(72849, 256);
- if (streamSessionId == null || streamSessionId.length == 0) {
+ Session streamSession = mediaCas.openSession();
+ if (streamSession == null) {
fail("Can't open session for stream");
}
- mediaCas.release();
+ mediaCas.close();
mediaCas = null;
try {
- descrambler.setMediaCasSession(sessionId);
+ descrambler.setMediaCasSession(session);
fail("Program session not closed after MediaCas is released");
} catch (MediaCasStateException e) {
Log.d(TAG, "setMediaCasSession throws "
+ e.getDiagnosticInfo() + " (as expected)");
}
try {
- descrambler.setMediaCasSession(streamSessionId);
+ descrambler.setMediaCasSession(streamSession);
fail("Stream session not closed after MediaCas is released");
} catch (MediaCasStateException e) {
Log.d(TAG, "setMediaCasSession throws "
@@ -353,10 +352,10 @@
}
} finally {
if (mediaCas != null) {
- mediaCas.release();
+ mediaCas.close();
}
if (descrambler != null) {
- descrambler.release();
+ descrambler.close();
}
}
}
@@ -393,26 +392,31 @@
Log.d(TAG, "processEmm throws ArrayIndexOutOfBoundsException (as expected)");
}
- byte[] invalidSessionId = new byte[] {};
+ // open a session, then close it so that it should become invalid
+ Session invalidSession = mediaCas.openSession();
+ if (invalidSession == null) {
+ fail("Can't open session for program");
+ }
+ invalidSession.close();
byte[] ecmData = loadByteArrayFromString(sEcmBufferStr);
// processEcm should fail with an invalid session id
try {
- mediaCas.processEcm(invalidSessionId, ecmData);
+ invalidSession.processEcm(ecmData);
fail("processEcm shouldn't succeed with invalid session id");
} catch (MediaCasStateException e) {
Log.d(TAG, "processEcm throws " + e.getDiagnosticInfo() + " (as expected)");
}
- byte[] sessionId = mediaCas.openSession(72849);
- if (sessionId == null || sessionId.length == 0) {
+ Session session = mediaCas.openSession();
+ if (session == null) {
fail("Can't open session for program");
}
// processEcm should fail without provisioning
try {
- mediaCas.processEcm(sessionId, ecmData);
+ session.processEcm(ecmData);
fail("processEcm shouldn't succeed without provisioning");
} catch (MediaCasException.NotProvisionedException e) {
Log.d(TAG, "processEcm throws NotProvisionedException (as expected)");
@@ -423,7 +427,7 @@
// processEcm should fail with ecm buffer that's too short
try {
- mediaCas.processEcm(sessionId, ecmData, 0, 8);
+ session.processEcm(ecmData, 0, 8);
fail("processEcm shouldn't succeed with truncated ecm");
} catch (IllegalArgumentException e) {
Log.d(TAG, "processEcm throws " + e.toString() + " (as expected)");
@@ -432,7 +436,7 @@
// processEcm should fail with ecm with bad descriptor count
try {
ecmData[17] = 3; // change the descriptor count field to 3 (invalid)
- mediaCas.processEcm(sessionId, ecmData);
+ session.processEcm(ecmData);
fail("processEcm shouldn't succeed with altered descriptor count");
} catch (MediaCasStateException e) {
Log.d(TAG, "processEcm throws " + e.getDiagnosticInfo() + " (as expected)");
@@ -444,7 +448,7 @@
// setMediaCasSession should fail with an invalid session id
try {
- descrambler.setMediaCasSession(invalidSessionId);
+ descrambler.setMediaCasSession(invalidSession);
fail("setMediaCasSession shouldn't succeed with invalid session id");
} catch (MediaCasStateException e) {
Log.d(TAG, "setMediaCasSession throws "
@@ -460,7 +464,7 @@
}
// Now set a valid session, should still fail because no valid ecm is processed
- descrambler.setMediaCasSession(sessionId);
+ descrambler.setMediaCasSession(session);
try {
ByteBuffer outputBuf = descrambleTestInputBuffer(descrambler);
fail("descramble should fail without valid ecm");
@@ -469,10 +473,10 @@
}
} finally {
if (mediaCas != null) {
- mediaCas.release();
+ mediaCas.close();
}
if (descrambler != null) {
- descrambler.release();
+ descrambler.close();
}
}
}
@@ -537,7 +541,7 @@
ByteBuffer inputBuf = ByteBuffer.wrap(
loadByteArrayFromString(sInputBufferStr));
ByteBuffer outputBuf = ByteBuffer.allocate(inputBuf.capacity());
- descrambler.descramble(inputBuf, 0, outputBuf, 0, cryptoInfo);
+ descrambler.descramble(inputBuf, outputBuf, cryptoInfo);
return outputBuf;
}
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java b/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
index 253a5ab..99f2790 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecClearKeyPlayer.java
@@ -230,8 +230,6 @@
private void prepareVideo() throws IOException {
boolean hasVideo = false;
- android.media.DrmInitData drmInitData = mVideoExtractor.getDrmInitData();
-
for (int i = mVideoExtractor.getTrackCount(); i-- > 0;) {
MediaFormat format = mVideoExtractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
@@ -244,11 +242,10 @@
Log.d(TAG, "video track #" + i + " " + format + " " + mime +
" Width:" + mMediaFormatWidth + ", Height:" + mMediaFormatHeight);
- if (mScrambled && drmInitData != null && mime.startsWith("video/")) {
- android.media.DrmInitData.SchemeInitData schemeInitData =
- drmInitData.get(new UUID(0, i));
- if (schemeInitData != null) {
- mDescrambler.setMediaCasSession(schemeInitData.data);
+ if (mScrambled && mime.startsWith("video/")) {
+ MediaExtractor.CasInfo casInfo = mVideoExtractor.getCasInfo(i);
+ if (casInfo != null && casInfo.getSession() != null) {
+ mDescrambler.setMediaCasSession(casInfo.getSession());
}
}
@@ -291,23 +288,18 @@
private void initCasAndDescrambler(MediaExtractor extractor) throws MediaCasException {
int trackCount = extractor.getTrackCount();
- android.media.DrmInitData drmInitData = extractor.getDrmInitData();
for (int trackId = 0; trackId < trackCount; trackId++) {
android.media.MediaFormat format = extractor.getTrackFormat(trackId);
String mime = format.getString(android.media.MediaFormat.KEY_MIME);
Log.d(TAG, "track "+ trackId + ": " + mime);
if ("video/scrambled".equals(mime) || "audio/scrambled".equals(mime)) {
- if (drmInitData == null) {
- throw new IllegalArgumentException("found scrambled track without drmInitData!");
+ MediaExtractor.CasInfo casInfo = extractor.getCasInfo(trackId);
+ if (casInfo != null) {
+ mMediaCas = new MediaCas(casInfo.getSystemId());
+ mDescrambler = new MediaDescrambler(casInfo.getSystemId());
+ mMediaCas.provision(sProvisionStr);
+ extractor.setMediaCas(mMediaCas);
}
- android.media.DrmInitData.SchemeInitData schemeInitData =
- drmInitData.get(new UUID(0, trackId));
- int CA_system_id = (schemeInitData.data[0] & 0xff)
- | ((schemeInitData.data[1] & 0xff) << 8);
- mMediaCas = new MediaCas(CA_system_id);
- mDescrambler = new MediaDescrambler(CA_system_id);
- mMediaCas.provision(sProvisionStr);
- extractor.setMediaCas(mMediaCas);
}
}
}
@@ -550,12 +542,12 @@
}
if (mMediaCas != null) {
- mMediaCas.release();
+ mMediaCas.close();
mMediaCas = null;
}
if (mDescrambler != null) {
- mDescrambler.release();
+ mDescrambler.close();
mDescrambler = null;
}
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecTest.java b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
index 9b941a2..56cbc93 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecTest.java
@@ -32,10 +32,10 @@
import android.media.MediaFormat;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecInfo.CodecProfileLevel;
-import android.media.MediaMetricsSet;
import android.opengl.GLES20;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.PersistableBundle;
import android.support.test.filters.SmallTest;
import android.platform.test.annotations.RequiresDevice;
import android.test.AndroidTestCase;
@@ -919,17 +919,17 @@
// good
}
- MediaMetricsSet metricsSet = encoder.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = encoder.getMetrics();
+ if (metrics == null) {
fail("getMetrics() returns null");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("getMetrics() returns empty results");
}
- int encoding = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+ int encoding = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
if (encoding != 1) {
fail("getMetrics() returns bad encoder value " + encoding);
}
- String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+ String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
if (theCodec == null) {
fail("getMetrics() returns null codec value ");
}
@@ -989,17 +989,17 @@
// good
}
- MediaMetricsSet metricsSet = encoder.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = encoder.getMetrics();
+ if (metrics == null) {
fail("getMetrics() returns null");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("getMetrics() returns empty results");
}
- int encoding = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+ int encoding = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
if (encoding != 1) {
fail("getMetrics() returns bad encoder value " + encoding);
}
- String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+ String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
if (theCodec == null) {
fail("getMetrics() returns null codec value ");
}
@@ -1050,17 +1050,17 @@
throw new RuntimeException("decoder does not generate non-empty output.");
}
- MediaMetricsSet metricsSet = mediaCodec.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = mediaCodec.getMetrics();
+ if (metrics == null) {
fail("getMetrics() returns null");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("getMetrics() returns empty results");
}
- int encoder = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+ int encoder = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
if (encoder != 0) {
fail("getMetrics() returns bad encoder value " + encoder);
}
- String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+ String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
if (theCodec == null) {
fail("getMetrics() returns null codec value ");
}
@@ -1071,17 +1071,17 @@
mediaCodec.flush();
completed.set(runDecodeTillFirstOutput(mediaCodec, mediaExtractor));
- metricsSet = mediaCodec.getMetrics();
- if (metricsSet == null) {
+ metrics = mediaCodec.getMetrics();
+ if (metrics == null) {
fail("getMetrics() returns null");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("getMetrics() returns empty results");
}
- int encoding = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+ int encoding = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
if (encoding != 0) {
fail("getMetrics() returns bad encoder value " + encoding);
}
- String theCodec2 = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+ String theCodec2 = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
if (theCodec2 == null) {
fail("getMetrics() returns null codec value ");
}
@@ -1092,17 +1092,17 @@
if (mediaCodec != null) {
mediaCodec.stop();
- MediaMetricsSet metricsSet = mediaCodec.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = mediaCodec.getMetrics();
+ if (metrics == null) {
fail("getMetrics() returns null");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("getMetrics() returns empty results");
}
- int encoder = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+ int encoder = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
if (encoder != 0) {
fail("getMetrics() returns bad encoder value " + encoder);
}
- String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+ String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
if (theCodec == null) {
fail("getMetrics() returns null codec value ");
}
@@ -1166,14 +1166,14 @@
}
assertTrue("Wrong output buffer index", outputBufferIndex >= 0);
- MediaMetricsSet metricsSet = mediaCodec.getMetrics();
- Log.d(TAG, "getMetrics after first buffer metricsSet says: " + metricsSet);
+ PersistableBundle metrics = mediaCodec.getMetrics();
+ Log.d(TAG, "getMetrics after first buffer metrics says: " + metrics);
- int encoder = metricsSet.getInt(MediaMetricsSet.MediaCodec.KEY_ENCODER, -1);
+ int encoder = metrics.getInt(MediaCodec.MetricsConstants.ENCODER, -1);
if (encoder != 0) {
fail("getMetrics() returns bad encoder value " + encoder);
}
- String theCodec = metricsSet.getString(MediaMetricsSet.MediaCodec.KEY_CODEC, null);
+ String theCodec = metrics.getString(MediaCodec.MetricsConstants.CODEC, null);
if (theCodec == null) {
fail("getMetrics() returns null codec value ");
}
diff --git a/tests/tests/media/src/android/media/cts/MediaControllerTest.java b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
index 9aaf1aa..17588ee 100644
--- a/tests/tests/media/src/android/media/cts/MediaControllerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaControllerTest.java
@@ -19,11 +19,8 @@
import android.media.AudioManager;
import android.media.Rating;
import android.media.VolumeProvider;
-import android.media.MediaDescription;
import android.media.session.MediaController;
import android.media.session.MediaSession;
-import android.media.session.MediaSession.QueueItem;
-import android.media.session.PlaybackState;
import android.media.session.PlaybackState.CustomAction;
import android.net.Uri;
import android.os.Bundle;
@@ -53,7 +50,6 @@
super.setUp();
mSession = new MediaSession(getContext(), SESSION_TAG);
mSession.setCallback(mCallback, mHandler);
- mSession.setFlags(MediaSession.FLAG_HANDLES_QUEUE_COMMANDS);
mController = mSession.getController();
}
@@ -88,53 +84,6 @@
}
}
- public void testAddRemoveQueueItems() throws Exception {
- final String mediaId = "media_id";
- final String mediaTitle = "media_title";
- MediaDescription itemDescription = new MediaDescription.Builder()
- .setMediaId(mediaId).setTitle(mediaTitle).build();
- final MediaSession.Callback callback = (MediaSession.Callback) mCallback;
-
- synchronized (mWaitLock) {
- mCallback.reset();
- mController.addQueueItem(itemDescription);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnAddQueueItemCalled);
- assertEquals(-1, mCallback.mQueueIndex);
- assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
- assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
- // just call the callback once directly so it's marked as tested
- callback.onAddQueueItem(mCallback.mQueueDescription);
-
- mCallback.reset();
- mController.addQueueItem(itemDescription, 0);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnAddQueueItemAtCalled);
- assertEquals(0, mCallback.mQueueIndex);
- assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
- assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
- // just call the callback once directly so it's marked as tested
- callback.onAddQueueItem(mCallback.mQueueDescription, mCallback.mQueueIndex);
-
- mCallback.reset();
- mController.removeQueueItemAt(0);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnRemoveQueueItemAtCalled);
- assertEquals(0, mCallback.mQueueIndex);
- // just call the callback once directly so it's marked as tested
- callback.onRemoveQueueItemAt(mCallback.mQueueIndex);
-
- mCallback.reset();
- mController.removeQueueItem(itemDescription);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnRemoveQueueItemCalled);
- assertEquals(mediaId, mCallback.mQueueDescription.getMediaId());
- assertEquals(mediaTitle, mCallback.mQueueDescription.getTitle());
- // just call the callback once directly so it's marked as tested
- callback.onRemoveQueueItem(mCallback.mQueueDescription);
- }
- }
-
public void testVolumeControl() throws Exception {
VolumeProvider vp = new VolumeProvider(VolumeProvider.VOLUME_CONTROL_ABSOLUTE, 11, 5) {
@Override
@@ -346,26 +295,6 @@
assertTrue(mCallback.mOnPrepareFromUriCalled);
assertEquals(uri, mCallback.mUri);
assertEquals(EXTRAS_VALUE, mCallback.mExtras.getString(EXTRAS_KEY));
- // just call the callback once directly so it's marked as tested
- callback.onPrepareFromUri(mCallback.mUri, mCallback.mExtras);
-
- mCallback.reset();
- final int repeatMode = PlaybackState.REPEAT_MODE_ALL;
- controls.setRepeatMode(repeatMode);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnSetRepeatModeCalled);
- assertEquals(repeatMode, mCallback.mRepeatMode);
- // just call the callback once directly so it's marked as tested
- callback.onSetRepeatMode(mCallback.mRepeatMode);
-
- mCallback.reset();
- final boolean shuffleModeEnabled = true;
- controls.setShuffleModeEnabled(shuffleModeEnabled);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnSetShuffleModeEnabledCalled);
- assertEquals(shuffleModeEnabled, mCallback.mShuffleModeEnabled);
- // just call the callback once directly so it's marked as tested
- callback.onSetShuffleModeEnabled(mCallback.mShuffleModeEnabled);
}
}
@@ -389,8 +318,6 @@
private class MediaSessionCallback extends MediaSession.Callback {
private long mSeekPosition;
private long mQueueItemId;
- private int mQueueIndex;
- private MediaDescription mQueueDescription;
private Rating mRating;
private String mMediaId;
private String mQuery;
@@ -399,8 +326,6 @@
private String mCommand;
private Bundle mExtras;
private ResultReceiver mCommandCallback;
- private int mRepeatMode;
- private boolean mShuffleModeEnabled;
private boolean mOnPlayCalled;
private boolean mOnPauseCalled;
@@ -421,18 +346,10 @@
private boolean mOnPrepareFromMediaIdCalled;
private boolean mOnPrepareFromSearchCalled;
private boolean mOnPrepareFromUriCalled;
- private boolean mOnSetRepeatModeCalled;
- private boolean mOnSetShuffleModeEnabledCalled;
- private boolean mOnAddQueueItemCalled;
- private boolean mOnAddQueueItemAtCalled;
- private boolean mOnRemoveQueueItemCalled;
- private boolean mOnRemoveQueueItemAtCalled;
public void reset() {
mSeekPosition = -1;
mQueueItemId = -1;
- mQueueIndex = -1;
- mQueueDescription = null;
mRating = null;
mMediaId = null;
mQuery = null;
@@ -441,8 +358,6 @@
mExtras = null;
mCommand = null;
mCommandCallback = null;
- mShuffleModeEnabled = false;
- mRepeatMode = PlaybackState.REPEAT_MODE_NONE;
mOnPlayCalled = false;
mOnPauseCalled = false;
@@ -463,12 +378,6 @@
mOnPrepareFromMediaIdCalled = false;
mOnPrepareFromSearchCalled = false;
mOnPrepareFromUriCalled = false;
- mOnSetRepeatModeCalled = false;
- mOnSetShuffleModeEnabledCalled = false;
- mOnAddQueueItemCalled = false;
- mOnAddQueueItemAtCalled = false;
- mOnRemoveQueueItemCalled = false;
- mOnRemoveQueueItemAtCalled = false;
}
@Override
@@ -642,60 +551,5 @@
mWaitLock.notify();
}
}
-
- @Override
- public void onSetRepeatMode(int repeatMode) {
- synchronized (mWaitLock) {
- mOnSetRepeatModeCalled = true;
- mRepeatMode = repeatMode;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onSetShuffleModeEnabled(boolean enabled) {
- synchronized (mWaitLock) {
- mOnSetShuffleModeEnabledCalled = true;
- mShuffleModeEnabled = enabled;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onAddQueueItem(MediaDescription description) {
- synchronized (mWaitLock) {
- mOnAddQueueItemCalled = true;
- mQueueDescription = description;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onAddQueueItem(MediaDescription description, int index) {
- synchronized (mWaitLock) {
- mOnAddQueueItemAtCalled = true;
- mQueueIndex = index;
- mQueueDescription = description;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onRemoveQueueItem(MediaDescription description) {
- synchronized (mWaitLock) {
- mOnRemoveQueueItemCalled = true;
- mQueueDescription = description;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onRemoveQueueItemAt(int index) {
- synchronized (mWaitLock) {
- mOnRemoveQueueItemAtCalled = true;
- mQueueIndex = index;
- mWaitLock.notify();
- }
- }
}
}
diff --git a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
index 7248c7d..b6f34f4 100644
--- a/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaExtractorTest.java
@@ -17,12 +17,12 @@
package android.media.cts;
import android.media.cts.R;
-import android.media.MediaMetricsSet;
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaDataSource;
import android.media.MediaExtractor;
+import android.os.PersistableBundle;
import android.test.AndroidTestCase;
import java.io.IOException;
@@ -110,12 +110,12 @@
}
// verify some getMetrics() behaviors while we're here.
- MediaMetricsSet metricsSet = mExtractor.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = mExtractor.getMetrics();
+ if (metrics == null) {
fail("getMetrics() returns no data");
} else {
// ensure existence of some known fields
- int tracks = metricsSet.getInt(MediaMetricsSet.MediaExtractor.KEY_TRACKS, -1);
+ int tracks = metrics.getInt(MediaExtractor.MetricsConstants.TRACKS, -1);
if (tracks != trackCount) {
fail("getMetrics() trackCount expect " + trackCount + " got " + tracks);
}
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 2431bf2..82b992d 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -20,8 +20,8 @@
import android.content.res.AssetFileDescriptor;
import android.content.res.Resources;
import android.media.MediaPlayer;
-import android.media.MediaMetricsSet;
import android.net.Uri;
+import android.os.PersistableBundle;
import android.test.ActivityInstrumentationTestCase2;
import com.android.compatibility.common.util.MediaUtils;
@@ -324,15 +324,15 @@
}
// validate a few MediaMetrics.
- MediaMetricsSet metricsSet = mMediaPlayer.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = mMediaPlayer.getMetrics();
+ if (metrics == null) {
fail("MediaPlayer.getMetrics() returned null metrics");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("MediaPlayer.getMetrics() returned empty metrics");
} else {
- int size = metricsSet.size();
- Set<String> keys = metricsSet.keySet();
+ int size = metrics.size();
+ Set<String> keys = metrics.keySet();
if (keys == null) {
fail("MediaMetricsSet returned no keys");
@@ -341,22 +341,22 @@
}
// we played something; so one of these should be non-null
- String vmime = metricsSet.getString(MediaMetricsSet.MediaPlayer.KEY_MIME_VIDEO, null);
- String amime = metricsSet.getString(MediaMetricsSet.MediaPlayer.KEY_MIME_AUDIO, null);
+ String vmime = metrics.getString(MediaPlayer.MetricsConstants.MIME_TYPE_VIDEO, null);
+ String amime = metrics.getString(MediaPlayer.MetricsConstants.MIME_TYPE_AUDIO, null);
if (vmime == null && amime == null) {
fail("getMetrics() returned neither video nor audio mime value");
}
- long duration = metricsSet.getLong(MediaMetricsSet.MediaPlayer.KEY_DURATION, -2);
+ long duration = metrics.getLong(MediaPlayer.MetricsConstants.DURATION, -2);
if (duration == -2) {
fail("getMetrics() didn't return a duration");
}
- long playing = metricsSet.getLong(MediaMetricsSet.MediaPlayer.KEY_PLAYING, -2);
+ long playing = metrics.getLong(MediaPlayer.MetricsConstants.PLAYING, -2);
if (playing == -2) {
fail("getMetrics() didn't return a playing time");
}
- if (!keys.contains(MediaMetricsSet.MediaPlayer.KEY_PLAYING)) {
- fail("MediaMetricsSet.keys() missing: " + MediaMetricsSet.MediaPlayer.KEY_PLAYING);
+ if (!keys.contains(MediaPlayer.MetricsConstants.PLAYING)) {
+ fail("MediaMetricsSet.keys() missing: " + MediaPlayer.MetricsConstants.PLAYING);
}
}
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index fbf51ca..d3c392c 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -30,10 +30,10 @@
import android.media.MediaRecorder.OnErrorListener;
import android.media.MediaRecorder.OnInfoListener;
import android.media.MediaMetadataRetriever;
-import android.media.MediaMetricsSet;
import android.os.ConditionVariable;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.os.PersistableBundle;
import android.support.test.filters.SmallTest;
import android.platform.test.annotations.RequiresDevice;
import android.test.ActivityInstrumentationTestCase2;
@@ -230,14 +230,14 @@
// verify some getMetrics() behaviors while we're here.
- MediaMetricsSet metricsSet = mMediaRecorder.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = mMediaRecorder.getMetrics();
+ if (metrics == null) {
fail("MediaRecorder.getMetrics() returned null metrics");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("MediaRecorder.getMetrics() returned empty metrics");
} else {
- int size = metricsSet.size();
- Set<String> keys = metricsSet.keySet();
+ int size = metrics.size();
+ Set<String> keys = metrics.keySet();
if (size == 0) {
fail("MediaRecorder.getMetrics().size() reports empty record");
@@ -250,14 +250,14 @@
}
// ensure existence of some known fields
- int videoBitRate = metricsSet.getInt(MediaMetricsSet.MediaRecorder.KEY_VIDEO_BITRATE, -1);
+ int videoBitRate = metrics.getInt(MediaRecorder.MetricsConstants.VIDEO_BITRATE, -1);
if (videoBitRate != VIDEO_BIT_RATE_IN_BPS) {
fail("getMetrics() videoEncodeBitrate set " +
VIDEO_BIT_RATE_IN_BPS + " got " + videoBitRate);
}
// careful when comparing floating point numbers
- double captureFrameRate = metricsSet.getDouble(MediaMetricsSet.MediaRecorder.KEY_CAPTURE_FPS, -1);
+ double captureFrameRate = metrics.getDouble(MediaRecorder.MetricsConstants.CAPTURE_FPS, -1);
if (captureFrameRate < 0) {
fail("getMetrics() capture framerate reports " + captureFrameRate);
}
@@ -304,14 +304,14 @@
Thread.sleep(RECORD_TIME_MS);
// verify some getMetrics() behaviors while we're here.
- MediaMetricsSet metricsSet = mMediaRecorder.getMetrics();
- if (metricsSet == null) {
+ PersistableBundle metrics = mMediaRecorder.getMetrics();
+ if (metrics == null) {
fail("MediaRecorder.getMetrics() returned null metrics");
- } else if (metricsSet.isEmpty()) {
+ } else if (metrics.isEmpty()) {
fail("MediaRecorder.getMetrics() returned empty metrics");
} else {
- int size = metricsSet.size();
- Set<String> keys = metricsSet.keySet();
+ int size = metrics.size();
+ Set<String> keys = metrics.keySet();
if (size == 0) {
fail("MediaRecorder.getMetrics().size() reports empty record");
@@ -324,14 +324,14 @@
}
// ensure existence of some known fields
- int videoBitRate = metricsSet.getInt(MediaMetricsSet.MediaRecorder.KEY_VIDEO_BITRATE, -1);
+ int videoBitRate = metrics.getInt(MediaRecorder.MetricsConstants.VIDEO_BITRATE, -1);
if (videoBitRate != VIDEO_BIT_RATE_IN_BPS) {
fail("getMetrics() videoEncodeBitrate set " +
VIDEO_BIT_RATE_IN_BPS + " got " + videoBitRate);
}
// careful when comparing floating point numbers
- double captureFrameRate = metricsSet.getDouble(MediaMetricsSet.MediaRecorder.KEY_CAPTURE_FPS, -1);
+ double captureFrameRate = metrics.getDouble(MediaRecorder.MetricsConstants.CAPTURE_FPS, -1);
if (captureFrameRate < 0) {
fail("getMetrics() capture framerate reports " + captureFrameRate);
}
@@ -520,6 +520,19 @@
fos.close();
}
+ public void testSetOutputFile() throws Exception {
+ if (!hasCamera()) {
+ return;
+ }
+ mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
+ mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);
+ mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
+ mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
+ mMediaRecorder.setOutputFile(mOutFile);
+ long maxFileSize = MAX_FILE_SIZE * 10;
+ recordMedia(maxFileSize, mOutFile);
+ }
+
public void testRecordingAudioInRawFormats() throws Exception {
int testsRun = 0;
if (hasAmrNb()) {
@@ -771,7 +784,8 @@
} else if (mFileIndex < 6) {
try {
String path = OUTPUT_PATH + mFileIndex;
- mMediaRecorder.setNextOutputFile(path);
+ File nextFile = new File(path);
+ mMediaRecorder.setNextOutputFile(nextFile);
recordFileList.add(path);
mFileIndex++;
} catch (IOException e) {
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
index 50b3033..07f63da 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
@@ -149,6 +149,9 @@
session.setPlaybackState(state);
session.setActive(true);
+ // A media playback is also needed to receive media key events.
+ Utils.assertMediaPlaybackStarted(getInstrumentation().getTargetContext());
+
// Ensure that the listener is called for media key event,
// and any other media sessions don't get the key.
MediaKeyListener listener = new MediaKeyListener(2, true, handler);
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTest.java b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
index b84bf1c..5f13a2e 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaSessionTest.java
@@ -222,28 +222,6 @@
mSession.setSessionActivity(pi);
assertEquals(pi, controller.getSessionActivity());
- // test setRepeatMode
- mCallback.resetLocked();
- final int repeatMode = PlaybackState.REPEAT_MODE_ALL;
- mSession.setRepeatMode(repeatMode);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnRepeatModeChangedCalled);
- assertEquals(repeatMode, mCallback.mRepeatMode);
- assertEquals(repeatMode, controller.getRepeatMode());
- // just call the callback once directly so it's marked as tested
- callback.onRepeatModeChanged(mCallback.mRepeatMode);
-
- // test setShuffleModeEnabled
- mCallback.resetLocked();
- final boolean shuffleModeEnabled = true;
- mSession.setShuffleModeEnabled(shuffleModeEnabled);
- mWaitLock.wait(TIME_OUT_MS);
- assertTrue(mCallback.mOnShuffleModeChangedCalled);
- assertEquals(shuffleModeEnabled, mCallback.mShuffleModeEnabled);
- assertEquals(shuffleModeEnabled, controller.isShuffleModeEnabled());
- // just call the callback once directly so it's marked as tested
- callback.onShuffleModeChanged(mCallback.mShuffleModeEnabled);
-
// test setActivity
mSession.setActive(true);
assertTrue(mSession.isActive());
@@ -354,6 +332,9 @@
.setState(PlaybackState.STATE_PLAYING, 0L, 0.0f).build();
mSession.setPlaybackState(defaultState);
+ // A media playback is also needed to receive media key events.
+ Utils.assertMediaPlaybackStarted(getContext());
+
synchronized (mWaitLock) {
sessionCallback.reset();
simulateMediaKeyInput(KeyEvent.KEYCODE_MEDIA_PLAY);
@@ -474,8 +455,6 @@
private volatile boolean mOnAudioInfoChangedCalled;
private volatile boolean mOnSessionDestroyedCalled;
private volatile boolean mOnSessionEventCalled;
- private volatile boolean mOnRepeatModeChangedCalled;
- private volatile boolean mOnShuffleModeChangedCalled;
private volatile PlaybackState mPlaybackState;
private volatile MediaMetadata mMediaMetadata;
@@ -484,8 +463,6 @@
private volatile String mEvent;
private volatile Bundle mExtras;
private volatile MediaController.PlaybackInfo mPlaybackInfo;
- private volatile int mRepeatMode;
- private volatile boolean mShuffleModeEnabled;
public void resetLocked() {
mOnPlaybackStateChangedCalled = false;
@@ -496,8 +473,6 @@
mOnAudioInfoChangedCalled = false;
mOnSessionDestroyedCalled = false;
mOnSessionEventCalled = false;
- mOnRepeatModeChangedCalled = false;
- mOnShuffleModeChangedCalled = false;
mPlaybackState = null;
mMediaMetadata = null;
@@ -505,8 +480,6 @@
mTitle = null;
mExtras = null;
mPlaybackInfo = null;
- mRepeatMode = PlaybackState.REPEAT_MODE_NONE;
- mShuffleModeEnabled = false;
}
@Override
@@ -580,24 +553,6 @@
mWaitLock.notify();
}
}
-
- @Override
- public void onRepeatModeChanged(int repeatMode) {
- synchronized (mWaitLock) {
- mOnRepeatModeChangedCalled = true;
- mRepeatMode = repeatMode;
- mWaitLock.notify();
- }
- }
-
- @Override
- public void onShuffleModeChanged(boolean enabled) {
- synchronized (mWaitLock) {
- mOnShuffleModeChangedCalled = true;
- mShuffleModeEnabled = enabled;
- mWaitLock.notify();
- }
- }
}
private class MediaSessionCallback extends MediaSession.Callback {
diff --git a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
index 96b33da..3dff5bf 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneManagerTest.java
@@ -99,12 +99,19 @@
return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
}
+ private boolean isTV() {
+ return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
+ }
+
public void testConstructors() {
new RingtoneManager(mActivity);
new RingtoneManager(mContext);
}
public void testAccessMethods() {
+ if (isTV()) {
+ return;
+ }
if (!hasAudioOutput()) {
Log.i(TAG, "Skipping testAccessMethods(): device doesn't have audio output.");
return;
@@ -145,6 +152,9 @@
}
public void testStopPreviousRingtone() {
+ if (isTV()) {
+ return;
+ }
if (!hasAudioOutput()) {
Log.i(TAG, "Skipping testStopPreviousRingtone(): device doesn't have audio output.");
return;
diff --git a/tests/tests/media/src/android/media/cts/RingtoneTest.java b/tests/tests/media/src/android/media/cts/RingtoneTest.java
index 1477f3f..31ae5bb 100644
--- a/tests/tests/media/src/android/media/cts/RingtoneTest.java
+++ b/tests/tests/media/src/android/media/cts/RingtoneTest.java
@@ -107,10 +107,18 @@
private boolean hasAudioOutput() {
return getInstrumentation().getContext().getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+ .hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+ }
+
+ private boolean isTV() {
+ return getInstrumentation().getContext().getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
}
public void testRingtone() {
+ if (isTV()) {
+ return;
+ }
if (!hasAudioOutput()) {
Log.i(TAG, "Skipping testRingtone(): device doesn't have audio output.");
return;
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
index 888b3d4..9f90a75 100644
--- a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
+++ b/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
@@ -45,10 +45,6 @@
MEDIA_ID_CHILDREN_DELAYED
};
- static final String SEARCH_QUERY = "test_media_children";
- static final String SEARCH_QUERY_FOR_NO_RESULT = "query no result";
- static final String SEARCH_QUERY_FOR_ERROR = "query for error";
-
static StubMediaBrowserService sInstance;
/* package private */ static MediaSession sSession;
@@ -76,8 +72,10 @@
public void onLoadChildren(final String parentMediaId, final Result<List<MediaItem>> result) {
List<MediaItem> mediaItems = new ArrayList<>();
if (MEDIA_ID_ROOT.equals(parentMediaId)) {
+ Bundle rootHints = getBrowserRootHints();
for (String id : MEDIA_ID_CHILDREN) {
- mediaItems.add(createMediaItem(id));
+ mediaItems.add(new MediaItem(new MediaDescription.Builder()
+ .setMediaId(id).setExtras(rootHints).build(), MediaItem.FLAG_BROWSABLE));
}
result.sendResult(mediaItems);
} else if (MEDIA_ID_CHILDREN_DELAYED.equals(parentMediaId)) {
@@ -101,7 +99,9 @@
for (String id : MEDIA_ID_CHILDREN) {
if (id.equals(itemId)) {
- result.sendResult(createMediaItem(id));
+ result.sendResult(new MediaItem(new MediaDescription.Builder()
+ .setMediaId(id).setExtras(getBrowserRootHints()).build(),
+ MediaItem.FLAG_BROWSABLE));
return;
}
}
@@ -109,27 +109,6 @@
super.onLoadItem(itemId, result);
}
- @Override
- public void onSearch(String query, Bundle extras, Result<List<MediaItem>> result) {
- if (result == null) {
- // called the callback to mark as tested
- return;
- }
- if (SEARCH_QUERY_FOR_NO_RESULT.equals(query)) {
- result.sendResult(Collections.<MediaItem>emptyList());
- } else if (SEARCH_QUERY_FOR_ERROR.equals(query)) {
- result.sendResult(null);
- } else if (SEARCH_QUERY.equals(query)) {
- List<MediaItem> items = new ArrayList<>();
- for (String id : MEDIA_ID_CHILDREN) {
- if (id.contains(query)) {
- items.add(createMediaItem(id));
- }
- }
- result.sendResult(items);
- }
- }
-
public void sendDelayedNotifyChildrenChanged() {
if (mPendingLoadChildrenResult != null) {
mPendingLoadChildrenResult.sendResult(Collections.<MediaItem>emptyList());
@@ -147,10 +126,4 @@
mPendingLoadItemResult = null;
}
}
-
- private MediaItem createMediaItem(String id) {
- return new MediaItem(new MediaDescription.Builder()
- .setMediaId(id).setExtras(getBrowserRootHints()).build(),
- MediaItem.FLAG_BROWSABLE);
- }
}
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
index e8ceeae..fb461fe 100644
--- a/tests/tests/media/src/android/media/cts/Utils.java
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -20,15 +20,28 @@
import android.app.UiAutomation;
import android.content.ContentResolver;
import android.content.Context;
+import android.media.AudioManager;
+import android.media.AudioPlaybackConfiguration;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.provider.Settings;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import java.util.Scanner;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
public class Utils {
+ private static final String TAG = "CtsMediaTestUtil";
+ private static final int TEST_TIMING_TOLERANCE_MS = 50;
+
public static void enableAppOps(String packageName, String operation,
Instrumentation instrumentation) {
setAppOps(packageName, operation, instrumentation, true);
@@ -113,4 +126,53 @@
}
uiAutomation.destroy();
}
+
+ /**
+ * Assert that a media playback is started and an active {@link AudioPlaybackConfiguration}
+ * is created once. The playback will be stopped immediately after that.
+ * <p>For a media session to receive media button events, an actual playback is needed.
+ */
+ static void assertMediaPlaybackStarted(Context context) {
+ final AudioManager am = new AudioManager(context);
+ final HandlerThread handlerThread = new HandlerThread(TAG);
+ handlerThread.start();
+ final TestAudioPlaybackCallback callback = new TestAudioPlaybackCallback();
+ MediaPlayer mediaPlayer = null;
+
+ try {
+ final int activeConfigSizeBeforeStart = am.getActivePlaybackConfigurations().size();
+ final Handler handler = new Handler(handlerThread.getLooper());
+
+ am.registerAudioPlaybackCallback(callback, handler);
+ mediaPlayer = MediaPlayer.create(context, R.raw.sine1khzs40dblong);
+ mediaPlayer.start();
+ if (!callback.mCountDownLatch.await(TEST_TIMING_TOLERANCE_MS, TimeUnit.MILLISECONDS)
+ || callback.mActiveConfigSize != activeConfigSizeBeforeStart + 1) {
+ Assert.fail("Failed to create an active AudioPlaybackConfiguration");
+ }
+ } catch (InterruptedException e) {
+ Assert.fail("Failed to create an active AudioPlaybackConfiguration");
+ } finally {
+ am.unregisterAudioPlaybackCallback(callback);
+ if (mediaPlayer != null) {
+ mediaPlayer.stop();
+ mediaPlayer.release();
+ mediaPlayer = null;
+ }
+ handlerThread.quitSafely();
+ }
+ }
+
+ private static class TestAudioPlaybackCallback extends AudioManager.AudioPlaybackCallback {
+ private final CountDownLatch mCountDownLatch = new CountDownLatch(1);
+ private int mActiveConfigSize;
+
+ @Override
+ public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
+ // For non-framework apps, only anonymized active AudioPlaybackCallbacks will be
+ // notified.
+ mActiveConfigSize = configs.size();
+ mCountDownLatch.countDown();
+ }
+ }
}
diff --git a/tests/tests/nativemedia/aaudio/Android.mk b/tests/tests/nativemedia/aaudio/Android.mk
index af46aee..e37df49 100644
--- a/tests/tests/nativemedia/aaudio/Android.mk
+++ b/tests/tests/nativemedia/aaudio/Android.mk
@@ -27,7 +27,9 @@
frameworks/av/media/libaaudio/include
LOCAL_SRC_FILES := \
- src/test_aaudio.cpp
+ src/test_aaudio.cpp \
+ src/test_aaudio_misc.cpp \
+ src/test_aaudio_callback.cpp
LOCAL_SHARED_LIBRARIES := \
libaaudio \
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
index 77c91e4..37b434e 100644
--- a/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.cpp
@@ -21,17 +21,9 @@
#include <utils/Log.h>
#include <aaudio/AAudio.h>
-#include <aaudio/AAudioDefinitions.h>
+#include "test_aaudio.h"
-
-#define NANOS_PER_MICROSECOND ((int64_t)1000)
-#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
-#define MILLIS_PER_SECOND 1000
-#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * MILLIS_PER_SECOND)
-
-#define DEFAULT_STATE_TIMEOUT (500 * NANOS_PER_MILLISECOND)
-
-static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
+int64_t getNanoseconds(clockid_t clockId) {
struct timespec time;
int result = clock_gettime(clockId, &time);
if (result < 0) {
@@ -136,10 +128,12 @@
// Check to see what kind of stream we actually got.
actualSampleRate = AAudioStream_getSampleRate(aaudioStream);
- ASSERT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000); // TODO what is range?
+ ASSERT_GE(actualSampleRate, 44100);
+ ASSERT_LE(actualSampleRate, 96000); // TODO what is min/max?
actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(aaudioStream);
- ASSERT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?
+ ASSERT_GE(actualSamplesPerFrame, 1);
+ ASSERT_LE(actualSamplesPerFrame, 16); // TODO what is min/max?
actualSharingMode = AAudioStream_getSharingMode(aaudioStream);
ASSERT_TRUE(actualSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
@@ -151,7 +145,8 @@
// ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(aaudioStream));
framesPerBurst = AAudioStream_getFramesPerBurst(aaudioStream);
- ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
+ ASSERT_GE(framesPerBurst, 16);
+ ASSERT_LE(framesPerBurst, 10000); // TODO what is min/max?
// Allocate a buffer for the audio data.
// TODO handle possibility of other data formats
@@ -270,10 +265,13 @@
aaudioFramesRead = AAudioStream_getFramesRead(aaudioStream);
EXPECT_EQ(aaudioFramesRead, aaudioFramesWritten);
+ sleep(1); // FIXME - The write returns 0 if we remove this sleep! Why?
+
// The buffer should be empty after a flush so we should be able to write.
framesWritten = AAudioStream_write(aaudioStream, data, framesPerBurst, timeoutNanos);
// There should be some room for priming the buffer.
- ASSERT_TRUE(framesWritten > 0 && framesWritten <= framesPerBurst);
+ ASSERT_GT(framesWritten, 0);
+ ASSERT_LE(framesWritten, framesPerBurst);
EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
free(data);
@@ -291,60 +289,6 @@
}
*/
-#define AAUDIO_THREAD_ANSWER 1826375
-#define AAUDIO_THREAD_DURATION_MSEC 500
-
-static void *TestAAudioStreamThreadProc(void *arg) {
- AAudioStream* aaudioStream = (AAudioStream*) reinterpret_cast<size_t>(arg);
- aaudio_stream_state_t state;
-
- // Use this to sleep by waiting for something that won't happen.
- state = AAudioStream_getState(aaudioStream);
- AAudioStream_waitForStateChange(aaudioStream, AAUDIO_STREAM_STATE_PAUSED, &state,
- AAUDIO_THREAD_DURATION_MSEC * NANOS_PER_MILLISECOND);
- return reinterpret_cast<void *>(AAUDIO_THREAD_ANSWER);
-}
-
-// Test creating a stream related thread.
-TEST(test_aaudio, aaudio_stream_thread_basic) {
- AAudioStreamBuilder *aaudioBuilder = nullptr;
- AAudioStream *aaudioStream = nullptr;
- aaudio_result_t result = AAUDIO_OK;
- void *threadResult;
-
- // Use an AAudioStreamBuilder to define the stream.
- result = AAudio_createStreamBuilder(&aaudioBuilder);
- ASSERT_EQ(AAUDIO_OK, result);
-
- // Create an AAudioStream using the Builder.
- ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(aaudioBuilder, &aaudioStream));
-
- // Start a thread.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_createThread(aaudioStream,
- 10 * NANOS_PER_MILLISECOND,
- TestAAudioStreamThreadProc,
- reinterpret_cast<void *>(aaudioStream)));
- // Thread already started.
- ASSERT_NE(AAUDIO_OK, AAudioStream_createThread(aaudioStream, // should fail!
- 10 * NANOS_PER_MILLISECOND,
- TestAAudioStreamThreadProc,
- reinterpret_cast<void *>(aaudioStream)));
-
- // Wait for the thread to finish.
- ASSERT_EQ(AAUDIO_OK, AAudioStream_joinThread(aaudioStream,
- &threadResult, 2 * AAUDIO_THREAD_DURATION_MSEC * NANOS_PER_MILLISECOND));
- // The thread returns a special answer.
- ASSERT_EQ(AAUDIO_THREAD_ANSWER, (int)reinterpret_cast<size_t>(threadResult));
-
- // Thread should already be joined.
- ASSERT_NE(AAUDIO_OK, AAudioStream_joinThread(aaudioStream, // should fail!
- &threadResult, 2 * AAUDIO_THREAD_DURATION_MSEC * NANOS_PER_MILLISECOND));
-
- // Cleanup
- EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(aaudioBuilder));
- EXPECT_EQ(AAUDIO_OK, AAudioStream_close(aaudioStream));
-}
-
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio.h b/tests/tests/nativemedia/aaudio/src/test_aaudio.h
new file mode 100644
index 0000000..dbb111d
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef CTS_MEDIA_TEST_AAUDIO_H
+#define CTS_MEDIA_TEST_AAUDIO_H
+
+#define NANOS_PER_MICROSECOND ((int64_t)1000)
+#define NANOS_PER_MILLISECOND (NANOS_PER_MICROSECOND * 1000)
+#define MILLIS_PER_SECOND 1000
+#define NANOS_PER_SECOND (NANOS_PER_MILLISECOND * MILLIS_PER_SECOND)
+
+#define DEFAULT_STATE_TIMEOUT (500 * NANOS_PER_MILLISECOND)
+
+int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC);
+
+#endif //CTS_MEDIA_TEST_AAUDIO_H
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
new file mode 100644
index 0000000..2ec1e1c
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_callback.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AAudioTest"
+
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+#include <aaudio/AAudio.h>
+#include "test_aaudio.h"
+
+typedef struct AAudioCallbackTestData {
+ int32_t callbackCount;
+ int32_t expectedFramesPerCallback;
+ int32_t actualFramesPerCallback;
+} AAudioCallbackTestData;
+
+// Callback function that fills the audio output buffer.
+static aaudio_data_callback_result_t MyDataCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames
+) {
+ AAudioCallbackTestData *myData = (AAudioCallbackTestData *) userData;
+
+ if (numFrames != myData->expectedFramesPerCallback) {
+ // record unexpected framecounts
+ myData->actualFramesPerCallback = numFrames;
+ } else if (myData->actualFramesPerCallback == 0) {
+ // record at least one frame count
+ myData->actualFramesPerCallback = numFrames;
+ }
+ int32_t samplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+ int32_t numSamples = samplesPerFrame * numFrames;
+ if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_I16) {
+ int16_t *shortData = (int16_t *) audioData;
+ for (int i = 0; i < numSamples; i++) *shortData++ = 0;
+ } else if (AAudioStream_getFormat(stream) == AAUDIO_FORMAT_PCM_FLOAT) {
+ float *floatData = (float *) audioData;
+ for (int i = 0; i < numSamples; i++) *floatData++ = 0.0f;
+ }
+ myData->callbackCount++;
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+}
+
+// Test Writing to an AAudioStream using a Callback
+void runtest_aaudio_callback(aaudio_sharing_mode_t requestedSharingMode,
+ int32_t framesPerDataCallback) {
+ AAudioCallbackTestData myTestData = { 0, 0, 0 };
+ const int32_t requestedSampleRate = 48000;
+ const int32_t requestedSamplesPerFrame = 2;
+ const aaudio_audio_format_t requestedDataFormat = AAUDIO_FORMAT_PCM_I16;
+
+ int32_t actualSampleRate = -1;
+ int32_t actualSamplesPerFrame = -1;
+ aaudio_audio_format_t actualDataFormat = AAUDIO_FORMAT_INVALID;
+ aaudio_sharing_mode_t actualSharingMode;
+ int32_t framesPerBurst = -1;
+ int32_t actualBufferSize = 0;
+ int32_t actualFramesPerDataCallback = 0;
+
+ aaudio_stream_state_t state = AAUDIO_STREAM_STATE_UNINITIALIZED;
+ AAudioStreamBuilder *builder = nullptr;
+ AAudioStream *stream = nullptr;
+
+ aaudio_result_t result = AAUDIO_OK;
+
+ // Use an AAudioStreamBuilder to define the stream.
+ result = AAudio_createStreamBuilder(&builder);
+ ASSERT_EQ(AAUDIO_OK, result);
+
+ // Request stream properties.
+ AAudioStreamBuilder_setDeviceId(builder, AAUDIO_DEVICE_UNSPECIFIED);
+ AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
+ AAudioStreamBuilder_setSampleRate(builder, requestedSampleRate);
+ AAudioStreamBuilder_setSamplesPerFrame(builder, requestedSamplesPerFrame);
+ AAudioStreamBuilder_setFormat(builder, requestedDataFormat);
+ AAudioStreamBuilder_setSharingMode(builder, requestedSharingMode);
+ AAudioStreamBuilder_setBufferCapacityInFrames(builder, 2000);
+
+ AAudioStreamBuilder_setDataCallback(builder, MyDataCallbackProc, &myTestData);
+ if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+ AAudioStreamBuilder_setFramesPerDataCallback(builder, framesPerDataCallback);
+ }
+
+ // Create an AAudioStream using the Builder.
+ ASSERT_EQ(AAUDIO_OK, AAudioStreamBuilder_openStream(builder, &stream));
+ EXPECT_EQ(AAUDIO_OK, AAudioStreamBuilder_delete(builder));
+
+ EXPECT_EQ(AAUDIO_STREAM_STATE_OPEN, AAudioStream_getState(stream));
+ EXPECT_EQ(AAUDIO_DIRECTION_OUTPUT, AAudioStream_getDirection(stream));
+
+ // Check to see what kind of stream we actually got.
+ actualSampleRate = AAudioStream_getSampleRate(stream);
+ ASSERT_TRUE(actualSampleRate >= 44100 && actualSampleRate <= 96000); // TODO what is range?
+
+ actualSamplesPerFrame = AAudioStream_getSamplesPerFrame(stream);
+ ASSERT_TRUE(actualSamplesPerFrame >= 1 && actualSamplesPerFrame <= 16); // TODO what is max?
+
+ actualSharingMode = AAudioStream_getSharingMode(stream);
+ ASSERT_TRUE(actualSharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE
+ || actualSharingMode == AAUDIO_SHARING_MODE_SHARED);
+
+ actualDataFormat = AAudioStream_getFormat(stream);
+
+ // TODO test this on full build
+ // ASSERT_NE(AAUDIO_DEVICE_UNSPECIFIED, AAudioStream_getDeviceId(stream));
+
+ framesPerBurst = AAudioStream_getFramesPerBurst(stream);
+ ASSERT_TRUE(framesPerBurst >= 16 && framesPerBurst <= 1024); // TODO what is min/max?
+
+ actualFramesPerDataCallback = AAudioStream_getFramesPerDataCallback(stream);
+ if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+ ASSERT_EQ(framesPerDataCallback, actualFramesPerDataCallback);
+ }
+
+ actualBufferSize = AAudioStream_getBufferSizeInFrames(stream);
+ actualBufferSize = AAudioStream_setBufferSizeInFrames(stream, actualBufferSize);
+ ASSERT_TRUE(actualBufferSize > 0);
+
+ // Start/stop more than once to see if it fails after the first time.
+ // Write some data and measure the rate to see if the timing is OK.
+ for (int loopIndex = 0; loopIndex < 2; loopIndex++) {
+ myTestData.callbackCount = 0;
+ myTestData.expectedFramesPerCallback = actualFramesPerDataCallback;
+
+ // Start and wait for server to respond.
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStart(stream));
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
+ AAUDIO_STREAM_STATE_STARTING,
+ &state,
+ DEFAULT_STATE_TIMEOUT));
+ EXPECT_EQ(AAUDIO_STREAM_STATE_STARTED, state);
+
+ sleep(2);
+
+ // For more coverage, alternate pausing and stopping.
+ if ((loopIndex & 1) == 0) {
+ // Request async pause and wait for server to say that it has completed the request.
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestPause(stream));
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
+ AAUDIO_STREAM_STATE_PAUSING,
+ &state,
+ DEFAULT_STATE_TIMEOUT));
+ EXPECT_EQ(AAUDIO_STREAM_STATE_PAUSED, state);
+ } else {
+ // Request async stop and wait for server to say that it has completed the request.
+ ASSERT_EQ(AAUDIO_OK, AAudioStream_requestStop(stream));
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_waitForStateChange(stream,
+ AAUDIO_STREAM_STATE_STOPPING,
+ &state,
+ DEFAULT_STATE_TIMEOUT));
+ EXPECT_EQ(AAUDIO_STREAM_STATE_STOPPED, state);
+ }
+
+ int32_t oldCallbackCount = myTestData.callbackCount;
+ EXPECT_GT(oldCallbackCount, 10);
+ sleep(1);
+ EXPECT_EQ(oldCallbackCount, myTestData.callbackCount); // expect not advancing
+
+ if (framesPerDataCallback != AAUDIO_UNSPECIFIED) {
+ ASSERT_EQ(framesPerDataCallback, myTestData.actualFramesPerCallback);
+ }
+ }
+
+ EXPECT_EQ(AAUDIO_OK, AAudioStream_close(stream));
+}
+
+// Test Using an AAudioStream callback in SHARED mode.
+
+TEST(test_aaudio, aaudio_callback_shared_unspecified) {
+runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, AAUDIO_UNSPECIFIED);
+}
+
+TEST(test_aaudio, aaudio_callback_shared_109) {
+runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 109); // arbitrary prime number < 192
+}
+
+TEST(test_aaudio, aaudio_callback_shared_223) {
+runtest_aaudio_callback(AAUDIO_SHARING_MODE_SHARED, 223); // arbitrary prime number > 192
+}
diff --git a/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
new file mode 100644
index 0000000..a26f17a
--- /dev/null
+++ b/tests/tests/nativemedia/aaudio/src/test_aaudio_misc.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "AAudioTest"
+#include <utils/Log.h>
+
+#include <gtest/gtest.h>
+
+#include <aaudio/AAudio.h>
+
+// Make sure enums do not change value.
+TEST(test_aaudio_misc, aaudio_freeze_enums) {
+
+ ASSERT_EQ(0, AAUDIO_DIRECTION_OUTPUT);
+ ASSERT_EQ(1, AAUDIO_DIRECTION_INPUT);
+
+ ASSERT_EQ(-1, AAUDIO_FORMAT_INVALID);
+ ASSERT_EQ(0, AAUDIO_FORMAT_UNSPECIFIED);
+ ASSERT_EQ(1, AAUDIO_FORMAT_PCM_I16);
+ ASSERT_EQ(2, AAUDIO_FORMAT_PCM_FLOAT);
+ ASSERT_EQ(3, AAUDIO_FORMAT_PCM_I8_24);
+ ASSERT_EQ(4, AAUDIO_FORMAT_PCM_I32);
+
+ ASSERT_EQ(0, AAUDIO_OK);
+ ASSERT_EQ(-900, AAUDIO_ERROR_BASE);
+ ASSERT_EQ(-899, AAUDIO_ERROR_DISCONNECTED);
+ ASSERT_EQ(-898, AAUDIO_ERROR_ILLEGAL_ARGUMENT);
+ ASSERT_EQ(-897, AAUDIO_ERROR_INCOMPATIBLE);
+ ASSERT_EQ(-896, AAUDIO_ERROR_INTERNAL);
+ ASSERT_EQ(-895, AAUDIO_ERROR_INVALID_STATE);
+ ASSERT_EQ(-894, AAUDIO_ERROR_UNEXPECTED_STATE);
+ ASSERT_EQ(-893, AAUDIO_ERROR_UNEXPECTED_VALUE);
+ ASSERT_EQ(-892, AAUDIO_ERROR_INVALID_HANDLE);
+ ASSERT_EQ(-891, AAUDIO_ERROR_INVALID_QUERY);
+ ASSERT_EQ(-890, AAUDIO_ERROR_UNIMPLEMENTED);
+ ASSERT_EQ(-889, AAUDIO_ERROR_UNAVAILABLE);
+ ASSERT_EQ(-888, AAUDIO_ERROR_NO_FREE_HANDLES);
+ ASSERT_EQ(-887, AAUDIO_ERROR_NO_MEMORY);
+ ASSERT_EQ(-886, AAUDIO_ERROR_NULL);
+ ASSERT_EQ(-885, AAUDIO_ERROR_TIMEOUT);
+ ASSERT_EQ(-884, AAUDIO_ERROR_WOULD_BLOCK);
+ ASSERT_EQ(-883, AAUDIO_ERROR_INVALID_FORMAT);
+ ASSERT_EQ(-882, AAUDIO_ERROR_OUT_OF_RANGE);
+ ASSERT_EQ(-881, AAUDIO_ERROR_NO_SERVICE);
+
+ ASSERT_EQ(0, AAUDIO_STREAM_STATE_UNINITIALIZED);
+ ASSERT_EQ(1, AAUDIO_STREAM_STATE_UNKNOWN);
+ ASSERT_EQ(2, AAUDIO_STREAM_STATE_OPEN);
+ ASSERT_EQ(3, AAUDIO_STREAM_STATE_STARTING);
+ ASSERT_EQ(4, AAUDIO_STREAM_STATE_STARTED);
+ ASSERT_EQ(5, AAUDIO_STREAM_STATE_PAUSING);
+ ASSERT_EQ(6, AAUDIO_STREAM_STATE_PAUSED);
+ ASSERT_EQ(7, AAUDIO_STREAM_STATE_FLUSHING);
+ ASSERT_EQ(8, AAUDIO_STREAM_STATE_FLUSHED);
+ ASSERT_EQ(9, AAUDIO_STREAM_STATE_STOPPING);
+ ASSERT_EQ(10, AAUDIO_STREAM_STATE_STOPPED);
+ ASSERT_EQ(11, AAUDIO_STREAM_STATE_CLOSING);
+ ASSERT_EQ(12, AAUDIO_STREAM_STATE_CLOSED);
+
+ ASSERT_EQ(0, AAUDIO_SHARING_MODE_EXCLUSIVE);
+ ASSERT_EQ(1, AAUDIO_SHARING_MODE_SHARED);
+
+ ASSERT_EQ(0, AAUDIO_CALLBACK_RESULT_CONTINUE);
+ ASSERT_EQ(1, AAUDIO_CALLBACK_RESULT_STOP);
+}
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 24871ca..83f087b 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -45,12 +45,15 @@
import com.android.internal.telephony.PhoneConstants;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.InetSocketAddress;
import java.util.HashMap;
+import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -74,6 +77,17 @@
"Host: " + TEST_HOST + "\r\n" +
"Connection: keep-alive\r\n\r\n";
+ // Base path for IPv6 sysctls
+ private static final String IPV6_SYSCTL_DIR = "/proc/sys/net/ipv6/conf";
+
+ // Expected values for MIN|MAX_PLEN.
+ private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN = 48;
+ private static final int IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN = 64;
+
+ // Expected values for RFC 7559 router soliciations.
+ // Maximum number of router solicitations to send. -1 means no limit.
+ private static final int IPV6_WIFI_ROUTER_SOLICITATIONS = -1;
+
// Action sent to ConnectivityActionReceiver when a network callback is sent via PendingIntent.
private static final String NETWORK_CALLBACK_ACTION =
"ConnectivityManagerTest.NetworkCallbackAction";
@@ -91,6 +105,7 @@
private PackageManager mPackageManager;
private final HashMap<Integer, NetworkConfig> mNetworks =
new HashMap<Integer, NetworkConfig>();
+ boolean mWifiConnectAttempted;
@Override
protected void setUp() throws Exception {
@@ -99,6 +114,7 @@
mCm = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
mPackageManager = mContext.getPackageManager();
+ mWifiConnectAttempted = false;
// Get com.android.internal.R.array.networkAttributes
int resId = mContext.getResources().getIdentifier("networkAttributes", "array", "android");
@@ -116,6 +132,27 @@
}
}
+ @Override
+ protected void tearDown() throws Exception {
+ // Return WiFi to its original disabled state after tests that explicitly connect.
+ if (mWifiConnectAttempted) {
+ disconnectFromWifi(null);
+ }
+ }
+
+ /**
+ * Make sure WiFi is connected to an access point if it is not already. If
+ * WiFi is enabled as a result of this function, it will be disabled
+ * automatically in tearDown().
+ */
+ private Network ensureWifiConnected() {
+ if (mWifiManager.isWifiEnabled()) {
+ return getWifiNetwork();
+ }
+ mWifiConnectAttempted = true;
+ return connectToWifi();
+ }
+
public void testIsNetworkTypeValid() {
assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
@@ -298,14 +335,10 @@
final TestNetworkCallback defaultTrackingCallback = new TestNetworkCallback();
mCm.registerDefaultNetworkCallback(defaultTrackingCallback);
- final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
Network wifiNetwork = null;
try {
- // Make sure WiFi is connected to an access point to start with.
- if (!previousWifiEnabledState) {
- connectToWifi();
- }
+ ensureWifiConnected();
// Now we should expect to get a network callback about availability of the wifi
// network even if it was already connected as a state-based action when the callback
@@ -321,11 +354,6 @@
} finally {
mCm.unregisterNetworkCallback(callback);
mCm.unregisterNetworkCallback(defaultTrackingCallback);
-
- // Return WiFi to its original enabled/disabled state.
- if (!previousWifiEnabledState) {
- disconnectFromWifi(wifiNetwork);
- }
}
}
@@ -357,13 +385,8 @@
// We will register for a WIFI network being available or lost.
mCm.registerNetworkCallback(makeWifiNetworkRequest(), pendingIntent);
- final boolean previousWifiEnabledState = mWifiManager.isWifiEnabled();
-
try {
- // Make sure WiFi is connected to an access point to start with.
- if (!previousWifiEnabledState) {
- connectToWifi();
- }
+ ensureWifiConnected();
// Now we expect to get the Intent delivered notifying of the availability of the wifi
// network even if it was already connected as a state-based action when the callback
@@ -376,11 +399,6 @@
mCm.unregisterNetworkCallback(pendingIntent);
pendingIntent.cancel();
mContext.unregisterReceiver(receiver);
-
- // Return WiFi to its original enabled/disabled state.
- if (!previousWifiEnabledState) {
- disconnectFromWifi(null);
- }
}
}
@@ -761,4 +779,42 @@
fail("No exception thrown when restricted network requested.");
} catch (SecurityException expected) {}
}
+
+ private Scanner makeWifiSysctlScanner(String key) throws FileNotFoundException {
+ Network network = ensureWifiConnected();
+ String iface = mCm.getLinkProperties(network).getInterfaceName();
+ String path = IPV6_SYSCTL_DIR + "/" + iface + "/" + key;
+ return new Scanner(new File(path));
+ }
+
+ /** Verify that accept_ra_rt_info_min_plen exists and is set to the expected value */
+ public void testAcceptRaRtInfoMinPlen() throws Exception {
+ Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_min_plen");
+ assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MIN_PLEN, s.nextInt());
+ }
+
+ /** Verify that accept_ra_rt_info_max_plen exists and is set to the expected value */
+ public void testAcceptRaRtInfoMaxPlen() throws Exception {
+ Scanner s = makeWifiSysctlScanner("accept_ra_rt_info_max_plen");
+ assertEquals(IPV6_WIFI_ACCEPT_RA_RT_INFO_MAX_PLEN, s.nextInt());
+ }
+
+ /** Verify that router_solicitations exists and is set to the expected value */
+ public void testRouterSolicitations() throws Exception {
+ Scanner s = makeWifiSysctlScanner("router_solicitations");
+ assertEquals(IPV6_WIFI_ROUTER_SOLICITATIONS, s.nextInt());
+ }
+
+ /** Verify that router_solicitation_max_interval exists and is in an acceptable interval */
+ public void testRouterSolicitationMaxInterval() throws Exception {
+ Scanner s = makeWifiSysctlScanner("router_solicitation_max_interval");
+ int interval = s.nextInt();
+ // Verify we're in the interval [15 minutes, 60 minutes]. Lower values may adversely
+ // impact battery life and higher values can decrease the probability of detecting
+ // network changes.
+ final int lowerBoundSec = 15 * 60;
+ final int upperBoundSec = 60 * 60;
+ assertTrue(lowerBoundSec <= interval);
+ assertTrue(interval <= upperBoundSec);
+ }
}
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
index 93b5c44..39d683d 100644
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
@@ -85,8 +85,7 @@
randomSpi =
mISM.reserveSecurityParameterIndex(
IpSecTransform.DIRECTION_OUT,
- addr,
- IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
+ addr);
assertTrue(randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
droidSpi =
@@ -121,8 +120,7 @@
IpSecManager.SecurityParameterIndex outSpi =
mISM.reserveSecurityParameterIndex(
IpSecTransform.DIRECTION_OUT,
- local,
- IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
+ local);
IpSecManager.SecurityParameterIndex inSpi =
mISM.reserveSecurityParameterIndex(
@@ -133,21 +131,21 @@
.setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
.setEncryption(
IpSecTransform.DIRECTION_OUT,
- new IpSecAlgorithm(IpSecAlgorithm.ALGO_CRYPT_AES_CBC, CRYPT_KEY))
+ new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
.setAuthentication(
IpSecTransform.DIRECTION_OUT,
new IpSecAlgorithm(
- IpSecAlgorithm.ALGO_AUTH_HMAC_SHA256,
+ IpSecAlgorithm.AUTH_HMAC_SHA256,
AUTH_KEY,
AUTH_KEY.length * 8))
.setSpi(IpSecTransform.DIRECTION_IN, inSpi)
.setEncryption(
IpSecTransform.DIRECTION_IN,
- new IpSecAlgorithm(IpSecAlgorithm.ALGO_CRYPT_AES_CBC, CRYPT_KEY))
+ new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
.setAuthentication(
IpSecTransform.DIRECTION_IN,
new IpSecAlgorithm(
- IpSecAlgorithm.ALGO_AUTH_HMAC_SHA256,
+ IpSecAlgorithm.AUTH_HMAC_SHA256,
AUTH_KEY,
CRYPT_KEY.length * 8))
.buildTransportModeTransform(local);
diff --git a/tests/tests/os/src/android/os/cts/AbiTest.java b/tests/tests/os/src/android/os/cts/AbiTest.java
index 49ff8aa..1765ae7 100644
--- a/tests/tests/os/src/android/os/cts/AbiTest.java
+++ b/tests/tests/os/src/android/os/cts/AbiTest.java
@@ -16,11 +16,14 @@
package android.os.cts;
+import android.system.OsConstants;
+import android.system.ErrnoException;
import android.util.ArraySet;
import com.android.compatibility.common.util.ReadElf;
import java.io.File;
+import java.io.IOException;
import java.util.Arrays;
import junit.framework.TestCase;
@@ -74,6 +77,14 @@
elf = ReadElf.read(f);
} catch (IllegalArgumentException ignored) {
// If it's not actually an ELF file, we don't care.
+ } catch (IOException ex) {
+ Throwable cause = ex.getCause();
+ if (cause instanceof ErrnoException) {
+ // if we are denied access to the file, ignore.
+ if (((ErrnoException) cause).errno != OsConstants.EACCES) {
+ throw ex;
+ }
+ }
} finally {
if (elf != null) {
elf.close();
diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
index 1db2d72..736e0f3 100644
--- a/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
+++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerTest.java
@@ -53,6 +53,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
import junit.framework.AssertionFailedError;
@@ -256,6 +257,32 @@
assertStorageVolumesEquals(primary, childVolume);
}
+ private void assertNoUuid(File file) {
+ try {
+ final UUID uuid = mStorageManager.getUuidForPath(file);
+ fail("Unexpected UUID " + uuid + " for " + file);
+ } catch (IOException expected) {
+ }
+ }
+
+ public void testGetUuidForPath() throws Exception {
+ assertEquals(StorageManager.UUID_DEFAULT,
+ mStorageManager.getUuidForPath(Environment.getDataDirectory()));
+ assertEquals(StorageManager.UUID_DEFAULT,
+ mStorageManager.getUuidForPath(mContext.getDataDir()));
+
+ final UUID extUuid = mStorageManager
+ .getUuidForPath(Environment.getExternalStorageDirectory());
+ if (Environment.isExternalStorageEmulated()) {
+ assertEquals(StorageManager.UUID_DEFAULT, extUuid);
+ }
+
+ assertEquals(extUuid, mStorageManager.getUuidForPath(mContext.getExternalCacheDir()));
+
+ assertNoUuid(new File("/"));
+ assertNoUuid(new File("/proc/"));
+ }
+
private static class TestProxyFileDescriptorCallback extends ProxyFileDescriptorCallback {
final byte[] bytes;
int fsyncCount;
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 4e6b9ea..949e2c1 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -1511,6 +1511,16 @@
<permission android:name="android.permission.DVB_DEVICE"
android:protectionLevel="signature|privileged" />
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by carrier state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
+ <!-- @SystemApi Allows reading and enabling/disabling the OEM unlock allowed by user state
+ @hide <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE"
+ android:protectionLevel="signature|privileged" />
+
<!-- @SystemApi Allows reading the OEM unlock state
@hide <p>Not for use by third-party applications. -->
<permission android:name="android.permission.READ_OEM_UNLOCK_STATE"
diff --git a/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java b/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
index e40f2ed..d8a80d2 100644
--- a/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
+++ b/tests/tests/provider/src/android/provider/cts/MediaStoreUiTest.java
@@ -131,6 +131,14 @@
}
}
+ private void maybeClick(UiSelector sel) {
+ try { mDevice.findObject(sel).click(); } catch (Throwable ignored) { }
+ }
+
+ private void maybeClick(BySelector sel) {
+ try { mDevice.findObject(sel).click(); } catch (Throwable ignored) { }
+ }
+
/**
* Verify that whoever handles {@link MediaStore#ACTION_IMAGE_CAPTURE} can
* correctly write the contents into a passed {@code content://} Uri.
@@ -164,7 +172,7 @@
+ pkg + " " + android.Manifest.permission.ACCESS_COARSE_LOCATION);
getInstrumentation().getUiAutomation().executeShellCommand("pm grant "
+ pkg + " " + android.Manifest.permission.ACCESS_FINE_LOCATION);
- Thread.sleep(1000);
+ SystemClock.sleep(DateUtils.SECOND_IN_MILLIS);
mActivity.startActivityForResult(intent, REQUEST_CODE);
mDevice.waitForIdle();
@@ -184,15 +192,27 @@
// Hrm, that didn't work; let's try an alternative approach of digging
// around for a shutter button
if (result == null) {
- mDevice.findObject(new UiSelector().resourceId(pkg + ":id/shutter_button")).click();
+ maybeClick(new UiSelector().resourceId(pkg + ":id/shutter_button"));
mDevice.waitForIdle();
SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
- mDevice.findObject(new UiSelector().resourceId(pkg + ":id/shutter_button")).click();
+ maybeClick(new UiSelector().resourceId(pkg + ":id/shutter_button"));
mDevice.waitForIdle();
+
+ result = mActivity.getResult(15, TimeUnit.SECONDS);
+ Log.d(TAG, "Second pass result was " + result);
}
- result = mActivity.getResult(15, TimeUnit.SECONDS);
- Log.d(TAG, "Second pass result was " + result);
+ // Grr, let's try hunting around even more
+ if (result == null) {
+ maybeClick(By.pkg(pkg).descContains("Capture"));
+ mDevice.waitForIdle();
+ SystemClock.sleep(5 * DateUtils.SECOND_IN_MILLIS);
+ maybeClick(By.pkg(pkg).descContains("Done"));
+ mDevice.waitForIdle();
+
+ result = mActivity.getResult(15, TimeUnit.SECONDS);
+ Log.d(TAG, "Third pass result was " + result);
+ }
assertNotNull("Expected to get a IMAGE_CAPTURE result; your camera app should "
+ "respond to the CAMERA and DPAD_CENTER keycodes", result);
diff --git a/tests/tests/security/src/android/security/cts/SeccompTest.java b/tests/tests/security/src/android/security/cts/SeccompTest.java
index 44185bd..745aa87 100644
--- a/tests/tests/security/src/android/security/cts/SeccompTest.java
+++ b/tests/tests/security/src/android/security/cts/SeccompTest.java
@@ -67,6 +67,30 @@
}
}
+ public void testCTSSwapOnOffBlocked() {
+ if (CpuFeatures.isArm64Cpu()) {
+ testBlocked(224); // __NR_swapon
+ testBlocked(225); // __NR_swapoff
+ } else if (CpuFeatures.isArmCpu()) {
+ testBlocked(87); // __NR_swapon
+ testBlocked(115); // __NR_swapoff
+ } else if (CpuFeatures.isX86_64Cpu()) {
+ testBlocked(167); // __NR_swapon
+ testBlocked(168); // __NR_swapoff
+ } else if (CpuFeatures.isX86Cpu()) {
+ testBlocked(87); // __NR_swapon
+ testBlocked(115); // __NR_swapoff
+ } else if (CpuFeatures.isMips64Cpu()) {
+ testBlocked(5162); // __NR_swapon
+ testBlocked(5163); // __NR_swapoff
+ } else if (CpuFeatures.isMipsCpu()) {
+ testBlocked(4087); // __NR_swapon
+ testBlocked(4115); // __NR_swapoff
+ } else {
+ fail("Unsupported OS");
+ }
+ }
+
private void testBlocked(int nr) {
assertTrue("Syscall " + nr + " allowed", testSyscallBlocked(nr));
}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 199c63b..c458ffd 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -617,6 +617,7 @@
codec.release();
}
}
+ ex.unselectTrack(t);
}
ex.release();
String cve = rname.replace("_", "-").toUpperCase();
diff --git a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
index 420bba1..c01a173 100644
--- a/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/TelephonyManagerTest.java
@@ -555,7 +555,47 @@
fail("Expected SecurityException. App does not have carrier privileges or is not the "
+ "default dialer app");
} catch (SecurityException expected) {
+ }
+ }
+ /**
+ * Tests that the device properly reports the contents of EF_FPLMN or null
+ */
+ @Test
+ public void testGetForbiddenPlmns() {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ return;
+ }
+ String[] plmns = mTelephonyManager.getForbiddenPlmns();
+
+ int phoneType = mTelephonyManager.getPhoneType();
+ switch (phoneType) {
+ case TelephonyManager.PHONE_TYPE_GSM:
+ assertNotNull("Forbidden PLMNs must be valid or an empty list!", plmns);
+ case TelephonyManager.PHONE_TYPE_CDMA:
+ case TelephonyManager.PHONE_TYPE_NONE:
+ if (plmns == null) {
+ return;
+ }
+ }
+
+ for(String plmn : plmns) {
+ if (plmn.length() > 6 || plmn.length() < 5) {
+ fail("Invalid Length for PLMN-ID, must be 5 or 6: " + plmn);
+ }
+
+ // A record which is written in the SIM but empty will
+ // be all f's
+ if(android.text.TextUtils.isDigitsOnly(plmn)) {
+ assertTrue(
+ "PLMNs must be strings of digits 0-9,F! " + plmn,
+ android.text.TextUtils.isDigitsOnly(plmn));
+ } else {
+ for (char c : plmn.toUpperCase().toCharArray()) {
+ assertTrue("PLMNs must be strings of digits 0-9,F! " + plmn,
+ Character.toUpperCase(c) == 'F');
+ }
+ }
}
}
diff --git a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
index ae8ab8d..1e766ba 100644
--- a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -348,6 +348,10 @@
}
public void testFilter_originatingNumber_match_filtered() {
+ if (!hasTelephony(mContext)) {
+ Log.d(TAG, "skipping test that requires telephony feature");
+ return;
+ }
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setOriginatingNumbers(Arrays.asList(mPhoneNumber))
@@ -357,6 +361,10 @@
}
public void testFilter_originatingNumber_mismatch_notFiltered() {
+ if (!hasTelephony(mContext)) {
+ Log.d(TAG, "skipping test that requires telephony feature");
+ return;
+ }
VisualVoicemailSmsFilterSettings settings = new VisualVoicemailSmsFilterSettings.Builder()
.setClientPrefix("//CTSVVM")
.setOriginatingNumbers(Arrays.asList("1"))
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
index 9dca58f..308e750 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutTest.java
@@ -1196,8 +1196,8 @@
assertEquals(0, layout.getLineForOffset(lineBreakOffset - 1));
assertEquals(0, layout.getOffsetForHorizontal(0, 0.0f));
- assertEquals(lineBreakOffset, layout.getOffsetForHorizontal(0, width));
- assertEquals(lineBreakOffset, layout.getOffsetForHorizontal(0, width * 2));
+ assertEquals(lineBreakOffset - 2, layout.getOffsetForHorizontal(0, width));
+ assertEquals(lineBreakOffset - 2, layout.getOffsetForHorizontal(0, width * 2));
final int lineCount = layout.getLineCount();
assertEquals(testString.length(), layout.getOffsetForHorizontal(lineCount - 1, width));
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
index 0b28d05..578591c 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvContractTest.java
@@ -426,7 +426,6 @@
ContentValues baseValues = createDummyChannelValues(mInputId, false);
Uri channelUri = mContentResolver.insert(mChannelsUri, baseValues);
- final String COLUMN_SYSTEM_APPROVED = "system_approved";
// Test: insert
ContentValues values = new ContentValues(baseValues);
@@ -438,14 +437,6 @@
// Expected.
}
values = new ContentValues(baseValues);
- values.put(COLUMN_SYSTEM_APPROVED, 1);
- try {
- mContentResolver.insert(mChannelsUri, values);
- fail("'" + COLUMN_SYSTEM_APPROVED + "' should be read-only.");
- } catch (Exception e) {
- // Expected.
- }
- values = new ContentValues(baseValues);
values.put(Channels.COLUMN_LOCKED, 1);
try {
mContentResolver.insert(mChannelsUri, values);
@@ -464,14 +455,6 @@
// Expected.
}
values = new ContentValues(baseValues);
- values.put(COLUMN_SYSTEM_APPROVED, 1);
- try {
- mContentResolver.update(channelUri, values, null, null);
- fail("'" + COLUMN_SYSTEM_APPROVED + "' should be read-only.");
- } catch (Exception e) {
- // Expected.
- }
- values = new ContentValues(baseValues);
values.put(Channels.COLUMN_LOCKED, 1);
try {
mContentResolver.update(channelUri, values, null, null);
@@ -716,6 +699,14 @@
Uri programUri = TvContract.buildPreviewProgramUri(programId);
verifyPreviewProgram(programUri, values, programId);
+ values.remove(PreviewPrograms.COLUMN_TYPE);
+ try {
+ mContentResolver.insert(previewProgramsUri, values);
+ fail("Type should be a required column.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
// Test: update
values.put(PreviewPrograms.COLUMN_EPISODE_TITLE, "Sample title");
values.put(PreviewPrograms.COLUMN_SHORT_DESCRIPTION, "Short description");
@@ -743,6 +734,14 @@
Uri programUri = TvContract.buildWatchNextProgramUri(programId);
verifyWatchNextProgram(programUri, values, programId);
+ values.remove(WatchNextPrograms.COLUMN_TYPE);
+ try {
+ mContentResolver.insert(watchNextProgramsUri, values);
+ fail("Type should be a required column.");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
// Test: update
values.put(WatchNextPrograms.COLUMN_EPISODE_TITLE, "Sample title");
values.put(WatchNextPrograms.COLUMN_SHORT_DESCRIPTION, "Short description");
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
index e3d56ba..95c222c3 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/AutofillHighlightTests.java
@@ -20,14 +20,17 @@
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class AutofillHighlightTests extends ActivityTestBase {
@Test
public void testHighlightedFrameLayout() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
index 77ff8f2..d705c7e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapFilterTests.java
@@ -20,6 +20,7 @@
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.bitmapverifiers.PerPixelBitmapVerifier;
@@ -27,8 +28,10 @@
import android.uirendering.cts.testinfrastructure.CanvasClient;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class BitmapFilterTests extends ActivityTestBase {
private static final int WHITE_WEIGHT = 255 * 3;
private enum FilterEnum {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
index d9b8d7f..789d8d5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/BitmapTests.java
@@ -24,6 +24,7 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Handler;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
@@ -41,7 +42,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-@MediumTest
+@LargeTest
@RunWith(AndroidJUnit4.class)
public class BitmapTests extends ActivityTestBase {
class BitmapView extends View {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
index d9eec30..16f98f6 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/CanvasStateTests.java
@@ -26,11 +26,13 @@
import android.graphics.RectF;
import android.graphics.Region;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.util.DisplayMetrics;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Tests of state query-able from canvas at draw time.
@@ -39,6 +41,7 @@
* capability to test the hardware accelerated Canvas in the way that it is used by Views.
*/
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class CanvasStateTests extends ActivityTestBase {
@Test
public void testClipRectReturnValues() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
index bbc50df..5d875ab 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorFilterAlphaTest.java
@@ -22,17 +22,19 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
-import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import java.util.List;
-@LargeTest // large while non-parameterized
-//@RunWith(Parameterized.class) // TODO: Reenable when CTS supports parameterized tests
+@MediumTest
+@RunWith(Parameterized.class)
public class ColorFilterAlphaTest extends ActivityTestBase {
// We care about one point in each of the four rectangles of different alpha values, as well as
// the area outside the rectangles
@@ -85,12 +87,16 @@
0xFFC21A1A, 0xFFC93333, 0xFFD04D4D, 0xFFD66666, 0xFFBB0000 } },
};
- //@Parameterized.Parameters(name = "{0}")
+ @Parameterized.Parameters(name = "{0}")
public static List<XfermodeTest.Config> configs() {
return XfermodeTest.configs(MODES_AND_EXPECTED_COLORS);
}
- private XfermodeTest.Config mConfig;
+ private final XfermodeTest.Config mConfig;
+
+ public ColorFilterAlphaTest(XfermodeTest.Config config) {
+ mConfig = config;
+ }
private static final int[] BLOCK_COLORS = new int[] {
0x33808080,
@@ -127,12 +133,9 @@
@Test
public void test() {
- for (XfermodeTest.Config config : configs()) {
- mConfig = config;
- createTest()
- .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
- .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
- }
+ createTest()
+ .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
+ .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
}
}
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java
index c5aa1b3..13c8e91 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ColorSpaceTests.java
@@ -31,16 +31,19 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ColorSpaceTests extends ActivityTestBase {
private Bitmap mMask;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index 444af9f..304303a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -25,6 +25,7 @@
import android.graphics.Rect;
import android.graphics.drawable.NinePatchDrawable;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.bitmapcomparers.ExactComparer;
@@ -35,8 +36,10 @@
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ExactCanvasTests extends ActivityTestBase {
private final BitmapComparer mExactComparer = new ExactComparer();
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
index 2a2ec51..ea7403b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/FontRenderingTests.java
@@ -22,6 +22,7 @@
import android.graphics.Paint;
import android.graphics.Typeface;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
@@ -29,8 +30,10 @@
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class FontRenderingTests extends ActivityTestBase {
// Thresholds are barely loose enough for differences between sw and hw renderers.
private static final double REGULAR_THRESHOLD = 0.92;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java
index e808296..4b8b6b2 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/GradientTests.java
@@ -22,11 +22,14 @@
import android.graphics.Point;
import android.graphics.Shader;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class GradientTests extends ActivityTestBase {
@Test
public void testAlphaPreMultiplication() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
index 00b61e9..c62e134 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/HardwareBitmapTests.java
@@ -28,6 +28,7 @@
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.graphics.Bitmap;
@@ -41,11 +42,13 @@
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class HardwareBitmapTests extends ActivityTestBase {
private Resources mRes;
@@ -82,7 +85,7 @@
HARDWARE_OPTIONS);
canvas.drawBitmap(hardwareBitmap, 0, 0, new Paint());
}, true).runWithVerifier(new GoldenImageVerifier(getActivity(),
- R.drawable.golden_headless_robot, new ExactComparer()));
+ R.drawable.golden_headless_robot, new MSSIMComparer(0.95)));
}
@Test
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index f952bc2..ee46601 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -18,7 +18,9 @@
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
@@ -28,8 +30,10 @@
import android.uirendering.cts.testinfrastructure.ViewInitializer;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class InfrastructureTests extends ActivityTestBase {
@Test
@@ -45,6 +49,7 @@
* by verifying that two paths that should render differently *do* render
* differently.
*/
+ @LargeTest
@Test
public void testRenderSpecIsolation() {
CanvasClient canvasClient = (canvas, width, height) -> {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
index f7661a5..ed0110a 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayerTests.java
@@ -32,6 +32,7 @@
import android.graphics.Rect;
import android.graphics.Region.Op;
import android.support.annotation.ColorInt;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
@@ -140,6 +141,7 @@
.runWithVerifier(new ColorVerifier(expectedColor));
}
+ @LargeTest
@Test
public void testLayerClear() {
ViewInitializer initializer = new ViewInitializer() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
index c0323b6..3d1c10e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/LayoutTests.java
@@ -18,14 +18,17 @@
import android.graphics.Color;
import android.graphics.Rect;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class LayoutTests extends ActivityTestBase {
@Test
public void testSimpleRedLayout() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
index 6eaba8f..ae4fee1 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathClippingTests.java
@@ -24,7 +24,9 @@
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Typeface;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
@@ -38,10 +40,12 @@
import android.webkit.WebView;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class PathClippingTests extends ActivityTestBase {
// draw circle with hole in it, with stroked circle
static final CanvasClient sTorusDrawCanvasClient = (canvas, width, height) -> {
@@ -173,6 +177,7 @@
};
}
+ @LargeTest
@Test
public void testWebViewClipWithCircle() {
if (!getActivity().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java
index 5abe831..2d5acaa 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PathTests.java
@@ -5,14 +5,17 @@
import android.graphics.Path;
import android.graphics.Typeface;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class PathTests extends ActivityTestBase {
private static final double REGULAR_THRESHOLD = 0.92;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
index c1e10d3..454eb2c0 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/PictureTest.java
@@ -22,13 +22,16 @@
import android.graphics.Picture;
import android.graphics.Rect;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class PictureTest extends ActivityTestBase {
private static final Rect sRect = new Rect(0, 0, 40, 40);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java
index 44831bf..d9ec2b5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/Rgba16fTests.java
@@ -25,16 +25,19 @@
import android.graphics.Point;
import android.graphics.Shader;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.IOException;
import java.io.InputStream;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class Rgba16fTests extends ActivityTestBase {
@Test
public void testTransferFunctions() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
index 2c9df73..252874d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShaderTests.java
@@ -27,14 +27,17 @@
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ShaderTests extends ActivityTestBase {
@Test
public void testSinglePixelBitmapShader() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
index e9b9bd4..e4f9809 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShadowTests.java
@@ -18,14 +18,17 @@
import android.graphics.Color;
import android.graphics.Point;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.util.CompareUtils;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ShadowTests extends ActivityTestBase {
private class GrayScaleVerifier extends SamplePointVerifier {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
index 9aad23d..0b708d4 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ShapeTests.java
@@ -17,14 +17,17 @@
package android.uirendering.cts.testclasses;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ShapeTests extends ActivityTestBase {
@Test
public void testDashedOval() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
index 52b87cc..741c35c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
@@ -24,7 +24,9 @@
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -40,10 +42,12 @@
import org.junit.Assert;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
-@MediumTest
+@LargeTest
+@RunWith(AndroidJUnit4.class)
public class SurfaceViewTests extends ActivityTestBase {
static final CanvasCallback sGreenCanvasCallback =
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
index c374dd7e..ff0e9a7 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SweepTests.java
@@ -22,7 +22,9 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.bitmapcomparers.BitmapComparer;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -31,11 +33,13 @@
import android.uirendering.cts.testinfrastructure.ResourceModifier;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Test cases of all combination of resource modifications.
*/
-@MediumTest
+@LargeTest
+@RunWith(AndroidJUnit4.class)
public class SweepTests extends ActivityTestBase {
private final static DisplayModifier COLOR_FILTER_GRADIENT_MODIFIER = new DisplayModifier() {
private final Rect mBounds = new Rect(30, 30, 150, 150);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java
index f220bfb..abbec36 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextureViewTests.java
@@ -27,6 +27,7 @@
import android.graphics.SurfaceTexture;
import android.support.annotation.ColorInt;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.ColorVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
@@ -42,10 +43,12 @@
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.util.concurrent.CountDownLatch;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class TextureViewTests extends ActivityTestBase {
private static SurfaceTexture sRedTexture;
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java
index 2a64ac4..ffb263d 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/VectorDrawableTests.java
@@ -26,8 +26,10 @@
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class VectorDrawableTests extends ActivityTestBase {
@Test
public void testScaleDown() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
index d74dcb7..88aa265 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewAnimationUtilsTests.java
@@ -17,6 +17,7 @@
package android.uirendering.cts.testclasses;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapcomparers.MSSIMComparer;
import android.uirendering.cts.bitmapverifiers.GoldenImageVerifier;
@@ -25,8 +26,10 @@
import android.view.ViewAnimationUtils;
import org.junit.Test;
+import org.junit.runner.RunWith;
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ViewAnimationUtilsTests extends ActivityTestBase {
@Test
public void testCreateCircularReveal() {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
index 47f9f4d..d1f0ee5 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ViewClippingTests.java
@@ -7,6 +7,7 @@
import android.graphics.Path;
import android.graphics.Rect;
import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
import android.uirendering.cts.R;
import android.uirendering.cts.bitmapverifiers.BitmapVerifier;
import android.uirendering.cts.bitmapverifiers.RectVerifier;
@@ -18,6 +19,7 @@
import android.view.ViewOutlineProvider;
import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* This tests view clipping by modifying properties of blue_padded_layout, and validating
@@ -26,6 +28,7 @@
* Since the layout is blue on a white background, this is always done with a RectVerifier.
*/
@MediumTest
+@RunWith(AndroidJUnit4.class)
public class ViewClippingTests extends ActivityTestBase {
static final Rect FULL_RECT = new Rect(0, 0, 90, 90);
static final Rect BOUNDS_RECT = new Rect(0, 0, 80, 80);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
index 04e1dfd..38a4d40 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
@@ -22,18 +22,20 @@
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
-import android.support.test.filters.LargeTest;
+import android.support.test.filters.MediumTest;
import android.uirendering.cts.bitmapverifiers.SamplePointVerifier;
import android.uirendering.cts.testinfrastructure.ActivityTestBase;
import android.uirendering.cts.testinfrastructure.CanvasClient;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import java.util.ArrayList;
import java.util.List;
-@LargeTest // large while non-parameterized
-//@RunWith(Parameterized.class) // TODO: Reenable when CTS supports parameterized tests
+@MediumTest
+@RunWith(Parameterized.class)
public class XfermodeTest extends ActivityTestBase {
/**
* There are 4 locations we care about in testing each filter:
@@ -124,12 +126,16 @@
BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR } },
};
- //@Parameterized.Parameters(name = "{0}")
+ @Parameterized.Parameters(name = "{0}")
public static List<Config> configs() {
return configs(MODES_AND_EXPECTED_COLORS);
}
- private Config mConfig;
+ private final Config mConfig;
+
+ public XfermodeTest(Config config) {
+ mConfig = config;
+ }
private CanvasClient mCanvasClient = new CanvasClient() {
final Paint mPaint = new Paint();
@@ -170,11 +176,8 @@
@Test
public void test() {
- for (XfermodeTest.Config config : configs()) {
- mConfig = config;
- createTest()
- .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
- .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
- }
+ createTest()
+ .addCanvasClient(mCanvasClient, mConfig.hardwareAccelerated)
+ .runWithVerifier(new SamplePointVerifier(TEST_POINTS, mConfig.expectedColors));
}
}
diff --git a/tests/tests/view/AndroidManifest.xml b/tests/tests/view/AndroidManifest.xml
index 8afec2c..5f50e9c 100644
--- a/tests/tests/view/AndroidManifest.xml
+++ b/tests/tests/view/AndroidManifest.xml
@@ -331,6 +331,13 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+
+ <activity android:name="android.view.cts.DefaultFocusHighlightCtsActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/view/res/drawable/scrollbar_no_size.xml b/tests/tests/view/res/drawable/scrollbar_no_size.xml
deleted file mode 100644
index 88a59f0..0000000
--- a/tests/tests/view/res/drawable/scrollbar_no_size.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@android:color/white" />
-</shape>
diff --git a/tests/tests/view/res/drawable/scrollbar_thumb.xml b/tests/tests/view/res/drawable/scrollbar_thumb.xml
deleted file mode 100644
index d7612ac..0000000
--- a/tests/tests/view/res/drawable/scrollbar_thumb.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@android:color/white" />
- <size
- android:width="@dimen/scrollbar_thumb_width"
- android:height="@dimen/scrollbar_thumb_height"/>
-</shape>
diff --git a/tests/tests/view/res/drawable/scrollbar_track.xml b/tests/tests/view/res/drawable/scrollbar_track.xml
deleted file mode 100644
index a184569..0000000
--- a/tests/tests/view/res/drawable/scrollbar_track.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@android:color/white" />
- <size
- android:width="@dimen/scrollbar_track_width"
- android:height="@dimen/scrollbar_track_height"/>
-</shape>
diff --git a/tests/tests/view/res/layout/default_focus_highlight_layout.xml b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
new file mode 100644
index 0000000..827de43
--- /dev/null
+++ b/tests/tests/view/res/layout/default_focus_highlight_layout.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (C) 2017 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <View
+ android:id="@+id/view"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"/>
+
+ <ListView
+ android:id="@+id/listview"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"/>
+
+ <EditText
+ android:id="@+id/edittext"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"
+ android:inputType="text"/>
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"/>
+
+ <LinearLayout
+ android:id="@+id/linearlayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ </LinearLayout>
+
+ <View
+ android:id="@+id/view_to_inflate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:defaultFocusHighlightEnabled="false"
+ android:text="@string/id_ok"/>
+
+ <ListView
+ android:id="@+id/listview_to_inflate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:defaultFocusHighlightEnabled="true"
+ android:text="@string/id_ok"/>
+
+ <EditText
+ android:id="@+id/edittext_to_inflate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/id_ok"
+ android:defaultFocusHighlightEnabled="true"
+ android:inputType="text"/>
+
+ <Button
+ android:id="@+id/button_to_inflate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:defaultFocusHighlightEnabled="false"
+ android:text="@string/id_ok"/>
+
+ <LinearLayout
+ android:id="@+id/linearlayout_to_inflate"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:defaultFocusHighlightEnabled="false"
+ android:orientation="vertical">
+ </LinearLayout>
+
+</LinearLayout>
+
diff --git a/tests/tests/view/res/layout/focus_finder_layout.xml b/tests/tests/view/res/layout/focus_finder_layout.xml
index 610ffc8..1dea684 100644
--- a/tests/tests/view/res/layout/focus_finder_layout.xml
+++ b/tests/tests/view/res/layout/focus_finder_layout.xml
@@ -19,7 +19,7 @@
<TableLayout android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_centerInParent="true">
+ android:layout_alignParentTop="true">
<TableRow>
<android.view.cts.TestButton android:id="@+id/top_left_button"
android:layout_width="60dp"
@@ -41,5 +41,12 @@
android:text="BR" />
</TableRow>
</TableLayout>
+ <LinearLayout android:id="@+id/inflate_layout"
+ android:orientation="horizontal"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/layout">
+
+ </LinearLayout>
</RelativeLayout>
diff --git a/tests/tests/view/res/layout/focus_finder_sublayout.xml b/tests/tests/view/res/layout/focus_finder_sublayout.xml
new file mode 100644
index 0000000..c9a4c3b
--- /dev/null
+++ b/tests/tests/view/res/layout/focus_finder_sublayout.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <FrameLayout
+ android:focusableInTouchMode="true"
+ android:id="@+id/itembox"
+ android:layout_width="200px"
+ android:layout_height="200px">
+ <Button
+ android:id="@+id/itembutton"
+ android:focusableInTouchMode="true"
+ android:nextFocusForward="@id/itembox"
+ android:layout_gravity="bottom|right"
+ android:layout_marginRight="10px"
+ android:layout_marginBottom="10px"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/view/res/layout/view_layout.xml b/tests/tests/view/res/layout/view_layout.xml
index 3cfaafa..920da83 100644
--- a/tests/tests/view/res/layout/view_layout.xml
+++ b/tests/tests/view/res/layout/view_layout.xml
@@ -46,42 +46,6 @@
android:requiresFadingEdge="horizontal|vertical"
android:fadingEdgeLength="20px"/>
- <android.view.cts.MockView
- android:id="@+id/scroll_view_3"
- android:layout_width="100px"
- android:layout_height="200px"
- android:scrollbars="horizontal|vertical"
- android:scrollbarThumbVertical="@drawable/scrollbar_no_size"
- android:scrollbarThumbHorizontal="@drawable/scrollbar_no_size"/>
-
- <android.view.cts.MockView
- android:id="@+id/scroll_view_4"
- android:layout_width="100px"
- android:layout_height="200px"
- android:scrollbars="horizontal|vertical"
- android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
- android:scrollbarThumbHorizontal="@drawable/scrollbar_thumb"/>
-
- <android.view.cts.MockView
- android:id="@+id/scroll_view_5"
- android:layout_width="100px"
- android:layout_height="200px"
- android:scrollbars="horizontal|vertical"
- android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
- android:scrollbarTrackVertical="@drawable/scrollbar_track"
- android:scrollbarThumbHorizontal="@drawable/scrollbar_thumb"
- android:scrollbarTrackHorizontal="@drawable/scrollbar_track"/>
-
- <android.view.cts.MockView
- android:id="@+id/scroll_view_6"
- android:layout_width="100px"
- android:layout_height="200px"
- android:scrollbars="horizontal|vertical"
- android:scrollbarThumbVertical="@drawable/scrollbar_thumb"
- android:scrollbarTrackVertical="@drawable/scrollbar_no_size"
- android:scrollbarThumbHorizontal="@drawable/scrollbar_thumb"
- android:scrollbarTrackHorizontal="@drawable/scrollbar_no_size"/>
-
<View
android:id="@+id/fit_windows"
android:fitsSystemWindows="true"
diff --git a/tests/tests/view/res/values/dimens.xml b/tests/tests/view/res/values/dimens.xml
index a1d66f9..59369a7 100644
--- a/tests/tests/view/res/values/dimens.xml
+++ b/tests/tests/view/res/values/dimens.xml
@@ -30,8 +30,4 @@
<dimen name="hover_target_margin">4dp</dimen>
<dimen name="hover_target_size">8dp</dimen>
<dimen name="hover_target_size_double">16dp</dimen>
- <dimen name="scrollbar_thumb_width">11dp</dimen>
- <dimen name="scrollbar_thumb_height">12dp</dimen>
- <dimen name="scrollbar_track_width">13dp</dimen>
- <dimen name="scrollbar_track_height">14dp</dimen>
</resources>
\ No newline at end of file
diff --git a/tests/tests/view/src/android/view/cts/DefaultFocusHighlightCtsActivity.java b/tests/tests/view/src/android/view/cts/DefaultFocusHighlightCtsActivity.java
new file mode 100644
index 0000000..5211938
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/DefaultFocusHighlightCtsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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.view.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * A simple activity to test "Default Focus Highlight"
+ */
+public class DefaultFocusHighlightCtsActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.default_focus_highlight_layout);
+ }
+}
diff --git a/tests/tests/view/src/android/view/cts/FocusFinderTest.java b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
index 22fb6e0..8d56087 100644
--- a/tests/tests/view/src/android/view/cts/FocusFinderTest.java
+++ b/tests/tests/view/src/android/view/cts/FocusFinderTest.java
@@ -21,13 +21,16 @@
import static org.junit.Assert.assertTrue;
import android.graphics.Rect;
+import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.FocusFinder;
+import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.FrameLayout;
import org.junit.Before;
import org.junit.Rule;
@@ -340,4 +343,75 @@
View.FOCUS_BACKWARD);
assertTrue(nextFocus == mBottomRight || nextFocus == mBottomLeft);
}
+
+ @Test
+ public void testDuplicateId() throws Throwable {
+ LayoutInflater inflater = mActivityRule.getActivity().getLayoutInflater();
+ mLayout = (ViewGroup) mActivityRule.getActivity().findViewById(R.id.inflate_layout);
+ View[] buttons = new View[3];
+ View[] boxes = new View[3];
+ mActivityRule.runOnUiThread(() -> {
+ for (int i = 0; i < 3; ++i) {
+ View item = inflater.inflate(R.layout.focus_finder_sublayout, mLayout, false);
+ buttons[i] = item.findViewById(R.id.itembutton);
+ boxes[i] = item.findViewById(R.id.itembox);
+ mLayout.addView(item);
+ }
+ });
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
+ verifyNextFocus(buttons[0], View.FOCUS_FORWARD, boxes[0]);
+ verifyNextFocus(boxes[0], View.FOCUS_FORWARD, buttons[1]);
+ verifyNextFocus(buttons[1], View.FOCUS_FORWARD, boxes[1]);
+ verifyNextFocus(boxes[1], View.FOCUS_FORWARD, buttons[2]);
+ }
+
+ @Test
+ public void testBasicFocusOrder() {
+ // Sanity check to make sure sorter is behaving
+ FrameLayout layout = new FrameLayout(mLayout.getContext());
+ Button button1 = new Button(mLayout.getContext());
+ Button button2 = new Button(mLayout.getContext());
+ button1.setLeftTopRightBottom(0, 0, 10, 10);
+ button2.setLeftTopRightBottom(0, 0, 10, 10);
+ layout.addView(button1);
+ layout.addView(button2);
+ View[] views = new View[]{button2, button1};
+ // empty shouldn't crash or anything
+ FocusFinder.sort(views, 0, 0, layout, false);
+ // one view should work
+ FocusFinder.sort(views, 0, 1, layout, false);
+ assertEquals(button2, views[0]);
+ // exactly overlapping views should remain in original order
+ FocusFinder.sort(views, 0, 2, layout, false);
+ assertEquals(button2, views[0]);
+ assertEquals(button1, views[1]);
+ // make sure it will actually mutate input array.
+ button2.setLeftTopRightBottom(20, 0, 30, 10);
+ FocusFinder.sort(views, 0, 2, layout, false);
+ assertEquals(button1, views[0]);
+ assertEquals(button2, views[1]);
+
+ // While we don't want to test details, we should at least verify basic correctness
+ // like "left-to-right" ordering in well-behaved layouts
+ assertEquals(mLayout.findFocus(), mTopLeft);
+ verifyNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+ verifyNextFocus(mTopRight, View.FOCUS_FORWARD, mBottomLeft);
+ verifyNextFocus(mBottomLeft, View.FOCUS_FORWARD, mBottomRight);
+
+ // Should still work intuitively even if some views are slightly shorter.
+ mBottomLeft.setBottom(mBottomLeft.getBottom() - 3);
+ mBottomLeft.offsetTopAndBottom(3);
+ verifyNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+ verifyNextFocus(mTopRight, View.FOCUS_FORWARD, mBottomLeft);
+ verifyNextFocus(mBottomLeft, View.FOCUS_FORWARD, mBottomRight);
+
+ // RTL layout should work right-to-left
+ mActivityRule.getActivity().runOnUiThread(
+ () -> mLayout.setLayoutDirection(View.LAYOUT_DIRECTION_RTL));
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ verifyNextFocus(mTopLeft, View.FOCUS_FORWARD, mTopRight);
+ verifyNextFocus(mTopRight, View.FOCUS_FORWARD, mBottomLeft);
+ verifyNextFocus(mBottomLeft, View.FOCUS_FORWARD, mBottomRight);
+ }
}
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 17c6843..95b8491 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -208,6 +208,19 @@
mMockViewGroup.setVisibility(View.GONE);
parent.addKeyboardNavigationClusters(list, 0);
assertEquals(0, list.size());
+ list.clear();
+
+ // Nested clusters are ignored
+ TestClusterHier h = new TestClusterHier();
+ h.nestedGroup.setKeyboardNavigationCluster(true);
+ h.cluster2.setKeyboardNavigationCluster(false);
+ h.top.addKeyboardNavigationClusters(list, View.FOCUS_FORWARD);
+ assertTrue(list.contains(h.nestedGroup));
+ list.clear();
+ h.cluster2.setKeyboardNavigationCluster(true);
+ h.top.addKeyboardNavigationClusters(list, View.FOCUS_FORWARD);
+ assertFalse(list.contains(h.nestedGroup));
+ list.clear();
}
@UiThreadTest
@@ -1562,6 +1575,14 @@
h.c2view1.setVisibility(View.INVISIBLE);
h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN);
assertSame(h.c2view2, h.top.findFocus());
+
+ // Nested clusters should be ignored.
+ h = new TestClusterHier();
+ h.c1view1.setFocusedInCluster();
+ h.nestedGroup.setKeyboardNavigationCluster(true);
+ h.c2view2.setFocusedInCluster();
+ h.cluster2.restoreFocusInCluster(View.FOCUS_DOWN);
+ assertSame(h.c2view2, h.top.findFocus());
}
@UiThreadTest
@@ -1781,6 +1802,7 @@
// can normal-navigate around once inside
h.top.addFocusables(views, View.FOCUS_DOWN);
assertTrue(views.contains(h.c1view1));
+ views.clear();
h.c1view1.requestFocus();
assertSame(h.c1view1, h.top.findFocus());
// focus loops within cluster (doesn't leave)
@@ -1791,6 +1813,17 @@
h.c2view2.requestFocus();
h.c1view1.requestFocus();
assertSame(h.c2view2, h.top.findFocus());
+
+ h = new TestClusterHier(false);
+ h.c1view1.requestFocus();
+ h.nestedGroup.setKeyboardNavigationCluster(true);
+ h.nestedGroup.setTouchscreenBlocksFocus(true);
+ // since cluster is nested, it should ignore its touchscreenBlocksFocus behavior.
+ h.c2view2.requestFocus();
+ assertSame(h.c2view2, h.top.findFocus());
+ h.top.addFocusables(views, View.FOCUS_DOWN);
+ assertTrue(views.contains(h.c2view2));
+ views.clear();
}
@UiThreadTest
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index ca39aab..2550915 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -3661,67 +3661,6 @@
}
@Test
- public void testScrollbarSize() {
- final int configScrollbarSize = ViewConfiguration.get(mActivity).getScaledScrollBarSize();
- final int customScrollbarSize = configScrollbarSize * 2;
-
- // No explicit scrollbarSize or custom drawables, ViewConfiguration applies.
- final MockView view = (MockView) mActivity.findViewById(R.id.scroll_view);
- assertEquals(configScrollbarSize, view.getScrollBarSize());
- assertEquals(configScrollbarSize, view.getVerticalScrollbarWidth());
- assertEquals(configScrollbarSize, view.getHorizontalScrollbarHeight());
-
- // No custom drawables, explicit scrollbarSize takes precedence.
- final MockView view2 = (MockView) mActivity.findViewById(R.id.scroll_view_2);
- view2.setScrollBarSize(customScrollbarSize);
- assertEquals(customScrollbarSize, view2.getScrollBarSize());
- assertEquals(customScrollbarSize, view2.getVerticalScrollbarWidth());
- assertEquals(customScrollbarSize, view2.getHorizontalScrollbarHeight());
-
- // Custom drawables with no intrinsic size, ViewConfiguration applies.
- final MockView view3 = (MockView) mActivity.findViewById(R.id.scroll_view_3);
- assertEquals(configScrollbarSize, view3.getVerticalScrollbarWidth());
- assertEquals(configScrollbarSize, view3.getHorizontalScrollbarHeight());
- // Explicit scrollbarSize takes precedence.
- view3.setScrollBarSize(customScrollbarSize);
- assertEquals(view3.getScrollBarSize(), view3.getVerticalScrollbarWidth());
- assertEquals(view3.getScrollBarSize(), view3.getHorizontalScrollbarHeight());
-
- // Custom thumb drawables with intrinsic sizes define the scrollbars' dimensions.
- final MockView view4 = (MockView) mActivity.findViewById(R.id.scroll_view_4);
- final Resources res = mActivity.getResources();
- final int thumbWidth = res.getDimensionPixelOffset(R.dimen.scrollbar_thumb_width);
- final int thumbHeight = res.getDimensionPixelOffset(R.dimen.scrollbar_thumb_height);
- assertEquals(thumbWidth, view4.getVerticalScrollbarWidth());
- assertEquals(thumbHeight, view4.getHorizontalScrollbarHeight());
- // Explicit scrollbarSize has no effect.
- view4.setScrollBarSize(customScrollbarSize);
- assertEquals(thumbWidth, view4.getVerticalScrollbarWidth());
- assertEquals(thumbHeight, view4.getHorizontalScrollbarHeight());
-
- // Custom thumb and track drawables with intrinsic sizes. Track size take precedence.
- final MockView view5 = (MockView) mActivity.findViewById(R.id.scroll_view_5);
- final int trackWidth = res.getDimensionPixelOffset(R.dimen.scrollbar_track_width);
- final int trackHeight = res.getDimensionPixelOffset(R.dimen.scrollbar_track_height);
- assertEquals(trackWidth, view5.getVerticalScrollbarWidth());
- assertEquals(trackHeight, view5.getHorizontalScrollbarHeight());
- // Explicit scrollbarSize has no effect.
- view5.setScrollBarSize(customScrollbarSize);
- assertEquals(trackWidth, view5.getVerticalScrollbarWidth());
- assertEquals(trackHeight, view5.getHorizontalScrollbarHeight());
-
- // Custom thumb and track, track with no intrinsic size, ViewConfiguration applies
- // regardless of the thumb drawable dimensions.
- final MockView view6 = (MockView) mActivity.findViewById(R.id.scroll_view_6);
- assertEquals(configScrollbarSize, view6.getVerticalScrollbarWidth());
- assertEquals(configScrollbarSize, view6.getHorizontalScrollbarHeight());
- // Explicit scrollbarSize takes precedence.
- view6.setScrollBarSize(customScrollbarSize);
- assertEquals(customScrollbarSize, view6.getVerticalScrollbarWidth());
- assertEquals(customScrollbarSize, view6.getHorizontalScrollbarHeight());
- }
-
- @Test
public void testOnStartAndFinishTemporaryDetach() throws Throwable {
final AtomicBoolean exitedDispatchStartTemporaryDetach = new AtomicBoolean(false);
final AtomicBoolean exitedDispatchFinishTemporaryDetach = new AtomicBoolean(false);
diff --git a/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
new file mode 100644
index 0000000..5e362cf
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/View_DefaultFocusHighlightTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 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.view.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.app.Activity;
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.rule.ActivityTestRule;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class View_DefaultFocusHighlightTest {
+
+ @Rule
+ public ActivityTestRule<DefaultFocusHighlightCtsActivity> mActivityRule =
+ new ActivityTestRule<>(DefaultFocusHighlightCtsActivity.class);
+
+ @UiThreadTest
+ @Test
+ public void testSettersAndGetters() {
+ Activity activity = mActivityRule.getActivity();
+
+ View view = activity.findViewById(R.id.view);
+ ListView listView = (ListView) activity.findViewById(R.id.listview);
+ EditText editText = (EditText) activity.findViewById(R.id.edittext);
+ Button button = (Button) activity.findViewById(R.id.button);
+ LinearLayout linearLayout = (LinearLayout) activity.findViewById(R.id.linearlayout);
+
+ assertTrue(view.getDefaultFocusHighlightEnabled());
+ assertFalse(listView.getDefaultFocusHighlightEnabled());
+ assertFalse(editText.getDefaultFocusHighlightEnabled());
+ assertTrue(button.getDefaultFocusHighlightEnabled());
+ assertTrue(linearLayout.getDefaultFocusHighlightEnabled());
+
+ view.setDefaultFocusHighlightEnabled(false);
+ listView.setDefaultFocusHighlightEnabled(true);
+ editText.setDefaultFocusHighlightEnabled(true);
+ button.setDefaultFocusHighlightEnabled(false);
+ linearLayout.setDefaultFocusHighlightEnabled(false);
+
+ assertFalse(view.getDefaultFocusHighlightEnabled());
+ assertTrue(listView.getDefaultFocusHighlightEnabled());
+ assertTrue(editText.getDefaultFocusHighlightEnabled());
+ assertFalse(button.getDefaultFocusHighlightEnabled());
+ assertFalse(linearLayout.getDefaultFocusHighlightEnabled());
+ }
+
+ @UiThreadTest
+ @Test
+ public void testInflating() {
+ Activity activity = mActivityRule.getActivity();
+
+ View view = activity.findViewById(R.id.view_to_inflate);
+ ListView listView = (ListView) activity.findViewById(R.id.listview_to_inflate);
+ EditText editText = (EditText) activity.findViewById(R.id.edittext_to_inflate);
+ Button button = (Button) activity.findViewById(R.id.button_to_inflate);
+ LinearLayout linearLayout = (LinearLayout) activity.findViewById(
+ R.id.linearlayout_to_inflate);
+
+ assertFalse(view.getDefaultFocusHighlightEnabled());
+ assertTrue(listView.getDefaultFocusHighlightEnabled());
+ assertTrue(editText.getDefaultFocusHighlightEnabled());
+ assertFalse(button.getDefaultFocusHighlightEnabled());
+ assertFalse(linearLayout.getDefaultFocusHighlightEnabled());
+ }
+}
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
index 3d9f66b..60ef12e 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/SurfacePixelValidator.java
@@ -36,7 +36,7 @@
* Observed that first few frames have errors with SurfaceView placement, so we skip for now.
* b/29603849 tracking that issue.
*/
- private static final int NUM_FIRST_FRAMES_SKIPPED = 8;
+ private static final int NUM_FIRST_FRAMES_SKIPPED = 25;
// If no channel is greater than this value, pixel will be considered 'blackish'.
private static final short PIXEL_CHANNEL_THRESHOLD = 4;
@@ -78,6 +78,7 @@
synchronized (mResultLock) {
if (numSkipped < NUM_FIRST_FRAMES_SKIPPED) {
numSkipped++;
+ Log.d(TAG, "skipped fram nr " + numSkipped + ", success = " + success);
} else {
if (success) {
mResultSuccessFrames++;
diff --git a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
index b16d473..a840116 100644
--- a/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
+++ b/tests/tests/view/src/android/view/textclassifier/cts/TextClassificationManagerTest.java
@@ -17,7 +17,6 @@
package android.view.textclassifier.cts;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import android.os.LocaleList;
@@ -25,21 +24,12 @@
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.textclassifier.TextClassificationManager;
-import android.view.textclassifier.TextClassificationResult;
import android.view.textclassifier.TextClassifier;
-import android.view.textclassifier.TextLanguage;
-import android.view.textclassifier.TextSelection;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.List;
-import java.util.Locale;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class TextClassificationManagerTest {
@@ -53,78 +43,23 @@
public void setup() {
mTcm = InstrumentationRegistry.getTargetContext()
.getSystemService(TextClassificationManager.class);
- mTcm.setTextClassifier(null);
+ mTcm.setTextClassifier(null); // Resets the classifier.
mClassifier = mTcm.getTextClassifier();
}
@Test
- public void testSmartSelection() {
- if (isTextClassifierDisabled()) return;
-
- String text = "Contact me at droid@android.com";
- String selected = "droid";
- String suggested = "droid@android.com";
- int startIndex = text.indexOf(selected);
- int endIndex = startIndex + selected.length();
- int smartStartIndex = text.indexOf(suggested);
- int smartEndIndex = smartStartIndex + suggested.length();
-
- assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
- isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_EMAIL));
+ public void testSmartSelectionDoesNotThrowException() {
+ mClassifier.suggestSelection("text", 2, 3, LOCALES);
}
@Test
- public void testSmartSelection_url() {
- if (isTextClassifierDisabled()) return;
-
- String text = "Visit http://www.android.com for more information";
- String selected = "http";
- String suggested = "http://www.android.com";
- int startIndex = text.indexOf(selected);
- int endIndex = startIndex + selected.length();
- int smartStartIndex = text.indexOf(suggested);
- int smartEndIndex = smartStartIndex + suggested.length();
-
- assertThat(mClassifier.suggestSelection(text, startIndex, endIndex, LOCALES),
- isTextSelection(smartStartIndex, smartEndIndex, TextClassifier.TYPE_URL));
+ public void testTextClassificationResultDoesNotThrowException() {
+ mClassifier.getTextClassificationResult("text", 2, 3, LOCALES);
}
@Test
- public void testTextClassificationResult() {
- if (isTextClassifierDisabled()) return;
-
- String text = "Contact me at droid@android.com";
- String classifiedText = "droid@android.com";
- int startIndex = text.indexOf(classifiedText);
- int endIndex = startIndex + classifiedText.length();
- assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
- isTextClassificationResult(classifiedText, TextClassifier.TYPE_EMAIL));
- }
-
- @Test
- public void testTextClassificationResult_url() {
- if (isTextClassifierDisabled()) return;
-
- String text = "Visit http://www.android.com for more information";
- String classifiedText = "http://www.android.com";
- int startIndex = text.indexOf(classifiedText);
- int endIndex = startIndex + classifiedText.length();
- assertThat(mClassifier.getTextClassificationResult(text, startIndex, endIndex, LOCALES),
- isTextClassificationResult(classifiedText, TextClassifier.TYPE_URL));
- }
-
- @Test
- public void testLanguageDetection() {
- if (isTextClassifierDisabled()) return;
-
- String text = "This is english text";
- assertThat(mTcm.detectLanguages(text), isDetectedLanguage("en"));
-
- text = "Das ist deutscher text";
- assertThat(mTcm.detectLanguages(text), isDetectedLanguage("de"));
-
- text = "これは日本語テキストです";
- assertThat(mTcm.detectLanguages(text), isDetectedLanguage("ja"));
+ public void testLanguageDetectionDoesNotThrowException() {
+ mTcm.detectLanguages("text");
}
@Test
@@ -133,80 +68,4 @@
mTcm.setTextClassifier(classifier);
assertEquals(classifier, mTcm.getTextClassifier());
}
-
- private boolean isTextClassifierDisabled() {
- return mClassifier == TextClassifier.NO_OP;
- }
-
- private static Matcher<TextSelection> isTextSelection(
- final int startIndex, final int endIndex, final String type) {
- return new BaseMatcher<TextSelection>() {
- @Override
- public boolean matches(Object o) {
- if (o instanceof TextSelection) {
- TextSelection selection = (TextSelection) o;
- return startIndex == selection.getSelectionStartIndex()
- && endIndex == selection.getSelectionEndIndex()
- && selection.getEntityCount() > 0
- && type.equals(selection.getEntity(0));
- }
- return false;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendValue(
- String.format("%d, %d, %s", startIndex, endIndex, type));
- }
- };
- }
-
- private static Matcher<TextClassificationResult> isTextClassificationResult(
- final String text, final String type) {
- return new BaseMatcher<TextClassificationResult>() {
- @Override
- public boolean matches(Object o) {
- if (o instanceof TextClassificationResult) {
- TextClassificationResult result = (TextClassificationResult) o;
- return text.equals(result.getText())
- && result.getEntityCount() > 0
- && type.equals(result.getEntity(0));
- // TODO: Include other properties.
- }
- return false;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendText("text=").appendValue(text)
- .appendText(", type=").appendValue(type);
- }
- };
- }
-
- private static Matcher<List<TextLanguage>> isDetectedLanguage(final String language) {
- return new BaseMatcher<List<TextLanguage>>() {
- @Override
- public boolean matches(Object o) {
- if (o instanceof List) {
- List languages = (List) o;
- if (!languages.isEmpty()) {
- Object o1 = languages.get(0);
- if (o1 instanceof TextLanguage) {
- TextLanguage lang = (TextLanguage) o1;
- return lang.getLanguageCount() > 0
- && new Locale(language).getLanguage()
- .equals(lang.getLanguage(0).getLanguage());
- }
- }
- }
- return false;
- }
-
- @Override
- public void describeTo(Description description) {
- description.appendValue(String.format("%s", language));
- }
- };
- }
}
diff --git a/tests/tests/widget/res/layout/textview_imeoptions.xml b/tests/tests/widget/res/layout/textview_imeoptions.xml
new file mode 100644
index 0000000..82b1d26
--- /dev/null
+++ b/tests/tests/widget/res/layout/textview_imeoptions.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <!-- Test EditorInfo.IME_NULL -->
+ <TextView
+ android:id="@+id/textview_imeoption_normal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="normal" />
+
+ <!-- Test EditorInfo.IME_ACTION_* -->
+ <TextView
+ android:id="@+id/textview_imeoption_action_unspecified"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionUnspecified" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_none"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionNone" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_go"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionGo" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_search"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionSearch" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_send"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionSend" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_next"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionNext" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_done"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionDone" />
+ <TextView
+ android:id="@+id/textview_imeoption_action_previous"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionPrevious" />
+
+ <!-- Test EditorInfo.IME_FLAG_* -->
+ <TextView
+ android:id="@+id/textview_imeoption_no_personalized_learning"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNoPersonalizedLearning" />
+ <TextView
+ android:id="@+id/textview_imeoption_no_fullscreen"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNoFullscreen" />
+ <TextView
+ android:id="@+id/textview_imeoption_navigation_previous"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNavigatePrevious" />
+ <TextView
+ android:id="@+id/textview_imeoption_navigation_next"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNavigateNext" />
+ <TextView
+ android:id="@+id/textview_imeoption_no_extract_ui"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNoExtractUi" />
+ <TextView
+ android:id="@+id/textview_imeoption_no_accessory_action"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNoAccessoryAction" />
+ <TextView
+ android:id="@+id/textview_imeoption_no_enter_action"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagNoEnterAction" />
+ <TextView
+ android:id="@+id/textview_imeoption_force_ascii"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="flagForceAscii" />
+
+ <!-- test an action with multiple flags -->
+ <TextView
+ android:id="@+id/textview_imeoption_action_go_nagivate_next_no_extract_ui_force_ascii"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionGo|flagNavigateNext|flagNoExtractUi|flagForceAscii" />
+
+</LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
index 4e33156..b2fd35c 100644
--- a/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AdapterViewTest.java
@@ -362,6 +362,11 @@
assertTrue(mAdapterView.isFocusable());
assertTrue(mAdapterView.isFocusableInTouchMode());
+ // FOCUSABLE_AUTO should also work with children added (AbsListView is clickable)
+ mAdapterView.setFocusable(View.FOCUSABLE_AUTO);
+ assertTrue(mAdapterView.isFocusable());
+ assertTrue(mAdapterView.isFocusableInTouchMode());
+
mAdapterView.setFocusable(false);
assertFalse(mAdapterView.isFocusable());
assertFalse(mAdapterView.isFocusableInTouchMode());
diff --git a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
index 2b55ed5..5476b22 100644
--- a/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ImageViewTest.java
@@ -510,7 +510,6 @@
Drawable backgroundDrawable = new ColorDrawable(0xFF0000FF);
mockImageView.setBackgroundDrawable(backgroundDrawable);
- assertFalse(mockImageView.verifyDrawable(null));
assertFalse(mockImageView.verifyDrawable(new ColorDrawable(0xFF00FF00)));
assertTrue(mockImageView.verifyDrawable(drawable));
assertTrue(mockImageView.verifyDrawable(backgroundDrawable));
diff --git a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
index 4ced4fb..5a68273 100644
--- a/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ProgressBarTest.java
@@ -514,26 +514,22 @@
public void testVerifyDrawable() {
MockProgressBar mockProgressBar =
(MockProgressBar) mActivity.findViewById(R.id.progress_custom);
- assertTrue(mockProgressBar.verifyDrawable(null));
Drawable d1 = mActivity.getDrawable(R.drawable.blue);
Drawable d2 = mActivity.getDrawable(R.drawable.red);
Drawable d3 = mActivity.getDrawable(R.drawable.yellow);
mockProgressBar.setBackgroundDrawable(d1);
- assertTrue(mockProgressBar.verifyDrawable(null));
assertTrue(mockProgressBar.verifyDrawable(d1));
assertFalse(mockProgressBar.verifyDrawable(d2));
assertFalse(mockProgressBar.verifyDrawable(d3));
mockProgressBar.setIndeterminateDrawable(d2);
- assertTrue(mockProgressBar.verifyDrawable(null));
assertTrue(mockProgressBar.verifyDrawable(d1));
assertTrue(mockProgressBar.verifyDrawable(d2));
assertFalse(mockProgressBar.verifyDrawable(d3));
mockProgressBar.setProgressDrawable(d3);
- assertFalse(mockProgressBar.verifyDrawable(null));
assertTrue(mockProgressBar.verifyDrawable(d1));
assertTrue(mockProgressBar.verifyDrawable(d2));
assertTrue(mockProgressBar.verifyDrawable(d3));
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 3da2cb4..a7cde1a 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -42,6 +42,9 @@
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
@@ -158,6 +161,7 @@
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
+import java.lang.annotation.Retention;
import java.util.Arrays;
import java.util.Locale;
@@ -411,6 +415,108 @@
assertEquals(-1, mTextView.getGravity());
}
+ @Retention(SOURCE)
+ @IntDef({EditorInfo.IME_ACTION_UNSPECIFIED, EditorInfo.IME_ACTION_NONE,
+ EditorInfo.IME_ACTION_GO, EditorInfo.IME_ACTION_SEARCH, EditorInfo.IME_ACTION_SEND,
+ EditorInfo.IME_ACTION_NEXT, EditorInfo.IME_ACTION_DONE, EditorInfo.IME_ACTION_PREVIOUS})
+ private @interface ImeOptionAction {}
+
+ @Retention(SOURCE)
+ @IntDef(flag = true,
+ value = {EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING,
+ EditorInfo.IME_FLAG_NO_FULLSCREEN, EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS,
+ EditorInfo.IME_FLAG_NAVIGATE_NEXT, EditorInfo.IME_FLAG_NO_EXTRACT_UI,
+ EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION, EditorInfo.IME_FLAG_NO_ENTER_ACTION,
+ EditorInfo.IME_FLAG_FORCE_ASCII})
+ private @interface ImeOptionFlags {}
+
+ private static void assertImeOptions(TextView textView,
+ @ImeOptionAction int expectedImeOptionAction,
+ @ImeOptionFlags int expectedImeOptionFlags) {
+ final int actualAction = textView.getImeOptions() & EditorInfo.IME_MASK_ACTION;
+ final int actualFlags = textView.getImeOptions() & ~EditorInfo.IME_MASK_ACTION;
+ assertEquals(expectedImeOptionAction, actualAction);
+ assertEquals(expectedImeOptionFlags, actualFlags);
+ }
+
+ @UiThreadTest
+ @Test
+ public void testImeOptions() {
+ mActivity.setContentView(R.layout.textview_imeoptions);
+
+ // Test "normal" to be a synonym EditorInfo.IME_NULL
+ assertEquals(EditorInfo.IME_NULL,
+ mActivity.<TextView>findViewById(R.id.textview_imeoption_normal).getImeOptions());
+
+ // Test EditorInfo.IME_ACTION_*
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_unspecified),
+ EditorInfo.IME_ACTION_UNSPECIFIED, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_none),
+ EditorInfo.IME_ACTION_NONE, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_go),
+ EditorInfo.IME_ACTION_GO, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_search),
+ EditorInfo.IME_ACTION_SEARCH, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_send),
+ EditorInfo.IME_ACTION_SEND, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_next),
+ EditorInfo.IME_ACTION_NEXT, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_done),
+ EditorInfo.IME_ACTION_DONE, 0);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_action_previous),
+ EditorInfo.IME_ACTION_PREVIOUS, 0);
+
+ // Test EditorInfo.IME_FLAG_*
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_no_personalized_learning),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_no_fullscreen),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NO_FULLSCREEN);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_navigation_previous),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_navigation_next),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NAVIGATE_NEXT);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_no_extract_ui),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NO_EXTRACT_UI);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_no_accessory_action),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_no_enter_action),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_NO_ENTER_ACTION);
+ assertImeOptions(
+ mActivity.findViewById(R.id.textview_imeoption_force_ascii),
+ EditorInfo.IME_ACTION_UNSPECIFIED,
+ EditorInfo.IME_FLAG_FORCE_ASCII);
+
+ // test action + multiple flags
+ assertImeOptions(
+ mActivity.findViewById(
+ R.id.textview_imeoption_action_go_nagivate_next_no_extract_ui_force_ascii),
+ EditorInfo.IME_ACTION_GO,
+ EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI
+ | EditorInfo.IME_FLAG_FORCE_ASCII);
+ }
+
@Test
public void testAccessAutoLinkMask() throws Throwable {
mTextView = findTextView(R.id.textview_text);
@@ -4546,7 +4652,7 @@
| InputType.TYPE_NUMBER_FLAG_DECIMAL
| InputType.TYPE_NUMBER_FLAG_SIGNED, mTextView.getInputType());
assertSame(mTextView.getKeyListener(),
- DigitsKeyListener.getInstance(mTextView.getTextLocale(), true, true));
+ DigitsKeyListener.getInstance(null, true, true));
mTextView.setInputType(InputType.TYPE_CLASS_PHONE);
assertEquals(InputType.TYPE_CLASS_PHONE, mTextView.getInputType());
@@ -4762,6 +4868,59 @@
@UiThreadTest
@Test
+ public void testSetImeHintLocalesChangesInputType() {
+ final TextView textView = new TextView(mActivity);
+ textView.setText("", BufferType.EDITABLE);
+
+ textView.setInputType(InputType.TYPE_CLASS_NUMBER);
+ assertEquals(InputType.TYPE_CLASS_NUMBER, textView.getInputType());
+
+ final LocaleList localeList = LocaleList.forLanguageTags("fa-IR");
+ textView.setImeHintLocales(localeList);
+ final int textType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_NORMAL;
+ // Setting IME hint locales to Persian must change the input type to a full text IME,
+ // since the typical number input IME may not have localized digits.
+ assertEquals(textType, textView.getInputType());
+
+ // Changing the input type to datetime should keep the full text IME, since the IME hint
+ // is still set to Persian, which needs advanced input.
+ final int dateType = InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE;
+ textView.setInputType(dateType);
+ assertEquals(textType, textView.getInputType());
+
+ // Changing the input type to number password should keep the full text IME, since the IME
+ // hint is still set to Persian, which needs advanced input. But it also needs to set the
+ // text password flag.
+ final int numberPasswordType = InputType.TYPE_CLASS_NUMBER
+ | InputType.TYPE_NUMBER_VARIATION_PASSWORD;
+ final int textPasswordType = InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_VARIATION_PASSWORD;
+ textView.setInputType(numberPasswordType);
+ assertEquals(textPasswordType, textView.getInputType());
+
+ // Setting the IME hint locales to null should reset the type to number password, since we
+ // no longer need internationalized input.
+ textView.setImeHintLocales(null);
+ assertEquals(numberPasswordType, textView.getInputType());
+ }
+
+ @UiThreadTest
+ @Test
+ public void testSetImeHintLocalesDoesntLoseInputType() {
+ final TextView textView = new TextView(mActivity);
+ textView.setText("", BufferType.EDITABLE);
+ final int inputType = InputType.TYPE_CLASS_TEXT
+ | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT
+ | InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
+ | InputType.TYPE_TEXT_FLAG_MULTI_LINE
+ | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+ textView.setInputType(inputType);
+ textView.setImeHintLocales(new LocaleList(Locale.US));
+ assertEquals(inputType, textView.getInputType());
+ }
+
+ @UiThreadTest
+ @Test
public void testSetExtractedText() {
mTextView = findTextView(R.id.textview_text);
assertEquals(mActivity.getResources().getString(R.string.text_view_hello),
@@ -6630,19 +6789,17 @@
public void testAutoSizeCallers_setHorizontallyScrolling() throws Throwable {
final TextView autoSizeTextView = prepareAndRetrieveAutoSizeTestData(
R.id.textview_autosize_uniform, false);
+ // Verify that we do not have horizontal scrolling turned on.
+ assertTrue(!autoSizeTextView.getHorizontallyScrolling());
+
final float initialTextSize = autoSizeTextView.getTextSize();
- mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(
- !autoSizeTextView.getHorizontallyScrolling()));
+ mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(true));
mInstrumentation.waitForIdleSync();
- final float changedTextSize = autoSizeTextView.getTextSize();
+ assertTrue(autoSizeTextView.getTextSize() > initialTextSize);
- assertTrue(changedTextSize < initialTextSize);
-
- mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(
- autoSizeTextView.getHorizontallyScrolling()));
+ mActivityRule.runOnUiThread(() -> autoSizeTextView.setHorizontallyScrolling(false));
mInstrumentation.waitForIdleSync();
-
- assertEquals(changedTextSize, autoSizeTextView.getTextSize(), 0f);
+ assertEquals(initialTextSize, autoSizeTextView.getTextSize(), 0f);
}
@Test
@@ -7346,8 +7503,8 @@
}
private void calculatePositions() {
- int xStart = (int) mParent.getLayout().getPrimaryHorizontal(mStartCharPos, true, true);
- int xEnd = (int) mParent.getLayout().getPrimaryHorizontal(mEndCharPos, true, true);
+ int xStart = (int) mParent.getLayout().getPrimaryHorizontal(mStartCharPos, true);
+ int xEnd = (int) mParent.getLayout().getPrimaryHorizontal(mEndCharPos, true);
int line = mParent.getLayout().getLineForOffset(mEndCharPos);
int yTop = mParent.getLayout().getLineTop(line);
int yBottom = mParent.getLayout().getLineBottom(line);
@@ -7487,8 +7644,8 @@
*/
private static Point getCenterPositionOfTextAt(
TextView textView, int startIndex, int endIndex) {
- int xStart = (int) textView.getLayout().getPrimaryHorizontal(startIndex, true, true);
- int xEnd = (int) textView.getLayout().getPrimaryHorizontal(endIndex, true, true);
+ int xStart = (int) textView.getLayout().getPrimaryHorizontal(startIndex, true);
+ int xEnd = (int) textView.getLayout().getPrimaryHorizontal(endIndex, true);
int line = textView.getLayout().getLineForOffset(endIndex);
int yTop = textView.getLayout().getLineTop(line);
int yBottom = textView.getLayout().getLineBottom(line);
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 769336d..f694daa 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -175,20 +175,16 @@
<!-- b/31803630 -->
<option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.ListeningPortsTest" />
- <!-- b/36812770 -->
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testAccelerometerHardwareBufferNormal" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testGyroscopeHardwareBufferNormal" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testMagneticFieldHardwareBufferNormal" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testAccelerometerHardwareBufferFast" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testGyroscopeHardwareBufferFast" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testMagneticFieldHardwareBufferFast" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testAccelerometerHardwareBufferVeryFast" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testGyroscopeHardwareBufferVeryFast" />
- <option name="compatibility:exclude-filter" value="CtsSensorTestCases android.hardware.cts.SensorDirectReportTest#testMagneticFieldHardwareBufferVeryFast" />
+ <!-- b/36686383 -->
+ <option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.ErrorsTest#testANR" />
- <!-- b/37216168 -->
- <option name="compatibility:exclude-filter" value="CtsNativeHardwareTestCases AHardwareBufferTest#AHardwareBuffer_SendAndRecv_Succeeds" />
+ <!-- b/33090965 -->
+ <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf0320x0180" />
+ <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf0640x0360" />
+ <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1280x0720" />
+ <option name="compatibility:exclude-filter" value="CtsVideoTestCases android.video.cts.VideoEncoderDecoderTest#testVp9Goog0Perf1920x1080" />
- <!-- b/37108688 -->
- <option name="compatibility:exclude-filter" value="CtsHardwareTestCases android.hardware.cts.HardwareBufferTest#testCreate" />
+ <!-- b/37105075 -->
+ <option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.BatteryStatsValidationTest#testWifiUpload" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-vendor-interface.xml b/tools/cts-tradefed/res/config/cts-vendor-interface.xml
index 582cebf..6785dd8 100644
--- a/tools/cts-tradefed/res/config/cts-vendor-interface.xml
+++ b/tools/cts-tradefed/res/config/cts-vendor-interface.xml
@@ -44,6 +44,7 @@
<option name="compatibility:include-filter" value="CtsMonkeyTestCases" />
<option name="compatibility:include-filter" value="CtsNetTestCases" />
<option name="compatibility:include-filter" value="CtsOsTestCases" />
+ <option name="compatibility:include-filter" value="CtsPdfTestCases" />
<option name="compatibility:include-filter" value="CtsPreference2TestCases" />
<option name="compatibility:include-filter" value="CtsPrintTestCases" />
<option name="compatibility:include-filter" value="CtsProviderTestCases" />
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index 28a5c27..0e31afb 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -24,6 +24,10 @@
<option name="test-tag" value="cts" />
<option name="enable-root" value="false" />
+ <!-- retain 200MB of host log -->
+ <option name="max-log-size" value="200" />
+ <!-- retain 200MB of logcat -->
+ <option name="max-tmp-logcat-file" value="209715200" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
<option name="property-name" value="ro.build.type" />