Merge "DO Disclosure: update instructions for enterprise installed apps, admin granted permission and entrise set default apps test cases." into oc-dev
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index 54fdb08..a8b9863 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -391,8 +391,6 @@
s,e,_,_,_ = cam.do_3a(get_results=True, do_af=False)
req = its.objects.manual_capture_request(s, e)
fps = 30
- if "60fps" in sys.argv:
- fps = 60
req["android.control.aeTargetFpsRange"] = [fps, fps]
print "Capturing %dx%d with sens. %d, exp. time %.1fms" % (
W, H, s, e*NSEC_TO_MSEC)
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index a613050..1787b42 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -48,6 +48,7 @@
android:required="false" />
<uses-feature android:name="android.software.vr.mode" android:required="false" />
<uses-feature android:name="android.hardware.vr.high_performance" android:required="false"/>
+ <uses-feature android:name="android.software.companion_device_setup" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
diff --git a/hostsidetests/devicepolicy/app/Assistant/Android.mk b/hostsidetests/devicepolicy/app/Assistant/Android.mk
new file mode 100644
index 0000000..196f323
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/Android.mk
@@ -0,0 +1,39 @@
+# 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)
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+# Tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsDevicePolicyAssistApp
+
+LOCAL_STATIC_JAVA_LIBRARIES = android-support-v4 compatibility-device-util android-support-test
+
+LOCAL_SDK_VERSION := current
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/devicepolicy/app/Assistant/AndroidManifest.xml b/hostsidetests/devicepolicy/app/Assistant/AndroidManifest.xml
new file mode 100644
index 0000000..5fc20de
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/AndroidManifest.xml
@@ -0,0 +1,48 @@
+<?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="com.android.cts.devicepolicy.assistapp" >
+
+ <application>
+
+ <service android:name=".MyInteractionService"
+ android:label="CTS test voice interaction service"
+ android:permission="android.permission.BIND_VOICE_INTERACTION"
+ android:exported="true">
+ <meta-data android:name="android.voice_interaction"
+ android:resource="@xml/interaction_service" />
+ <intent-filter>
+ <action android:name="android.service.voice.VoiceInteractionService" />
+ </intent-filter>
+ </service>
+
+ <service android:name=".MyInteractionSessionService"
+ android:permission="android.permission.BIND_VOICE_INTERACTION">
+ </service>
+
+ <activity android:name=".SettingsActivity"
+ android:exported="true">
+ </activity>
+ </application>
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.cts.devicepolicy.assistapp"
+ android:label="Assistant related device policy CTS" />
+
+</manifest>
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/Assistant/res/xml/interaction_service.xml b/hostsidetests/devicepolicy/app/Assistant/res/xml/interaction_service.xml
new file mode 100644
index 0000000..a3fe680
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/res/xml/interaction_service.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+
+<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
+ android:sessionService="com.android.cts.devicepolicy.assistapp.MyInteractionSessionService"
+ android:recognitionService="com.android.cts.devicepolicy.assistapp.MyInteractionService"
+ android:settingsActivity="com.android.cts.devicepolicy.assistapp.SettingsActivity"
+ android:supportsAssist="true" />
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionService.java b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionService.java
new file mode 100644
index 0000000..e232540
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionService.java
@@ -0,0 +1,76 @@
+/*
+ * 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.devicepolicy.assistapp;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionService;
+import android.util.Log;
+
+import static android.service.voice.VoiceInteractionSession.SHOW_WITH_ASSIST;
+import static android.service.voice.VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
+
+public class MyInteractionService extends VoiceInteractionService {
+ private static final String TAG = "DevicePolicyAssistTest";
+ private static final String ACTION_CHECK_IS_READY = "voice_interaction_service.is_ready";
+ private static final String ACTION_SHOW_SESSION = "voice_interaction_service.show_session";
+ private AssistReceiver mReceiver;
+ private boolean mReady;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ mReceiver = new AssistReceiver();
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(ACTION_CHECK_IS_READY);
+ intentFilter.addAction(ACTION_SHOW_SESSION);
+ registerReceiver(mReceiver, intentFilter);
+ }
+
+ @Override
+ public void onReady() {
+ super.onReady();
+ Log.d(TAG, "onReady() called");
+ mReady = true;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.d(TAG, "onDestroy() called");
+ unregisterReceiver(mReceiver);
+ mReceiver = null;
+ }
+
+ private class AssistReceiver extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "AssistReceiver: " + intent + " mReady: " + mReady);
+ if (ACTION_CHECK_IS_READY.equals(intent.getAction())) {
+ setResultCode(mReady ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
+ } else if (ACTION_SHOW_SESSION.equals(intent.getAction())) {
+ showSession(
+ new Bundle(),
+ SHOW_WITH_ASSIST | SHOW_WITH_SCREENSHOT);
+ }
+ }
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionSessionService.java b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionSessionService.java
new file mode 100644
index 0000000..5eae4f7
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/MyInteractionSessionService.java
@@ -0,0 +1,54 @@
+/*
+ * 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.devicepolicy.assistapp;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.service.voice.VoiceInteractionSessionService;
+import android.util.Log;
+
+public class MyInteractionSessionService extends VoiceInteractionSessionService {
+ private static final String TAG = "DevicePolicyAssistTest";
+ private static final String ACTION_HANDLE_SCREENSHOT =
+ "voice_interaction_session_service.handle_screenshot";
+ private static final String KEY_HAS_SCREENSHOT = "has_screenshot";
+
+ @Override
+ public VoiceInteractionSession onNewSession(Bundle args) {
+ return new MainInteractionSession(this);
+ }
+
+ public static class MainInteractionSession extends VoiceInteractionSession {
+
+ public MainInteractionSession(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onHandleScreenshot(Bitmap screenshot) {
+ Log.d(TAG, "onHandleScreenshot() called with: screenshot = [" + screenshot + "]");
+ Intent intent = new Intent(ACTION_HANDLE_SCREENSHOT);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(KEY_HAS_SCREENSHOT, screenshot != null);
+ getContext().sendBroadcast(intent);
+ finish();
+ }
+ }
+}
\ No newline at end of file
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/SettingsActivity.java
similarity index 61%
copy from hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
copy to hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/SettingsActivity.java
index e7a9e73..1f6d34f 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
+++ b/hostsidetests/devicepolicy/app/Assistant/src/com/android/cts/devicepolicy/assistapp/SettingsActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -13,19 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package com.android.cts.devicepolicy.assistapp;
-package com.android.cts.comp;
+import android.app.Activity;
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-
-/**
- * Dummy service that is exported.
- */
-public class ExportedCrossUserService extends Service {
- @Override
- public IBinder onBind(Intent intent) {
- return null;
- }
+public class SettingsActivity extends Activity {
}
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml
index 89ac4ae..820f1be 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/AndroidManifest.xml
@@ -37,11 +37,12 @@
</receiver>
<activity android:name="com.android.compatibility.common.util.devicepolicy.provisioning.StartProvisioningActivity"/>
- <service android:name=".CrossUserService"
- android:exported="false">
+ <service android:name=".ProtectedCrossUserService"
+ android:exported="true"
+ android:permission="android.permission.BIND_DEVICE_ADMIN">
</service>
- <service android:name=".ExportedCrossUserService"
+ <service android:name=".UnprotectedCrossUserService"
android:exported="true">
</service>
</application>
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java
index 476b99c..319d7ec 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceFailsTest.java
@@ -66,7 +66,7 @@
private void checkCannotBind(String targetPackageName, UserHandle otherProfile) {
try {
final Intent serviceIntent = new Intent();
- serviceIntent.setClassName(targetPackageName, CrossUserService.class.getName());
+ serviceIntent.setClassName(targetPackageName, ProtectedCrossUserService.class.getName());
bind(serviceIntent, EMPTY_SERVICE_CONNECTION, otherProfile);
fail("SecurityException should be thrown");
} catch (SecurityException ex) {
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java
index ad65367..e7386cd 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/BindDeviceAdminServiceGoodSetupTest.java
@@ -33,7 +33,6 @@
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.UserManager;
import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.util.Log;
@@ -107,16 +106,17 @@
}
/**
- * Make sure we cannot bind exported service.
+ * Make sure we cannot bind unprotected service.
*/
- public void testCannotBind_exportedCrossUserService() throws Exception {
- final Intent serviceIntent = new Intent(mContext, ExportedCrossUserService.class);
+ public void testCannotBind_unprotectedCrossUserService() throws Exception {
+ final Intent serviceIntent = new Intent(mContext, UnprotectedCrossUserService.class);
for (UserHandle targetUser : mTargetUsers) {
try {
bind(serviceIntent, EMPTY_SERVICE_CONNECTION, targetUser);
fail("SecurityException should be thrown for target user " + targetUser);
} catch (SecurityException ex) {
- MoreAsserts.assertContainsRegex("must be unexported", ex.getMessage());
+ MoreAsserts.assertContainsRegex(
+ "must be protected by BIND_DEVICE_ADMIN", ex.getMessage());
}
}
}
@@ -126,7 +126,7 @@
*/
public void testCheckCannotBind_nonManagingPackage() throws Exception {
final Intent serviceIntent = new Intent();
- serviceIntent.setClassName(NON_MANAGING_PACKAGE, CrossUserService.class.getName());
+ serviceIntent.setClassName(NON_MANAGING_PACKAGE, ProtectedCrossUserService.class.getName());
for (UserHandle targetUser : mTargetUsers) {
try {
bind(serviceIntent, EMPTY_SERVICE_CONNECTION, targetUser);
@@ -142,7 +142,7 @@
*/
public void testCannotBind_sameUser() throws Exception {
try {
- final Intent serviceIntent = new Intent(mContext, CrossUserService.class);
+ final Intent serviceIntent = new Intent(mContext, ProtectedCrossUserService.class);
bind(serviceIntent, EMPTY_SERVICE_CONNECTION, Process.myUserHandle());
fail("IllegalArgumentException should be thrown");
} catch (IllegalArgumentException ex) {
@@ -199,7 +199,7 @@
Log.d(TAG, "onServiceDisconnected is called");
}
};
- final Intent serviceIntent = new Intent(mContext, CrossUserService.class);
+ final Intent serviceIntent = new Intent(mContext, ProtectedCrossUserService.class);
assertTrue(bind(serviceIntent, serviceConnection, targetUserHandle));
IInterface service = queue.poll(5, TimeUnit.SECONDS);
assertNotNull("binding to the target service timed out", service);
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/CrossUserService.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ProtectedCrossUserService.java
similarity index 95%
rename from hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/CrossUserService.java
rename to hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ProtectedCrossUserService.java
index 3b95b94..76e926a 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/CrossUserService.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ProtectedCrossUserService.java
@@ -25,7 +25,7 @@
/**
* Handle the cross user call from the device admin in other side.
*/
-public class CrossUserService extends Service {
+public class ProtectedCrossUserService extends Service {
private final ICrossUserService.Stub mBinder = new ICrossUserService.Stub() {
public String echo(String msg) {
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/UnprotectedCrossUserService.java
similarity index 93%
rename from hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
rename to hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/UnprotectedCrossUserService.java
index e7a9e73..8540737 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/ExportedCrossUserService.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/UnprotectedCrossUserService.java
@@ -23,7 +23,7 @@
/**
* Dummy service that is exported.
*/
-public class ExportedCrossUserService extends Service {
+public class UnprotectedCrossUserService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
diff --git a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java
index 7a1fa40..442e544 100644
--- a/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java
+++ b/hostsidetests/devicepolicy/app/CorpOwnedManagedProfile/src/com/android/cts/comp/provisioning/AffiliationTest.java
@@ -21,9 +21,11 @@
import android.content.ComponentName;
import android.content.Context;
import android.test.AndroidTestCase;
+
import com.android.cts.comp.AdminReceiver;
-import java.util.Arrays;
-import java.util.List;
+
+import java.util.Collections;
+import java.util.Set;
public class AffiliationTest extends AndroidTestCase {
@@ -39,7 +41,7 @@
ComponentName admin = AdminReceiver.getComponentName(getContext());
DevicePolicyManager dpm = (DevicePolicyManager)
mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- List<String> ids = Arrays.asList(id);
+ Set<String> ids = Collections.singleton(id);
dpm.setAffiliationIds(admin, ids);
assertEquals(ids, dpm.getAffiliationIds(admin));
}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
new file mode 100644
index 0000000..db54ac3
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AssistScreenCaptureDisabledTest.java
@@ -0,0 +1,98 @@
+package com.android.cts.deviceandprofileowner;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import com.android.compatibility.common.util.BlockingBroadcastReceiver;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Testing
+ * {@link android.app.admin.DevicePolicyManager#setScreenCaptureDisabled(ComponentName, boolean)}
+ * is enforced in {@link android.service.voice.VoiceInteractionSession#onHandleScreenshot(Bitmap)}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class AssistScreenCaptureDisabledTest {
+ private static final String TAG = "DevicePolicyAssistTest";
+
+ private static final String ACTION_CHECK_IS_READY = "voice_interaction_service.is_ready";
+ private static final String ACTION_SHOW_SESSION = "voice_interaction_service.show_session";
+ private static final String ACTION_HANDLE_SCREENSHOT =
+ "voice_interaction_session_service.handle_screenshot";
+ private static final String KEY_HAS_SCREENSHOT = "has_screenshot";
+ private static final String ASSIST_PACKAGE = "com.android.cts.devicepolicy.assistapp";
+
+ private static final int MAX_ATTEMPTS_COUNT = 5;
+ private static final int WAIT_IN_SECOND = 5;
+ private Context mContext;
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getContext();
+ }
+
+ @Test
+ public void testScreenCaptureImpossible_assist() throws Exception {
+ assertScreenCapturePossible(false);
+ }
+
+ @Test
+ public void testScreenCapturePossible_assist() throws Exception {
+ assertScreenCapturePossible(true);
+ }
+
+ private void assertScreenCapturePossible(boolean possible) throws InterruptedException {
+ // Wait until voice interaction service is ready by sending broadcast to ask for status.
+ Intent checkIsReadyIntent = new Intent(ACTION_CHECK_IS_READY);
+ checkIsReadyIntent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ checkIsReadyIntent.setPackage(ASSIST_PACKAGE);
+ boolean isAssistReady = false;
+ for (int i = 0; i < MAX_ATTEMPTS_COUNT && !isAssistReady; i++) {
+ Log.d(TAG, "assertScreenCapturePossible: wait for assist service ready, attempt " + i);
+ final LinkedBlockingQueue<Boolean> q = new LinkedBlockingQueue<>();
+ mContext.sendOrderedBroadcast(checkIsReadyIntent, null, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ q.offer(getResultCode() == Activity.RESULT_OK);
+ }
+ }, null, Activity.RESULT_CANCELED, null, null);
+ Boolean result = q.poll(WAIT_IN_SECOND, TimeUnit.SECONDS);
+ isAssistReady = result != null && result;
+ }
+ Assert.assertTrue(isAssistReady);
+
+ // Send broadcast to voice interaction service and ask for screnshot.
+ BlockingBroadcastReceiver receiver = new BlockingBroadcastReceiver(
+ mContext, ACTION_HANDLE_SCREENSHOT);
+ try {
+ receiver.register();
+ Intent showSessionIntent = new Intent(ACTION_SHOW_SESSION);
+ showSessionIntent.setPackage(ASSIST_PACKAGE);
+ mContext.sendBroadcast(showSessionIntent);
+ Intent screenShotIntent = receiver.awaitForBroadcast();
+ Assert.assertNotNull(screenShotIntent);
+ Assert.assertTrue(screenShotIntent.hasExtra(KEY_HAS_SCREENSHOT));
+ assertEquals(possible, screenShotIntent.getBooleanExtra(KEY_HAS_SCREENSHOT, false));
+ } finally {
+ receiver.unregisterQuietly();
+ }
+ }
+}
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
index b7f9066..c5b3e96 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/ScreenCaptureDisabledTest.java
@@ -16,7 +16,7 @@
package com.android.cts.deviceandprofileowner;
import android.app.admin.DevicePolicyManager;
-import android.util.Log;
+import android.support.v4.content.LocalBroadcastManager;
/**
* Tests for {@link DevicePolicyManager#setScreenCaptureDisabled} and
@@ -26,6 +26,12 @@
private static final String TAG = "ScreenCaptureDisabledTest";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
public void testSetScreenCaptureDisabled_false() throws Exception {
mDevicePolicyManager.setScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT, false);
assertFalse(mDevicePolicyManager.getScreenCaptureDisabled(ADMIN_RECEIVER_COMPONENT));
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java
index 4ccb3c6..a9b43c6 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/AffiliationTest.java
@@ -16,26 +16,24 @@
package com.android.cts.deviceowner;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-
-import static org.junit.Assert.assertArrayEquals;
-
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Collections;
-import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertArrayEquals;
@RunWith(AndroidJUnit4.class)
public class AffiliationTest {
@@ -52,13 +50,33 @@
}
@Test
+ public void testSetAffiliationId_null() {
+ try {
+ mDevicePolicyManager.setAffiliationIds(mAdminComponent, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // Expected
+ }
+ }
+
+ @Test
+ public void testSetAffiliationId_containsEmptyString() {
+ try {
+ mDevicePolicyManager.setAffiliationIds(mAdminComponent, Collections.singleton(null));
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // Expected
+ }
+ }
+
+ @Test
public void testSetAffiliationId1() {
- setAffiliationIds(Collections.singletonList("id.number.1"));
+ setAffiliationIds(Collections.singleton("id.number.1"));
}
@Test
public void testSetAffiliationId2() {
- setAffiliationIds(Collections.singletonList("id.number.2"));
+ setAffiliationIds(Collections.singleton("id.number.2"));
}
@Test
@@ -75,11 +93,11 @@
assertTrue(mDevicePolicyManager.isLockTaskPermitted("package1"));
assertFalse(mDevicePolicyManager.isLockTaskPermitted("package3"));
- final List<String> previousAffiliationIds =
+ final Set<String> previousAffiliationIds =
mDevicePolicyManager.getAffiliationIds(mAdminComponent);
try {
// Clearing affiliation ids for this user. Lock task methods unavailable.
- setAffiliationIds(Collections.<String>emptyList());
+ setAffiliationIds(Collections.emptySet());
checkLockTaskMethodsThrow();
assertFalse(mDevicePolicyManager.isLockTaskPermitted("package1"));
@@ -92,7 +110,7 @@
}
}
- private void setAffiliationIds(List<String> ids) {
+ private void setAffiliationIds(Set<String> ids) {
mDevicePolicyManager.setAffiliationIds(mAdminComponent, ids);
assertEquals(ids, mDevicePolicyManager.getAffiliationIds(mAdminComponent));
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index d3cde44..d20d5e4 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -138,7 +138,7 @@
removeOwners();
removeTestUsers();
// Unlock keyguard before test
- executeShellCommand("wm dismiss-keyguard");
+ wakeupAndDismissKeyguard();
}
@Override
@@ -764,4 +764,9 @@
}
}
}
+
+ protected void wakeupAndDismissKeyguard() throws Exception {
+ executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ executeShellCommand("wm dismiss-keyguard");
+ }
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
index da902d3..865d785 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceAndProfileOwnerTest.java
@@ -96,9 +96,15 @@
private static final String AUTOFILL_APP_PKG = "com.android.cts.devicepolicy.autofillapp";
private static final String AUTOFILL_APP_APK = "CtsDevicePolicyAutofillApp.apk";
+ protected static final String ASSIST_APP_PKG = "com.android.cts.devicepolicy.assistapp";
+ protected static final String ASSIST_APP_APK = "CtsDevicePolicyAssistApp.apk";
+
private static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES
= "enabled_notification_policy_access_packages";
+ protected static final String ASSIST_INTERACTION_SERVICE =
+ ASSIST_APP_PKG + "/.MyInteractionService";
+
// ID of the user all tests are run as. For device owner this will be the primary user, for
// profile owner it is the user id of the created profile.
protected int mUserId;
@@ -364,6 +370,21 @@
}
}
+ public void testScreenCaptureDisabled_assist() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ try {
+ // Install and enable assistant, notice that profile can't have assistant.
+ installAppAsUser(ASSIST_APP_APK, mPrimaryUserId);
+ setVoiceInteractionService(ASSIST_INTERACTION_SERVICE);
+ setScreenCaptureDisabled_assist(mUserId, true /* disabled */);
+ } finally {
+ setScreenCaptureDisabled_assist(mUserId, false /* disabled */);
+ clearVoiceInteractionService();
+ }
+ }
+
public void testSupportMessage() throws Exception {
if (!mHasFeature) {
return;
@@ -773,35 +794,44 @@
*/
protected void startSimpleActivityAsUser(int userId) throws Exception {
installAppAsUser(TEST_APP_APK, userId);
+ wakeupAndDismissKeyguard();
String command = "am start -W --user " + userId + " " + TEST_APP_PKG + "/"
+ TEST_APP_PKG + ".SimpleActivity";
getDevice().executeShellCommand(command);
}
- // TODO: Remove this after investigation in b/28995242 is done
- // So we can check which one is the top window / activity.
- private void runDumpsysWindow() throws Exception {
- String command = "dumpsys window displays";
- CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
- command = "dumpsys activity a";
- CLog.d("Output for command " + command + ": " + getDevice().executeShellCommand(command));
- }
-
protected void setScreenCaptureDisabled(int userId, boolean disabled) throws Exception {
String testMethodName = disabled
? "testSetScreenCaptureDisabled_true"
: "testSetScreenCaptureDisabled_false";
executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
startSimpleActivityAsUser(userId);
- // [b/28995242], dump windows to make sure the top window is
- // ScreenCaptureDisabledActivity.
- runDumpsysWindow();
testMethodName = disabled
? "testScreenCaptureImpossible"
: "testScreenCapturePossible";
executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
}
+ protected void setScreenCaptureDisabled_assist(int userId, boolean disabled) throws Exception {
+ // Set the policy.
+ String testMethodName = disabled
+ ? "testSetScreenCaptureDisabled_true"
+ : "testSetScreenCaptureDisabled_false";
+ executeDeviceTestMethod(".ScreenCaptureDisabledTest", testMethodName);
+ // Make sure the foreground activity is from the target user.
+ startSimpleActivityAsUser(userId);
+ // Check whether the VoiceInteractionService can retrieve the screenshot.
+ testMethodName = disabled
+ ? "testScreenCaptureImpossible_assist"
+ : "testScreenCapturePossible_assist";
+ installAppAsUser(DEVICE_ADMIN_APK, mPrimaryUserId);
+ runDeviceTestsAsUser(
+ DEVICE_ADMIN_PKG,
+ ".AssistScreenCaptureDisabledTest",
+ testMethodName,
+ mPrimaryUserId);
+ }
+
/**
* Allows packageName to manage notification policy configuration, which
* includes toggling zen mode.
@@ -843,4 +873,16 @@
}
return new ArrayList<String>(Arrays.asList(settingValue.split(":|\n")));
}
+
+ protected void setVoiceInteractionService(String componentName)
+ throws DeviceNotAvailableException {
+ getDevice().setSetting(
+ mPrimaryUserId, "secure", "voice_interaction_service", componentName);
+ getDevice().setSetting(mPrimaryUserId, "secure", "assist_structure_enabled", "1");
+ getDevice().setSetting(mPrimaryUserId, "secure", "assist_screenshot_enabled", "1");
+ }
+
+ protected void clearVoiceInteractionService() throws DeviceNotAvailableException {
+ getDevice().executeShellCommand("settings delete secure voice_interaction_service");
+ }
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 8fce788..ac846a3 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -346,6 +346,14 @@
executeDeviceTestMethod(".NetworkLoggingTest", "testNetworkLoggingAndRetrieval");
}
+ public void testSetAffiliationId_IllegalArgumentException() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ executeDeviceTestMethod(".AffiliationTest", "testSetAffiliationId_null");
+ executeDeviceTestMethod(".AffiliationTest", "testSetAffiliationId_containsEmptyString");
+ }
+
public void testLockTask_deviceOwnerUser() throws Exception {
if (!mHasFeature) {
return;
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
index a2d8057..0022804 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/MixedManagedProfileOwnerTest.java
@@ -78,6 +78,36 @@
executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testScreenCapturePossible");
}
+ public void testScreenCaptureDisabled_assist_allowedPrimaryUser() throws Exception {
+ if (!mHasFeature) {
+ return;
+ }
+ // disable screen capture in profile
+ executeDeviceTestMethod(".ScreenCaptureDisabledTest", "testSetScreenCaptureDisabled_true");
+ try {
+ // Install and enable assistant in personal side.
+ installAppAsUser(ASSIST_APP_APK, mParentUserId);
+ setVoiceInteractionService(ASSIST_INTERACTION_SERVICE);
+
+ // Start an activity in parent user.
+ installAppAsUser(DEVICE_ADMIN_APK, mParentUserId);
+ startSimpleActivityAsUser(mParentUserId);
+
+ // Verify assistant app can't take a screenshot.
+ runDeviceTestsAsUser(
+ DEVICE_ADMIN_PKG,
+ ".AssistScreenCaptureDisabledTest",
+ "testScreenCapturePossible_assist",
+ mPrimaryUserId);
+ } finally {
+ // enable screen capture in profile
+ executeDeviceTestMethod(
+ ".ScreenCaptureDisabledTest",
+ "testSetScreenCaptureDisabled_false");
+ clearVoiceInteractionService();
+ }
+ }
+
@Override
public void testDisallowSetWallpaper_allowed() throws Exception {
// Managed profile doesn't have wallpaper.
diff --git a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
index c943aee..470e666 100644
--- a/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
+++ b/hostsidetests/inputmethodservice/hostside/AndroidTest.xml
@@ -16,6 +16,10 @@
-->
<configuration description="Config for CTS Input Method Service host test cases">
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
+ </target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsInputMethodServiceEventProvider.apk" />
diff --git a/hostsidetests/media/Android.mk b/hostsidetests/media/Android.mk
new file mode 100644
index 0000000..36e9066
--- /dev/null
+++ b/hostsidetests/media/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, common) \
+ $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := tests
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_MODULE := CtsMediaHostTestCases
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed compatibility-host-util
+
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
+
diff --git a/hostsidetests/media/AndroidTest.xml b/hostsidetests/media/AndroidTest.xml
new file mode 100644
index 0000000..0a6410c
--- /dev/null
+++ b/hostsidetests/media/AndroidTest.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.
+-->
+<configuration description="Config for CTS media host test cases">
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsMediaHostTestCases.jar" />
+ <option name="runtime-hint" value="30m" />
+ </test>
+</configuration>
+
diff --git a/hostsidetests/media/app/MediaSessionTest/Android.mk b/hostsidetests/media/app/MediaSessionTest/Android.mk
new file mode 100644
index 0000000..eb9059d
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTest/Android.mk
@@ -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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsMediaSessionHostTestApp
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ $(call all-java-files-under, ../../common)
+
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_PACKAGE)
diff --git a/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml b/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
new file mode 100644
index 0000000..60e82dd
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTest/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?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.media.session.cts">
+
+ <uses-sdk android:minSdkVersion="26"/>
+
+ <application />
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.media.session.cts"
+ android:label="MediaSession multi-user case CTS Tests" />
+
+</manifest>
diff --git a/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java b/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
new file mode 100644
index 0000000..2186038
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTest/src/android/media/session/cts/MediaSessionManagerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.media.session.cts;
+
+import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG;
+
+import android.content.Context;
+import android.content.ComponentName;
+import android.test.AndroidTestCase;
+import android.media.session.MediaSessionManager;
+import android.media.session.MediaController;
+
+import java.util.List;
+
+/**
+ * Tests {@link MediaSessionManager} with the multi-user environment.
+ * <p>Don't run tests here directly. They aren't stand-alone tests and each test will be run
+ * indirectly by the host-side test CtsMediaHostTestCases after the proper device setup.
+ */
+public class MediaSessionManagerTest extends AndroidTestCase {
+ private MediaSessionManager mMediaSessionManager;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mMediaSessionManager = (MediaSessionManager) getContext().getSystemService(
+ Context.MEDIA_SESSION_SERVICE);
+ }
+
+ /**
+ * Tests if the MediaSessionTestHelper doesn't have an active media session.
+ */
+ public void testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper() throws Exception {
+ List<MediaController> controllers = mMediaSessionManager.getActiveSessions(
+ createFakeNotificationListener());
+ for (MediaController controller : controllers) {
+ if (controller.getPackageName().equals(MEDIA_SESSION_TEST_HELPER_PKG)) {
+ fail("Media session for the media session app shouldn't be available");
+ return;
+ }
+ }
+ }
+
+ /**
+ * Tests if the MediaSessionTestHelper has an active media session.
+ */
+ public void testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper() throws Exception {
+ List<MediaController> controllers = mMediaSessionManager.getActiveSessions(
+ createFakeNotificationListener());
+ for (MediaController controller : controllers) {
+ if (controller.getPackageName().equals(MEDIA_SESSION_TEST_HELPER_PKG)) {
+ // Test success
+ return;
+ }
+ }
+ fail("Media session for the media session app is expected");
+ }
+
+ /**
+ * Tests if there's no media session.
+ */
+ public void testGetActiveSessions_noMediaSession() throws Exception {
+ List<MediaController> controllers = mMediaSessionManager.getActiveSessions(
+ createFakeNotificationListener());
+ assertTrue(controllers.isEmpty());
+ }
+
+ /**
+ * Returns the ComponentName of the notification listener for this test.
+ * <p>Notification listener will be enabled by the host-side test.
+ */
+ private ComponentName createFakeNotificationListener() {
+ return new ComponentName(getContext(), MediaSessionManagerTest.class);
+ }
+}
+
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/Android.mk b/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
new file mode 100644
index 0000000..3944cb6
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/Android.mk
@@ -0,0 +1,40 @@
+# 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)
+
+# Don't include this package in any target
+LOCAL_MODULE_TAGS := tests
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, src) \
+ $(call all-java-files-under, ../../common)
+
+# tag this module as a cts test artifact
+LOCAL_COMPATIBILITY_SUITE := cts
+
+LOCAL_PACKAGE_NAME := CtsMediaSessionTestHelper
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
+
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/AndroidManifest.xml b/hostsidetests/media/app/MediaSessionTestHelper/AndroidManifest.xml
new file mode 100644
index 0000000..1e29eca
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/AndroidManifest.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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.media.app.media_session_test_helper"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <application android:label="@string/label">
+ <service android:name=".MediaSessionTestHelperService">
+ <intent-filter>
+ <action android:name="android.media.app.media_session_test_helper.ACTION_CONTROL" />
+ </intent-filter>
+ </service>
+ </application>
+</manifest>
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/res/values/strings.xml b/hostsidetests/media/app/MediaSessionTestHelper/res/values/strings.xml
new file mode 100644
index 0000000..fb75fdb
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/res/values/strings.xml
@@ -0,0 +1,18 @@
+<?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.
+-->
+<resources>
+ <string name="label">MediaSessionTestHelper for media host-side CTS tests</string>
+</resources>
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/src/android/media/app/media_session_test_helper/MediaSessionTestHelperService.java b/hostsidetests/media/app/MediaSessionTestHelper/src/android/media/app/media_session_test_helper/MediaSessionTestHelperService.java
new file mode 100644
index 0000000..a161ba5
--- /dev/null
+++ b/hostsidetests/media/app/MediaSessionTestHelper/src/android/media/app/media_session_test_helper/MediaSessionTestHelperService.java
@@ -0,0 +1,103 @@
+/*
+ * 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.media.app.media_session_test_helper;
+
+import android.app.Notification;
+import android.app.Service;
+import android.content.Intent;
+import android.media.session.MediaSession;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import android.media.cts.MediaSessionTestHelperConstants;
+
+/**
+ * Service of the media session's host-side CTS helper.
+ * <p>This is the foreground service to prevent this process from being killed by the OOM killer
+ * while the host-side tests are running.
+ */
+public class MediaSessionTestHelperService extends Service {
+ private static final String TAG = "MediaSessionTestHelperService";
+
+ private static final int NOTIFICATION_ID = 100;
+
+ private MediaSession mMediaSession;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ // Build notification UI to make this a foreground service.
+ Notification notification = new Notification.Builder(this)
+ .setSmallIcon(android.R.drawable.sym_def_app_icon)
+ .setContentTitle(getString(R.string.label)).build();
+ startForeground(NOTIFICATION_ID, notification);
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ super.onStartCommand(intent, flags, startId);
+ if (!TextUtils.equals(intent.getAction(), MediaSessionTestHelperConstants.ACTION_CONTROL)) {
+ Log.e(TAG, "Invalid action " + intent.getAction() + ". Test may fail");
+ return START_STICKY;
+ }
+ int flag = intent.getIntExtra(MediaSessionTestHelperConstants.EXTRA_CONTROL_COMMAND, 0);
+ if ((flag & MediaSessionTestHelperConstants.FLAG_CREATE_MEDIA_SESSION) != 0) {
+ if (mMediaSession == null) {
+ mMediaSession = new MediaSession(this, TAG);
+ }
+ }
+ if (mMediaSession != null) {
+ if ((flag & MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_ACTIVE) != 0) {
+ mMediaSession.setActive(true);
+ }
+ if ((flag & MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_INACTIVE) != 0) {
+ mMediaSession.setActive(false);
+ }
+ }
+ if ((flag & MediaSessionTestHelperConstants.FLAG_RELEASE_MEDIA_SESSION) != 0) {
+ releaseMediaSession();
+ }
+ return START_STICKY;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ // It's not a bind service.
+ return null;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ releaseMediaSession();
+ }
+
+ private void releaseMediaSession() {
+ if (mMediaSession != null) {
+ mMediaSession.release();
+ mMediaSession = null;
+ }
+ }
+}
diff --git a/hostsidetests/media/common/android/media/cts/MediaSessionTestHelperConstants.java b/hostsidetests/media/common/android/media/cts/MediaSessionTestHelperConstants.java
new file mode 100644
index 0000000..8c8dc54
--- /dev/null
+++ b/hostsidetests/media/common/android/media/cts/MediaSessionTestHelperConstants.java
@@ -0,0 +1,90 @@
+/*
+ * 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.media.cts;
+
+/**
+ * Defines constants for controlling the media session test helper app, which can start media
+ * playback and create the media session for test.
+ * <p>Any change in these constants should also be applied to the media session test helper app.
+ * <p>Don't add Android specific imports because this will be used by the both host-side and
+ * device-side.
+ */
+public class MediaSessionTestHelperConstants {
+ /**
+ * Package name of the media session test helper.
+ */
+ public static final String MEDIA_SESSION_TEST_HELPER_PKG =
+ "android.media.app.media_session_test_helper";
+ /**
+ * Package binary file name of the media session test helper`.
+ */
+ public static final String MEDIA_SESSION_TEST_HELPER_APK = "CtsMediaSessionTestHelper.apk";
+
+ /**
+ * Intent action name to control media sesion test helper.
+ */
+ public static final String ACTION_CONTROL =
+ "android.media.app.media_session_test_helper.ACTION_CONTROL";
+ /**
+ * Intent extra key name to control media session test helper.
+ */
+ public static final String EXTRA_CONTROL_COMMAND =
+ "android.media.app.media_session_test_helper.EXTRA_CONTROL_COMMAND";
+
+ /**
+ * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to create the media session
+ * if it doesn't exist.
+ * @see buildControlCommand
+ */
+ public static final int FLAG_CREATE_MEDIA_SESSION = 0x01;
+ /**
+ * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to set the media session active
+ * if it exists.
+ * @see buildControlCommand
+ */
+ public static final int FLAG_SET_MEDIA_SESSION_ACTIVE = 0x02;
+ /**
+ * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to set the media session
+ * inactive if it exists.
+ * @see buildControlCommand
+ */
+ public static final int FLAG_SET_MEDIA_SESSION_INACTIVE = 0x04;
+ /**
+ * Intent extra value for the key {@link #EXTRA_CONTROL_COMMAND} to release the media session
+ * if it was created.
+ * @see buildControlCommand
+ */
+ public static final int FLAG_RELEASE_MEDIA_SESSION = 0x08;
+
+ private MediaSessionTestHelperConstants() {
+ // Prevent from the instantiation.
+ }
+
+ /**
+ * Builds the control command for the media session test helper app.
+ *
+ * @param userId user id to send the command
+ * @param flag bit masked flag among {@link #FLAG_CREATE_MEDIA_SESSION},
+ * {@link #FLAG_SET_MEDIA_SESSION_ACTIVE}, {@link #FLAG_SET_MEDIA_SESSION_INACTIVE},
+ * and {@link #FLAG_RELEASE_MEDIA_SESSION}. If multiple flags are specificed,
+ * operations will be exceuted in order.
+ **/
+ public static String buildControlCommand(int userId, int flag) {
+ return "am start-foreground-service --user " + userId + " -a " + ACTION_CONTROL + " --ei "
+ + EXTRA_CONTROL_COMMAND + " " + flag + " " + MEDIA_SESSION_TEST_HELPER_PKG;
+ }
+}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
new file mode 100644
index 0000000..ef8ba5b
--- /dev/null
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -0,0 +1,330 @@
+/*
+ * 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.media.cts;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.ddmlib.testrunner.TestResult;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
+import com.android.ddmlib.testrunner.TestRunResult;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ * Base class for host-side tests for multi-user aware media APIs.
+ */
+public class BaseMultiUserTest extends DeviceTestCase implements IBuildReceiver {
+ private static final String RUNNER = "android.support.test.runner.AndroidJUnitRunner";
+
+ /**
+ * The defined timeout (in milliseconds) is used as a maximum waiting time when expecting the
+ * command output from the device. At any time, if the shell command does not output anything
+ * for a period longer than the defined timeout the Tradefed run terminates.
+ */
+ private static final long DEFAULT_SHELL_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+
+ /**
+ * Instrumentation test runner argument key used for individual test timeout
+ **/
+ protected static final String TEST_TIMEOUT_INST_ARGS_KEY = "timeout_msec";
+
+ /**
+ * Sets timeout (in milliseconds) that will be applied to each test. In the
+ * event of a test timeout it will log the results and proceed with executing the next test.
+ */
+ private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(5);
+ private static final String SETTINGS_PACKAGE_VERIFIER_NAMESPACE = "global";
+ private static final String SETTINGS_PACKAGE_VERIFIER_NAME = "package_verifier_enable";
+
+ /**
+ * User ID for all users.
+ * The value is from the UserHandle class.
+ */
+ protected static final int USER_ALL = -1;
+
+ /**
+ * User ID for the system user.
+ * The value is from the UserHandle class.
+ */
+ protected static final int USER_SYSTEM = 0;
+
+ private IBuildInfo mCtsBuild;
+ private String mPackageVerifier;
+
+ private Set<String> mExistingPackages;
+ private List<Integer> mExistingUsers;
+
+ @Override
+ protected void setUp() throws Exception {
+ // Ensure that build has been set before test is run.
+ assertNotNull(mCtsBuild);
+ mExistingPackages = getDevice().getInstalledPackageNames();
+
+ // Disable the package verifier to avoid the dialog when installing an app
+ mPackageVerifier = getSettings(SETTINGS_PACKAGE_VERIFIER_NAMESPACE,
+ SETTINGS_PACKAGE_VERIFIER_NAME, USER_ALL);
+ putSettings(SETTINGS_PACKAGE_VERIFIER_NAMESPACE,
+ SETTINGS_PACKAGE_VERIFIER_NAME, "0", USER_ALL);
+
+ mExistingUsers = new ArrayList();
+ int primaryUserId = getDevice().getPrimaryUserId();
+ mExistingUsers.add(primaryUserId);
+ mExistingUsers.add(USER_SYSTEM);
+
+ executeShellCommand("am switch-user " + primaryUserId);
+ executeShellCommand("wm dismiss-keyguard");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // Reset the package verifier setting to its original value.
+ putSettings(SETTINGS_PACKAGE_VERIFIER_NAMESPACE, SETTINGS_PACKAGE_VERIFIER_NAME,
+ mPackageVerifier, USER_ALL);
+
+ // Remove users created during the test.
+ for (int userId : getDevice().listUsers()) {
+ if (!mExistingUsers.contains(userId)) {
+ removeUser(userId);
+ }
+ }
+ // Remove packages installed during the test.
+ for (String packageName : getDevice().getUninstallablePackageNames()) {
+ if (mExistingPackages.contains(packageName)) {
+ continue;
+ }
+ CLog.d("Removing leftover package: " + packageName);
+ getDevice().uninstallPackage(packageName);
+ }
+ super.tearDown();
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ /**
+ * Installs the app as if the user of the ID {@param userId} has installed the app.
+ *
+ * @param appFileName file name of the app.
+ * @param userId user ID to install the app against.
+ */
+ protected void installAppAsUser(String appFileName, int userId)
+ throws FileNotFoundException, DeviceNotAvailableException {
+ CLog.d("Installing app " + appFileName + " for user " + userId);
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mCtsBuild);
+ String result = getDevice().installPackageForUser(
+ buildHelper.getTestFile(appFileName), true, true, userId, "-t");
+ assertNull("Failed to install " + appFileName + " for user " + userId + ": " + result,
+ result);
+ }
+
+ /**
+ * Excutes shell command and returns the result.
+ *
+ * @param command command to run.
+ * @return result from the command. If the result was {@code null}, empty string ("") will be
+ * returned instead. Otherwise, trimmed result will be returned.
+ */
+ protected @Nonnull String executeShellCommand(final String command) throws Exception {
+ CLog.d("Starting command " + command);
+ String commandOutput = getDevice().executeShellCommand(command);
+ CLog.d("Output for command " + command + ": " + commandOutput);
+ return commandOutput != null ? commandOutput.trim() : "";
+ }
+
+ private int createAndStartUser(String extraParam) throws Exception {
+ String command = "pm create-user" + extraParam + " TestUser_" + System.currentTimeMillis();
+ String commandOutput = executeShellCommand(command);
+
+ String[] tokens = commandOutput.split("\\s+");
+ assertTrue(tokens.length > 0);
+ assertEquals("Success:", tokens[0]);
+ int userId = Integer.parseInt(tokens[tokens.length-1]);
+
+ // Start user for MediaSessionService to notice the created user.
+ getDevice().startUser(userId);
+ return userId;
+ }
+
+ /**
+ * Creates and starts a new user.
+ */
+ protected int createAndStartUser() throws Exception {
+ return createAndStartUser("");
+ }
+
+ /**
+ * Creates and starts a restricted profile for the {@param parentUserId}.
+ *
+ * @param parentUserId parent user id.
+ */
+ protected int createAndStartRestrictedProfile(int parentUserId) throws Exception {
+ return createAndStartUser(" --profileOf " + parentUserId + " --restricted");
+ }
+
+ /**
+ * Creates and starts a managed profile for the {@param parentUserId}.
+ *
+ * @param parentUserId parent user id.
+ */
+ protected int createAndStartManagedProfile(int parentUserId) throws Exception {
+ return createAndStartUser(" --profileOf " + parentUserId + " --managed");
+ }
+
+ /**
+ * Removes the user that is created during the test.
+ * <p>It will be no-op if the user cannot be removed or doesn't exist.
+ *
+ * @param userId user ID to remove.
+ */
+ protected void removeUser(int userId) throws Exception {
+ if (getDevice().listUsers().contains(userId) && userId != USER_SYSTEM
+ && !mExistingUsers.contains(userId)) {
+ // Don't log output, as tests sometimes set no debug user restriction, which
+ // causes this to fail, we should still continue and remove the user.
+ String stopUserCommand = "am stop-user -w -f " + userId;
+ CLog.d("Stopping and removing user " + userId);
+ getDevice().executeShellCommand(stopUserCommand);
+ assertTrue("Couldn't remove user", getDevice().removeUser(userId));
+ }
+ }
+
+ /**
+ * Runs tests on the device as if it's {@param userId}.
+ *
+ * @param pkgName test package file name that contains the {@link AndroidTestCase}
+ * @param testClassName Class name to test within the test package. Can be {@code null} if you
+ * want to run all test classes in the package.
+ * @param testMethodName Method name to test within the test class. Can be {@code null} if you
+ * want to run all test methods in the class. Will be ignored if {@param testClassName} is
+ * {@code null}.
+ * @param userId user ID to run the tests as.
+ */
+ protected void runDeviceTestsAsUser(
+ String pkgName, @Nullable String testClassName,
+ @Nullable String testMethodName, int userId) throws DeviceNotAvailableException {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = pkgName + testClassName;
+ }
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+ pkgName, RUNNER, getDevice().getIDevice());
+ testRunner.setMaxTimeToOutputResponse(DEFAULT_SHELL_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ testRunner.addInstrumentationArg(
+ TEST_TIMEOUT_INST_ARGS_KEY, Long.toString(DEFAULT_TEST_TIMEOUT_MILLIS));
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ } else if (testClassName != null) {
+ testRunner.setClassName(testClassName);
+ }
+
+ CollectingTestListener listener = new CollectingTestListener();
+ assertTrue(getDevice().runInstrumentationTestsAsUser(testRunner, userId, listener));
+
+ final TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ throw new AssertionError("Failed to successfully run device tests for "
+ + result.getName() + ": " + result.getRunFailureMessage());
+ }
+ if (result.getNumTests() == 0) {
+ throw new AssertionError("No tests were run on the device");
+ }
+
+ if (result.hasFailedTests()) {
+ // Build a meaningful error message
+ StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+ for (Map.Entry<TestIdentifier, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+ }
+
+ /**
+ * Checks whether it is possible to create the desired number of users.
+ */
+ protected boolean canCreateAdditionalUsers(int numberOfUsers)
+ throws DeviceNotAvailableException {
+ return getDevice().listUsers().size() + numberOfUsers <=
+ getDevice().getMaxNumberOfUsersSupported();
+ }
+
+ /**
+ * Gets the system setting as a string from the system settings provider for the user.
+ *
+ * @param namespace namespace of the setting.
+ * @param name name of the setting.
+ * @param userId user ID to query the setting. Can be {@link #USER_ALL}.
+ * @return value of the system setting provider with the given namespace and name.
+ * {@code null}, empty string, or "null" will be returned to the empty string ("") instead.
+ */
+ protected @Nonnull String getSettings(@Nonnull String namespace, @Nonnull String name,
+ int userId) throws Exception {
+ String userFlag = (userId == USER_ALL) ? "" : " --user " + userId;
+ String commandOutput = executeShellCommand(
+ "settings" + userFlag + " get " + namespace + " " + name);
+ if (commandOutput == null || commandOutput.isEmpty() || commandOutput.equals("null")) {
+ commandOutput = "";
+ }
+ return commandOutput;
+ }
+
+ /**
+ * Puts the string to the system settings provider for the user.
+ * <p>This deletes the setting for an empty {@param value} as 'settings put' doesn't allow
+ * putting empty value.
+ *
+ * @param namespace namespace of the setting.
+ * @param name name of the setting.
+ * @param value value of the system setting provider with the given namespace and name.
+ * @param userId user ID to set the setting. Can be {@link #USER_ALL}.
+ */
+ protected void putSettings(@Nonnull String namespace, @Nonnull String name,
+ @Nullable String value, int userId) throws Exception {
+ if (value == null || value.isEmpty()) {
+ // Delete the setting if the value is null or empty as 'settings put' doesn't accept
+ // them.
+ // Ignore userId here because 'settings delete' doesn't support it.
+ executeShellCommand("settings delete " + namespace + " " + name);
+ } else {
+ String userFlag = (userId == USER_ALL) ? "" : " --user " + userId;
+ executeShellCommand("settings" + userFlag + " put " + namespace + " " + name
+ + " " + value);
+ }
+ }
+}
diff --git a/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
new file mode 100644
index 0000000..d665f5f
--- /dev/null
+++ b/hostsidetests/media/src/android/media/session/cts/MediaSessionManagerHostTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.media.session.cts;
+
+import static android.media.cts.MediaSessionTestHelperConstants.FLAG_CREATE_MEDIA_SESSION;
+import static android.media.cts.MediaSessionTestHelperConstants.FLAG_SET_MEDIA_SESSION_ACTIVE;
+import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_APK;
+import static android.media.cts.MediaSessionTestHelperConstants.MEDIA_SESSION_TEST_HELPER_PKG;
+
+import android.media.cts.BaseMultiUserTest;
+import android.media.cts.MediaSessionTestHelperConstants;
+
+import android.platform.test.annotations.RequiresDevice;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.StringJoiner;
+import java.util.StringTokenizer;
+
+/**
+ * Host-side test for the media session manager that installs and runs device-side tests after the
+ * proper device setup.
+ * <p>Corresponding device-side tests are written in the {@link #DEVICE_SIDE_TEST_CLASS}
+ * which is in the {@link #DEVICE_SIDE_TEST_APK}.
+ */
+public class MediaSessionManagerHostTest extends BaseMultiUserTest {
+ /**
+ * Package name of the device-side tests.
+ */
+ private static final String DEVICE_SIDE_TEST_PKG = "android.media.session.cts";
+ /**
+ * Package file name (.apk) for the device-side tests.
+ */
+ private static final String DEVICE_SIDE_TEST_APK = "CtsMediaSessionHostTestApp.apk";
+ /**
+ * Fully qualified class name for the device-side tests.
+ */
+ private static final String DEVICE_SIDE_TEST_CLASS =
+ "android.media.session.cts.MediaSessionManagerTest";
+
+ private static final String SETTINGS_NOTIFICATION_LISTENER_NAMESPACE = "secure";
+ private static final String SETTINGS_NOTIFICATION_LISTENER_NAME =
+ "enabled_notification_listeners";
+
+ // Keep the original notification listener list to clean up.
+ private Map<Integer, String> mNotificationListeners;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mNotificationListeners = new HashMap<>();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ // Cleanup
+ for (int userId : mNotificationListeners.keySet()) {
+ String notificationListener = mNotificationListeners.get(userId);
+ putSettings(SETTINGS_NOTIFICATION_LISTENER_NAMESPACE,
+ SETTINGS_NOTIFICATION_LISTENER_NAME, notificationListener, userId);
+ }
+ super.tearDown();
+ }
+
+ /**
+ * Tests {@link MediaSessionManager#getActiveSessions} with the multi-users environment.
+ */
+ @RequiresDevice
+ public void testGetActiveSessions() throws Exception {
+ // Ensure that the previously running media session test helper app doesn't exist.
+ getDevice().uninstallPackage(MEDIA_SESSION_TEST_HELPER_PKG);
+
+ int primaryUserId = getDevice().getPrimaryUserId();
+
+ allowGetActiveSessionForTest(primaryUserId);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, primaryUserId);
+ runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
+
+ installAppAsUser(MEDIA_SESSION_TEST_HELPER_APK, primaryUserId);
+ sendControlCommand(primaryUserId, FLAG_CREATE_MEDIA_SESSION);
+ runTest("testGetActiveSessions_noMediaSessionFromMediaSessionTestHelper");
+
+ sendControlCommand(primaryUserId, FLAG_SET_MEDIA_SESSION_ACTIVE);
+ runTest("testGetActiveSessions_hasMediaSessionFromMediaSessionTestHelper");
+
+ if (!canCreateAdditionalUsers(1)) {
+ CLog.w("Cannot create a new user. Skipping multi-user test cases.");
+ return;
+ }
+
+ // Test if another user can get the session.
+ int newUser = createAndStartUser();
+ installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+ allowGetActiveSessionForTest(newUser);
+ runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
+ removeUser(newUser);
+
+ // Test if another managed profile can get the session.
+ // Remove the created user first not to exceed system's user number limit.
+ newUser = createAndStartManagedProfile(primaryUserId);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+ allowGetActiveSessionForTest(newUser);
+ runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
+ removeUser(newUser);
+
+ // Test if another restricted profile can get the session.
+ // Remove the created user first not to exceed system's user number limit.
+ newUser = createAndStartRestrictedProfile(primaryUserId);
+ installAppAsUser(DEVICE_SIDE_TEST_APK, newUser);
+ allowGetActiveSessionForTest(newUser);
+ runTestAsUser("testGetActiveSessions_noMediaSession", newUser);
+ }
+
+ private void runTest(String testMethodName) throws DeviceNotAvailableException {
+ runTestAsUser(testMethodName, getDevice().getPrimaryUserId());
+ }
+
+ private void runTestAsUser(String testMethodName, int userId)
+ throws DeviceNotAvailableException {
+ runDeviceTestsAsUser(DEVICE_SIDE_TEST_PKG, DEVICE_SIDE_TEST_CLASS,
+ testMethodName, userId);
+ }
+
+ /**
+ * Allows the {@link #DEVICE_SIDE_TEST_CLASS} to call
+ * {@link MediaSessionManager#getActiveSessions} for testing.
+ * <p>{@link MediaSessionManager#getActiveSessions} bypasses the permission check if the
+ * caller is the enabled notification listener. This method uses the behavior by making
+ * {@link #DEVICE_SIDE_TEST_CLASS} as the notification listener. So any change in this
+ * should be also applied to the class.
+ * <p>Note that the device-side test {@link android.media.cts.MediaSessionManagerTest} already
+ * covers the test for failing {@link MediaSessionManager#getActiveSessions} without the
+ * permission nor the notification listener.
+ */
+ private void allowGetActiveSessionForTest(int userId) throws Exception {
+ final String NOTIFICATION_LISTENER_DELIM = ":";
+ if (mNotificationListeners.get(userId) != null) {
+ // Already enabled.
+ return;
+ }
+ String list = getSettings(SETTINGS_NOTIFICATION_LISTENER_NAMESPACE,
+ SETTINGS_NOTIFICATION_LISTENER_NAME, userId);
+
+ String notificationListener = DEVICE_SIDE_TEST_PKG + "/" + DEVICE_SIDE_TEST_CLASS;
+ // Ensure that the list doesn't contain notificationListener already.
+ // This can happen if the test is killed while running.
+ StringTokenizer tokenizer = new StringTokenizer(list, NOTIFICATION_LISTENER_DELIM);
+ StringJoiner joiner = new StringJoiner(NOTIFICATION_LISTENER_DELIM);
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ if (!token.isEmpty() && !token.equals(notificationListener)) {
+ joiner.add(token);
+ }
+ }
+ list = joiner.toString();
+ // Preserve the original list.
+ mNotificationListeners.put(userId, list);
+ // Allow get active sessions by setting notification listener.
+ joiner.add(notificationListener);
+ putSettings(SETTINGS_NOTIFICATION_LISTENER_NAMESPACE,
+ SETTINGS_NOTIFICATION_LISTENER_NAME, joiner.toString(), userId);
+ }
+
+ private void sendControlCommand(int userId, int flag) throws Exception {
+ executeShellCommand(MediaSessionTestHelperConstants.buildControlCommand(userId, flag));
+ }
+}
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
index f60abfa..79d3c3f 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/src/android/server/cts/PipActivity.java
@@ -21,8 +21,8 @@
import android.app.Activity;
import android.app.ActivityOptions;
+import android.app.PictureInPictureParams;
import android.content.BroadcastReceiver;
-import android.app.PictureInPictureArgs;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -32,6 +32,7 @@
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
+import android.util.Rational;
import android.view.WindowManager;
public class PipActivity extends AbstractLifecycleLogActivity {
@@ -58,12 +59,23 @@
// Calls enterPictureInPicture() on creation
private static final String EXTRA_ENTER_PIP = "enter_pip";
// Used with EXTRA_AUTO_ENTER_PIP, value specifies the aspect ratio to enter PIP with
- private static final String EXTRA_ENTER_PIP_ASPECT_RATIO = "enter_pip_aspect_ratio";
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR =
+ "enter_pip_aspect_ratio_numerator";
+ // Used with EXTRA_AUTO_ENTER_PIP, value specifies the aspect ratio to enter PIP with
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR =
+ "enter_pip_aspect_ratio_denominator";
// Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value
- private static final String EXTRA_SET_ASPECT_RATIO = "set_aspect_ratio";
+ private static final String EXTRA_SET_ASPECT_RATIO_NUMERATOR = "set_aspect_ratio_numerator";
+ // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value
+ private static final String EXTRA_SET_ASPECT_RATIO_DENOMINATOR = "set_aspect_ratio_denominator";
// Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value with a
// fixed delay
- private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY = "set_aspect_ratio_with_delay";
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR =
+ "set_aspect_ratio_with_delay_numerator";
+ // Calls setPictureInPictureAspectRatio with the aspect ratio specified in the value with a
+ // fixed delay
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR =
+ "set_aspect_ratio_with_delay_denominator";
// Adds a click listener to finish this activity when it is clicked
private static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
// Calls requestAutoEnterPictureInPicture() with the value provided
@@ -102,14 +114,17 @@
startIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(startIntent);
- if (intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY)) {
+ if (intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR)
+ && intent.hasExtra(EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR)) {
// Ugly, but required to wait for the startActivity to actually start
// the activity...
mHandler.postDelayed(() -> {
- PictureInPictureArgs args = new PictureInPictureArgs();
- args.setAspectRatio(Float.valueOf(intent.getStringExtra(
- EXTRA_SET_ASPECT_RATIO_WITH_DELAY)));
- setPictureInPictureArgs(args);
+ final PictureInPictureParams.Builder builder =
+ new PictureInPictureParams.Builder();
+ builder.setAspectRatio(getAspectRatio(intent,
+ EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR,
+ EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR));
+ setPictureInPictureParams(builder.build());
}, 100);
}
break;
@@ -142,26 +157,33 @@
// Enter picture in picture with the given aspect ratio if provided
if (getIntent().hasExtra(EXTRA_ENTER_PIP)) {
- if (getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO)) {
+ if (getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR)
+ && getIntent().hasExtra(EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR)) {
try {
- final float aspectRatio = Float.valueOf(getIntent().getStringExtra(
- EXTRA_ENTER_PIP_ASPECT_RATIO));
- enterPictureInPictureMode(new PictureInPictureArgs(aspectRatio, null));
+ final PictureInPictureParams.Builder builder =
+ new PictureInPictureParams.Builder();
+ builder.setAspectRatio(getAspectRatio(getIntent(),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR,
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR));
+ enterPictureInPictureMode(builder.build());
} catch (Exception e) {
// This call can fail intentionally if the aspect ratio is too extreme
}
} else {
- enterPictureInPictureMode();
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}
}
// We need to wait for either enterPictureInPicture() or requestAutoEnterPictureInPicture()
// to be called before setting the aspect ratio
- if (getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO)) {
- final float aspectRatio = Float.valueOf(getIntent().getStringExtra(
- EXTRA_SET_ASPECT_RATIO));
+ if (getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO_NUMERATOR)
+ && getIntent().hasExtra(EXTRA_SET_ASPECT_RATIO_DENOMINATOR)) {
+ final PictureInPictureParams.Builder builder =
+ new PictureInPictureParams.Builder();
+ builder.setAspectRatio(getAspectRatio(getIntent(),
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, EXTRA_SET_ASPECT_RATIO_DENOMINATOR));
try {
- setPictureInPictureArgs(new PictureInPictureArgs(aspectRatio, null));
+ setPictureInPictureParams(builder.build());
} catch (Exception e) {
// This call can fail intentionally if the aspect ratio is too extreme
}
@@ -214,7 +236,7 @@
// Enter PIP on move to background
if (getIntent().hasExtra(EXTRA_ENTER_PIP_ON_PAUSE)) {
- enterPictureInPictureMode();
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}
}
@@ -223,7 +245,7 @@
super.onStop();
if (getIntent().hasExtra(EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP) && !mEnteredPictureInPicture) {
- Log.w("PipActivity", "Unexpected onStop() called before entering picture-in-picture");
+ Log.w(TAG, "Unexpected onStop() called before entering picture-in-picture");
finish();
}
}
@@ -239,6 +261,13 @@
public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
+ // Fail early if the activity state does not match the dispatched state
+ if (isInPictureInPictureMode() != isInPictureInPictureMode) {
+ Log.w(TAG, "Received onPictureInPictureModeChanged mode=" + isInPictureInPictureMode
+ + " activityState=" + isInPictureInPictureMode());
+ finish();
+ }
+
// Mark that we've entered picture-in-picture so that we can stop checking for
// EXTRA_ASSERT_NO_ON_STOP_BEFORE_PIP
if (isInPictureInPictureMode) {
@@ -250,7 +279,7 @@
// checking that the stacks ever changed). Therefor, we need to delay here slightly to
// allow the tests to verify that the stacks have changed before re-entering.
mHandler.postDelayed(() -> {
- enterPictureInPictureMode();
+ enterPictureInPictureMode(new PictureInPictureParams.Builder().build());
}, 1000);
}
}
@@ -284,4 +313,13 @@
protected String getTag() {
return TAG;
}
+
+ /**
+ * @return a {@link Rational} aspect ratio from the given intent and extras.
+ */
+ private Rational getAspectRatio(Intent intent, String extraNum, String extraDenom) {
+ return new Rational(
+ Integer.valueOf(intent.getStringExtra(extraNum)),
+ Integer.valueOf(intent.getStringExtra(extraDenom)));
+ }
}
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 038eb8d..65f507e 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerPinnedStackTests.java
@@ -49,9 +49,16 @@
private static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
private static final String EXTRA_ENTER_PIP = "enter_pip";
- private static final String EXTRA_ENTER_PIP_ASPECT_RATIO = "enter_pip_aspect_ratio";
- private static final String EXTRA_SET_ASPECT_RATIO = "set_aspect_ratio";
- private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY = "set_aspect_ratio_with_delay";
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR =
+ "enter_pip_aspect_ratio_numerator";
+ private static final String EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR =
+ "enter_pip_aspect_ratio_denominator";
+ private static final String EXTRA_SET_ASPECT_RATIO_NUMERATOR = "set_aspect_ratio_numerator";
+ private static final String EXTRA_SET_ASPECT_RATIO_DENOMINATOR = "set_aspect_ratio_denominator";
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR =
+ "set_aspect_ratio_with_delay_numerator";
+ private static final String EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR =
+ "set_aspect_ratio_with_delay_denominator";
private static final String EXTRA_ENTER_PIP_ON_PAUSE = "enter_pip_on_pause";
private static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
private static final String EXTRA_START_ACTIVITY = "start_activity";
@@ -91,11 +98,13 @@
private static final float FLOAT_COMPARE_EPSILON = 0.005f;
// Corresponds to com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio
- private static final float MIN_ASPECT_RATIO = 1f / 2.39f;
- private static final float BELOW_MIN_ASPECT_RATIO = MIN_ASPECT_RATIO - FLOAT_COMPARE_EPSILON;
+ private static final int MIN_ASPECT_RATIO_NUMERATOR = 100;
+ private static final int MIN_ASPECT_RATIO_DENOMINATOR = 239;
+ private static final int BELOW_MIN_ASPECT_RATIO_DENOMINATOR = MIN_ASPECT_RATIO_DENOMINATOR + 1;
// Corresponds to com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio
- private static final float MAX_ASPECT_RATIO = 2.39f;
- private static final float ABOVE_MAX_ASPECT_RATIO = MAX_ASPECT_RATIO + FLOAT_COMPARE_EPSILON;
+ private static final int MAX_ASPECT_RATIO_NUMERATOR = 239;
+ private static final int MAX_ASPECT_RATIO_DENOMINATOR = 100;
+ private static final int ABOVE_MAX_ASPECT_RATIO_NUMERATOR = MAX_ASPECT_RATIO_NUMERATOR + 1;
public void testEnterPictureInPictureMode() throws Exception {
pinnedStackTester(getAmStartCmd(PIP_ACTIVITY, EXTRA_ENTER_PIP, "true"), PIP_ACTIVITY,
@@ -270,42 +279,44 @@
}
public void testEnterPipAspectRatioMin() throws Exception {
- testEnterPipAspectRatio(MAX_ASPECT_RATIO);
+ testEnterPipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testEnterPipAspectRatioMax() throws Exception {
- testEnterPipAspectRatio(MIN_ASPECT_RATIO);
+ testEnterPipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testEnterPipAspectRatio(float aspectRatio) throws Exception {
+ private void testEnterPipAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
// Assert that we have entered PIP and that the aspect ratio is correct
Rectangle pinnedStackBounds =
mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getBounds();
assertTrue(floatEquals((float) pinnedStackBounds.width / pinnedStackBounds.height,
- aspectRatio));
+ (float) num / denom));
}
public void testResizePipAspectRatioMin() throws Exception {
- testResizePipAspectRatio(MIN_ASPECT_RATIO);
+ testResizePipAspectRatio(MIN_ASPECT_RATIO_NUMERATOR, MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testResizePipAspectRatioMax() throws Exception {
- testResizePipAspectRatio(MAX_ASPECT_RATIO);
+ testResizePipAspectRatio(MAX_ASPECT_RATIO_NUMERATOR, MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testResizePipAspectRatio(float aspectRatio) throws Exception {
+ private void testResizePipAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_SET_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
// Hacky, but we need to wait for the enterPictureInPicture animation to complete and
@@ -314,7 +325,8 @@
mAmWmState.waitForWithAmState(mDevice, (state) -> {
Rectangle pinnedStackBounds = state.getStackById(PINNED_STACK_ID).getBounds();
boolean isValidAspectRatio = floatEquals(
- (float) pinnedStackBounds.width / pinnedStackBounds.height, aspectRatio);
+ (float) pinnedStackBounds.width / pinnedStackBounds.height,
+ (float) num / denom);
result[0] = isValidAspectRatio;
return isValidAspectRatio;
}, "Waiting for pinned stack to be resized");
@@ -322,45 +334,54 @@
}
public void testEnterPipExtremeAspectRatioMin() throws Exception {
- testEnterPipExtremeAspectRatio(BELOW_MIN_ASPECT_RATIO);
+ testEnterPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
+ BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testEnterPipExtremeAspectRatioMax() throws Exception {
- testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO);
+ testEnterPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
+ MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testEnterPipExtremeAspectRatio(float aspectRatio) throws Exception {
+ private void testEnterPipExtremeAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
// Assert that we could not create a pinned stack with an extreme aspect ratio
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackDoesNotExist();
}
public void testSetPipExtremeAspectRatioMin() throws Exception {
- testSetPipExtremeAspectRatio(BELOW_MIN_ASPECT_RATIO);
+ testSetPipExtremeAspectRatio(MIN_ASPECT_RATIO_NUMERATOR,
+ BELOW_MIN_ASPECT_RATIO_DENOMINATOR);
}
public void testSetPipExtremeAspectRatioMax() throws Exception {
- testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO);
+ testSetPipExtremeAspectRatio(ABOVE_MAX_ASPECT_RATIO_NUMERATOR,
+ MAX_ASPECT_RATIO_DENOMINATOR);
}
- private void testSetPipExtremeAspectRatio(float aspectRatio) throws Exception {
+ private void testSetPipExtremeAspectRatio(int num, int denom) throws Exception {
if (!supportsPip()) return;
// Try to resize the a normal pinned stack to an extreme aspect ratio and ensure that
// fails (the aspect ratio remains the same)
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP, "true",
- EXTRA_ENTER_PIP_ASPECT_RATIO, Float.toString(MAX_ASPECT_RATIO),
- EXTRA_SET_ASPECT_RATIO, Float.toString(aspectRatio));
+ EXTRA_ENTER_PIP_ASPECT_RATIO_NUMERATOR,
+ Integer.toString(MAX_ASPECT_RATIO_NUMERATOR),
+ EXTRA_ENTER_PIP_ASPECT_RATIO_DENOMINATOR,
+ Integer.toString(MAX_ASPECT_RATIO_DENOMINATOR),
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(num),
+ EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(denom));
assertPinnedStackExists();
Rectangle pinnedStackBounds =
mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getBounds();
assertTrue(floatEquals((float) pinnedStackBounds.width / pinnedStackBounds.height,
- MAX_ASPECT_RATIO));
+ (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR));
}
public void testDisallowPipLaunchFromStoppedActivity() throws Exception {
@@ -434,7 +455,8 @@
// Launch the PIP activity on pause, and set the aspect ratio
launchActivity(PIP_ACTIVITY,
EXTRA_ENTER_PIP_ON_PAUSE, "true",
- EXTRA_SET_ASPECT_RATIO, Float.toString(MAX_ASPECT_RATIO));
+ EXTRA_SET_ASPECT_RATIO_NUMERATOR, Integer.toString(MAX_ASPECT_RATIO_NUMERATOR),
+ EXTRA_SET_ASPECT_RATIO_DENOMINATOR, Integer.toString(MAX_ASPECT_RATIO_DENOMINATOR));
// Go home while the pip activity is open to trigger auto-PIP
launchHomeActivity();
@@ -446,7 +468,8 @@
mAmWmState.waitForWithAmState(mDevice, (state) -> {
Rectangle pinnedStackBounds = state.getStackById(PINNED_STACK_ID).getBounds();
boolean isValidAspectRatio = floatEquals(
- (float) pinnedStackBounds.width / pinnedStackBounds.height, MAX_ASPECT_RATIO);
+ (float) pinnedStackBounds.width / pinnedStackBounds.height,
+ (float) MAX_ASPECT_RATIO_NUMERATOR / MAX_ASPECT_RATIO_DENOMINATOR);
result[0] = isValidAspectRatio;
return isValidAspectRatio;
}, "Waiting for pinned stack to be resized");
@@ -806,8 +829,9 @@
// Trigger it to go back to fullscreen and try to set the aspect ratio, and ensure that the
// call to set the aspect ratio did not prevent the PiP from returning to fullscreen
- executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_EXPAND_PIP + " -e "
- + EXTRA_SET_ASPECT_RATIO_WITH_DELAY + " 1.23456789");
+ executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_EXPAND_PIP
+ + " -e " + EXTRA_SET_ASPECT_RATIO_WITH_DELAY_NUMERATOR + " 123456789"
+ + " -e " + EXTRA_SET_ASPECT_RATIO_WITH_DELAY_DENOMINATOR + " 100000000");
mAmWmState.waitForValidState(mDevice, PIP_ACTIVITY, FULLSCREEN_WORKSPACE_STACK_ID);
assertPinnedStackDoesNotExist();
}
@@ -851,6 +875,9 @@
assertPinnedStackExists();
int taskId = mAmWmState.getAmState().getStackById(PINNED_STACK_ID).getTopTask().mTaskId;
+ // Ensure that we don't any any other overlays as a result of launching into PIP
+ launchHomeActivity();
+
// Launch task overlay activity into PiP activity task
launchActivityAsTaskOverlay(TRANSLUCENT_TEST_ACTIVITY, taskId, PINNED_STACK_ID);
@@ -858,10 +885,7 @@
executeShellCommand("am broadcast -a " + PIP_ACTIVITY_ACTION_FINISH);
mAmWmState.waitForWithAmState(mDevice, (amState) -> {
ActivityStack stack = amState.getStackById(PINNED_STACK_ID);
- if (stack != null) {
- return false;
- }
- return true;
+ return stack == null;
}, "Waiting for pinned stack to be removed...");
assertPinnedStackDoesNotExist();
}
@@ -908,15 +932,13 @@
if (expectTopTaskHasActivity) {
ActivityTask topTask = mAmWmState.getAmState().getStackById(
FULLSCREEN_WORKSPACE_STACK_ID).getTopTask();
- Activity topActivity = topTask.mActivities.get(0);
- assertTrue(topActivity.name.equals(ActivityManagerTestBase.getActivityComponentName(
+ assertTrue(topTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
activityName)));
}
if (expectBottomTaskHasActivity) {
ActivityTask bottomTask = mAmWmState.getAmState().getStackById(
FULLSCREEN_WORKSPACE_STACK_ID).getBottomTask();
- Activity bottomActivity = bottomTask.mActivities.get(0);
- assertTrue(bottomActivity.name.equals(ActivityManagerTestBase.getActivityComponentName(
+ assertTrue(bottomTask.containsActivity(ActivityManagerTestBase.getActivityComponentName(
activityName)));
}
}
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
index 6565215..56fed31 100644
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerState.java
@@ -607,6 +607,18 @@
public String getResizeMode() {
return mResizeMode;
}
+
+ /**
+ * @return whether this task contains the given activity.
+ */
+ public boolean containsActivity(String activityName) {
+ for (Activity activity : mActivities) {
+ if (activity.name.equals(activityName)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
static class Activity {
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index 521d5a3..3200409 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -359,7 +359,7 @@
.setSmallIcon(R.drawable.black)
.setContentTitle("notify#" + id)
.setContentText("This is #" + id + "notification ")
- .setTimeout(timeout)
+ .setTimeoutAfter(timeout)
.build();
mNotificationManager.notify(id, notification);
diff --git a/tests/app/src/android/app/cts/NotificationTest.java b/tests/app/src/android/app/cts/NotificationTest.java
index 75f75b2..b3d833f 100644
--- a/tests/app/src/android/app/cts/NotificationTest.java
+++ b/tests/app/src/android/app/cts/NotificationTest.java
@@ -76,11 +76,11 @@
public void testBuilderConstructor() {
mNotification = new Notification.Builder(mContext, CHANNEL.getId()).build();
- assertEquals(CHANNEL.getId(), mNotification.getChannel());
+ assertEquals(CHANNEL.getId(), mNotification.getChannelId());
assertEquals(Notification.BADGE_ICON_NONE, mNotification.getBadgeIconType());
assertNull(mNotification.getShortcutId());
assertEquals(Notification.GROUP_ALERT_ALL, mNotification.getGroupAlertBehavior());
- assertEquals((long) 0, mNotification.getTimeout());
+ assertEquals((long) 0, mNotification.getTimeoutAfter());
}
public void testDescribeContents() {
@@ -94,7 +94,7 @@
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setBadgeIconType(Notification.BADGE_ICON_SMALL)
.setShortcutId(SHORTCUT_ID)
- .setTimeout(TIMEOUT)
+ .setTimeoutAfter(TIMEOUT)
.setSettingsText(SETTING_TEXT)
.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
.build();
@@ -149,8 +149,8 @@
assertEquals(mNotification.iconLevel, result.iconLevel);
assertEquals(mNotification.getShortcutId(), result.getShortcutId());
assertEquals(mNotification.getBadgeIconType(), result.getBadgeIconType());
- assertEquals(mNotification.getTimeout(), result.getTimeout());
- assertEquals(mNotification.getChannel(), result.getChannel());
+ assertEquals(mNotification.getTimeoutAfter(), result.getTimeoutAfter());
+ assertEquals(mNotification.getChannelId(), result.getChannelId());
assertEquals(mNotification.getSettingsText(), result.getSettingsText());
assertEquals(mNotification.getGroupAlertBehavior(), result.getGroupAlertBehavior());
@@ -210,7 +210,7 @@
.setContentIntent(contentIntent)
.setBadgeIconType(Notification.BADGE_ICON_SMALL)
.setShortcutId(SHORTCUT_ID)
- .setTimeout(TIMEOUT)
+ .setTimeoutAfter(TIMEOUT)
.setSettingsText(SETTING_TEXT)
.setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
.build();
@@ -218,10 +218,10 @@
assertEquals(CONTENT_TITLE, mNotification.extras.getString(Notification.EXTRA_TITLE));
assertEquals(1, mNotification.icon);
assertEquals(contentIntent, mNotification.contentIntent);
- assertEquals(CHANNEL.getId(), mNotification.getChannel());
+ assertEquals(CHANNEL.getId(), mNotification.getChannelId());
assertEquals(Notification.BADGE_ICON_SMALL, mNotification.getBadgeIconType());
assertEquals(SHORTCUT_ID, mNotification.getShortcutId());
- assertEquals(TIMEOUT, mNotification.getTimeout());
+ assertEquals(TIMEOUT, mNotification.getTimeoutAfter());
assertEquals(SETTING_TEXT, mNotification.getSettingsText());
assertEquals(Notification.GROUP_ALERT_SUMMARY, mNotification.getGroupAlertBehavior());
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
index 786ff40..430c612 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AuthenticationActivity.java
@@ -62,9 +62,9 @@
final Parcelable result;
if (sResponse != null) {
- result = sResponse.asFillResponse(structure);
+ result = sResponse.asFillResponse((id) -> Helper.findNodeByResourceId(structure, id));
} else if (sDataset != null) {
- result = sDataset.asDataset(structure);
+ result = sDataset.asDataset((id) -> Helper.findNodeByResourceId(structure, id));
} else {
throw new IllegalStateException("no dataset or response");
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index b456dd7..9f5368f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -22,11 +22,11 @@
import static android.autofillservice.cts.Helper.getAutofillIds;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
-import android.autofillservice.cts.CannedFillResponse.Builder;
import android.content.IntentSender;
import android.os.Bundle;
import android.service.autofill.Dataset;
import android.service.autofill.FillCallback;
+import android.service.autofill.FillContext;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
import android.view.autofill.AutofillId;
@@ -38,6 +38,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
/**
* Helper class used to produce a {@link FillResponse} based on expected fields that should be
@@ -66,7 +67,7 @@
private final IntentSender mAuthentication;
private final String[] mAuthenticationIds;
private final String[] mIgnoredIds;
- private final CharSequence mNegativeActionLabel;
+ private final int mNegativeActionStyle;
private final IntentSender mNegativeActionListener;
private final int mFlags;
@@ -81,7 +82,7 @@
mAuthentication = builder.mAuthentication;
mAuthenticationIds = builder.mAuthenticationIds;
mIgnoredIds = builder.mIgnoredIds;
- mNegativeActionLabel = builder.mNegativeActionLabel;
+ mNegativeActionStyle = builder.mNegativeActionStyle;
mNegativeActionListener = builder.mNegativeActionListener;
mFlags = builder.mFlags;
}
@@ -96,45 +97,37 @@
* Creates a new response, replacing the dataset field ids by the real ids from the assist
* structure.
*/
- FillResponse asFillResponse(AssistStructure structure) {
+ FillResponse asFillResponse(Function<String, ViewNode> nodeResolver) {
final FillResponse.Builder builder = new FillResponse.Builder();
if (mDatasets != null) {
for (CannedDataset cannedDataset : mDatasets) {
- final Dataset dataset = cannedDataset.asDataset(structure);
+ final Dataset dataset = cannedDataset.asDataset(nodeResolver);
assertWithMessage("Cannot create datase").that(dataset).isNotNull();
builder.addDataset(dataset);
}
}
if (mRequiredSavableIds != null) {
- final SaveInfo.Builder saveInfo;
-
- if (mRequiredSavableIds == null) {
- saveInfo = new SaveInfo.Builder(mSaveType, null);
- } else {
- saveInfo = new SaveInfo.Builder(mSaveType,
- getAutofillIds(structure, mRequiredSavableIds));
- }
+ final SaveInfo.Builder saveInfo = new SaveInfo.Builder(mSaveType,
+ getAutofillIds(nodeResolver, mRequiredSavableIds));
saveInfo.setFlags(mFlags);
if (mOptionalSavableIds != null) {
- saveInfo.setOptionalIds(getAutofillIds(structure, mOptionalSavableIds));
+ saveInfo.setOptionalIds(getAutofillIds(nodeResolver, mOptionalSavableIds));
}
if (mSaveDescription != null) {
saveInfo.setDescription(mSaveDescription);
}
- if (mNegativeActionLabel != null) {
- saveInfo.setNegativeAction(mNegativeActionLabel, mNegativeActionListener);
- }
+ saveInfo.setNegativeAction(mNegativeActionStyle, mNegativeActionListener);
builder.setSaveInfo(saveInfo.build());
}
if (mIgnoredIds != null) {
- builder.setIgnoredIds(getAutofillIds(structure, mIgnoredIds));
+ builder.setIgnoredIds(getAutofillIds(nodeResolver, mIgnoredIds));
}
return builder
.setClientState(mExtras)
- .setAuthentication(getAutofillIds(structure, mAuthenticationIds), mAuthentication,
- mPresentation)
+ .setAuthentication(getAutofillIds(nodeResolver, mAuthenticationIds),
+ mAuthentication, mPresentation)
.build();
}
@@ -163,7 +156,7 @@
private IntentSender mAuthentication;
private String[] mAuthenticationIds;
private String[] mIgnoredIds;
- private CharSequence mNegativeActionLabel;
+ private int mNegativeActionStyle;
private IntentSender mNegativeActionListener;
private int mFlags;
@@ -246,9 +239,9 @@
/**
* Sets the negative action spec.
*/
- public Builder setNegativeAction(CharSequence label,
+ public Builder setNegativeAction(int style,
IntentSender listener) {
- mNegativeActionLabel = label;
+ mNegativeActionStyle = style;
mNegativeActionListener = listener;
return this;
}
@@ -291,7 +284,7 @@
/**
* Creates a new dataset, replacing the field ids by the real ids from the assist structure.
*/
- Dataset asDataset(AssistStructure structure) {
+ Dataset asDataset(Function<String, ViewNode> nodeResolver) {
final Dataset.Builder builder = (mPresentation == null)
? new Dataset.Builder()
: new Dataset.Builder(mPresentation);
@@ -299,9 +292,8 @@
if (mFieldValues != null) {
for (Map.Entry<String, AutofillValue> entry : mFieldValues.entrySet()) {
final String resourceId = entry.getKey();
- final ViewNode node = findNodeByResourceId(structure, resourceId);
+ final ViewNode node = nodeResolver.apply(resourceId);
if (node == null) {
- dumpStructure("asDataset()", structure);
throw new AssertionError("No node with resource id " + resourceId);
}
final AutofillId id = node.getAutofillId();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index e19fa0c..f1491b4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.UserManager;
import android.service.autofill.Dataset;
+import android.service.autofill.FillContext;
import android.service.autofill.FillResponse;
import android.support.annotation.NonNull;
import android.support.test.InstrumentationRegistry;
@@ -40,8 +41,10 @@
import com.android.compatibility.common.util.SystemUtil;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
/**
* Helper for common funcionalities.
@@ -163,6 +166,15 @@
}
/**
+ * Dump the contexts on logcat.
+ */
+ static void dumpStructure(String message, List<FillContext> contexts) {
+ for (FillContext context : contexts) {
+ dumpStructure(message, context.getStructure());
+ }
+ }
+
+ /**
* Dumps the state of the autofill service on logcat.
*/
static void dumpAutofillService() {
@@ -227,6 +239,19 @@
/**
* Gets a node given its Android resource id, or {@code null} if not found.
*/
+ static ViewNode findNodeByResourceId(ArrayList<FillContext> contexts, String resourceId) {
+ for (FillContext context : contexts) {
+ ViewNode node = findNodeByResourceId(context.getStructure(), resourceId);
+ if (node != null) {
+ return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Gets a node given its Android resource id, or {@code null} if not found.
+ */
static ViewNode findNodeByResourceId(ViewNode node, String resourceId) {
if (resourceId.equals(node.getIdEntry())) {
return node;
@@ -530,15 +555,15 @@
* Creates an array of {@link AutofillId} mapped from the {@code structure} nodes with the given
* {@code resourceIds}.
*/
- static AutofillId[] getAutofillIds(AssistStructure structure, String[] resourceIds) {
+ static AutofillId[] getAutofillIds(Function<String, ViewNode> nodeResolver,
+ String[] resourceIds) {
if (resourceIds == null) return null;
final AutofillId[] requiredIds = new AutofillId[resourceIds.length];
for (int i = 0; i < resourceIds.length; i++) {
final String resourceId = resourceIds[i];
- final ViewNode node = findNodeByResourceId(structure, resourceId);
+ final ViewNode node = nodeResolver.apply(resourceId);
if (node == null) {
- dumpStructure("getAutofillIds()", structure);
throw new AssertionError("No node with savable resourceId " + resourceId);
}
requiredIds[i] = node.getAutofillId();
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 44ca039..61b47af 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -38,6 +38,7 @@
import android.service.autofill.SaveCallback;
import android.util.Log;
+import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@@ -85,21 +86,17 @@
@Override
public void onFillRequest(android.service.autofill.FillRequest request,
CancellationSignal cancellationSignal, FillCallback callback) {
- final AssistStructure structure = request.getStructure();
- if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", structure);
+ if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", request.getFillContexts());
- sReplier.onFillRequest(structure, request.getClientState(), cancellationSignal, callback,
- request.getFlags());
+ sReplier.onFillRequest(request.getFillContexts(), request.getClientState(),
+ cancellationSignal, callback, request.getFlags());
}
@Override
public void onSaveRequest(android.service.autofill.SaveRequest request,
SaveCallback callback) {
- final List<FillContext> contexts = request.getFillContexts();
- final AssistStructure structure = contexts.get(contexts.size() - 1).getStructure();
-
- if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", structure);
- sReplier.onSaveRequest(structure, request.getClientState(), callback);
+ if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", request.getFillContexts());
+ sReplier.onSaveRequest(request.getFillContexts(), request.getClientState(), callback);
}
/**
@@ -152,18 +149,20 @@
*/
static final class FillRequest {
final AssistStructure structure;
+ final ArrayList<FillContext> contexts;
final Bundle data;
final CancellationSignal cancellationSignal;
final FillCallback callback;
final int flags;
- private FillRequest(AssistStructure structure, Bundle data,
+ private FillRequest(ArrayList<FillContext> contexts, Bundle data,
CancellationSignal cancellationSignal, FillCallback callback, int flags) {
- this.structure = structure;
+ this.contexts = contexts;
this.data = data;
this.cancellationSignal = cancellationSignal;
this.callback = callback;
this.flags = flags;
+ structure = contexts.get(contexts.size() - 1).getStructure();
}
}
@@ -173,12 +172,18 @@
* that can be asserted at the end of a test case.
*/
static final class SaveRequest {
+ final List<FillContext> contexts;
final AssistStructure structure;
final Bundle data;
final SaveCallback callback;
- private SaveRequest(AssistStructure structure, Bundle data, SaveCallback callback) {
- this.structure = structure;
+ private SaveRequest(List<FillContext> contexts, Bundle data, SaveCallback callback) {
+ if (contexts != null && contexts.size() > 0) {
+ structure = contexts.get(contexts.size() - 1).getStructure();
+ } else {
+ structure = null;
+ }
+ this.contexts = contexts;
this.data = data;
this.callback = callback;
}
@@ -277,7 +282,7 @@
mSaveRequests.clear();
}
- private void onFillRequest(AssistStructure structure, Bundle data,
+ private void onFillRequest(ArrayList<FillContext> contexts, Bundle data,
CancellationSignal cancellationSignal, FillCallback callback, int flags) {
try {
CannedFillResponse response = null;
@@ -288,7 +293,7 @@
Thread.currentThread().interrupt();
}
if (response == null) {
- dumpStructure("onFillRequest() without response", structure);
+ dumpStructure("onFillRequest() without response", contexts);
throw new IllegalStateException("No CannedResponse");
}
if (response == NO_RESPONSE) {
@@ -296,19 +301,20 @@
return;
}
- final FillResponse fillResponse = response.asFillResponse(structure);
+ final FillResponse fillResponse = response.asFillResponse(
+ (id) -> Helper.findNodeByResourceId(contexts, id));
Log.v(TAG, "onFillRequest(): fillResponse = " + fillResponse);
callback.onSuccess(fillResponse);
} finally {
- mFillRequests.offer(new FillRequest(structure, data, cancellationSignal, callback,
+ mFillRequests.offer(new FillRequest(contexts, data, cancellationSignal, callback,
flags));
}
}
- private void onSaveRequest(AssistStructure structure, Bundle data, SaveCallback callback) {
+ private void onSaveRequest(List<FillContext> contexts, Bundle data, SaveCallback callback) {
Log.d(TAG, "onSaveRequest()");
- mSaveRequests.offer(new SaveRequest(structure, data, callback));
+ mSaveRequests.offer(new SaveRequest(contexts, data, callback));
callback.onSuccess();
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 30cfde7..51f8e12 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -61,7 +61,9 @@
import android.content.IntentFilter;
import android.content.IntentSender;
import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
import android.service.autofill.FillEventHistory;
+import android.service.autofill.SaveInfo;
import android.support.test.rule.ActivityTestRule;
import android.support.test.uiautomator.UiObject2;
import android.view.View;
@@ -334,6 +336,7 @@
}
@Test
+ @Presubmit
public void testAutoFillOneDatasetAndSave() throws Exception {
// Set service.
enableService();
@@ -1146,7 +1149,7 @@
}
@Test
- public void testCustomNegativeSaveButton() throws Exception {
+ public void testRejectStyleNegativeSaveButton() throws Exception {
enableService();
// Set service behavior.
@@ -1159,7 +1162,7 @@
sReplier.addResponse(new CannedFillResponse.Builder()
.setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
- .setNegativeAction("Foo", listener)
+ .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT, listener)
.build());
// Trigger auto-fill.
@@ -1185,7 +1188,8 @@
}, intentFilter);
// Trigger the negative button.
- sUiBot.saveForAutofill(false, SAVE_DATA_TYPE_PASSWORD);
+ sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT,
+ false, SAVE_DATA_TYPE_PASSWORD);
// Wait for the custom action.
assertThat(latch.await(5, TimeUnit.SECONDS)).isTrue();
@@ -1194,6 +1198,55 @@
}
@Test
+ public void testCancelStyleNegativeSaveButton() throws Exception {
+ enableService();
+
+ // Set service behavior.
+
+ final String intentAction = "android.autofillservice.cts.CUSTOM_ACTION";
+
+ // Configure the save UI.
+ final IntentSender listener = PendingIntent.getBroadcast(
+ getContext(), 0, new Intent(intentAction), 0).getIntentSender();
+
+ sReplier.addResponse(new CannedFillResponse.Builder()
+ .setRequiredSavableIds(SAVE_DATA_TYPE_PASSWORD, ID_USERNAME, ID_PASSWORD)
+ .setNegativeAction(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, listener)
+ .build());
+
+ // Trigger auto-fill.
+ mActivity.onUsername(View::requestFocus);
+
+ // Wait for onFill() before proceeding.
+ sReplier.getNextFillRequest();
+
+ // Trigger save.
+ mActivity.onUsername((v) -> v.setText("foo"));
+ mActivity.onPassword((v) -> v.setText("foo"));
+ mActivity.tapLogin();
+
+ // Start watching for the negative intent
+ final CountDownLatch latch = new CountDownLatch(1);
+ final IntentFilter intentFilter = new IntentFilter(intentAction);
+ getContext().registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ getContext().unregisterReceiver(this);
+ latch.countDown();
+ }
+ }, intentFilter);
+
+ // Trigger the negative button.
+ sUiBot.saveForAutofill(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,
+ false, SAVE_DATA_TYPE_PASSWORD);
+
+ // Wait for the custom action.
+ assertThat(latch.await(500, TimeUnit.SECONDS)).isTrue();
+
+ assertNoDanglingSessions();
+ }
+
+ @Test
public void testGetTextInputType() throws Exception {
// Set service.
enableService();
@@ -1253,13 +1306,17 @@
assertThat(usernameContainer.getChildCount()).isEqualTo(2);
}
+ private static final boolean BUG_36171235_FIXED = false;
+
+ @Test
public void testAutofillManuallyOneDataset() throws Exception {
// Set service.
enableService();
+ if (BUG_36171235_FIXED)
// And activity.
mActivity.onUsername((v) -> {
- // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+ v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
// TODO: 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("");
@@ -1274,7 +1331,11 @@
mActivity.expectAutoFill("dude", "sweet");
// Long-press field to trigger AUTOFILL menu.
- sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ if (BUG_36171235_FIXED) {
+ sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ } else {
+ mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
+ }
final FillRequest fillRequest = sReplier.getNextFillRequest();
assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
@@ -1286,10 +1347,12 @@
mActivity.assertAutoFilled();
}
+ @Test
public void testAutofillManuallyTwoDatasetsPickFirst() throws Exception {
autofillManuallyTwoDatasets(true);
}
+ @Test
public void testAutofillManuallyTwoDatasetsPickSecond() throws Exception {
autofillManuallyTwoDatasets(false);
}
@@ -1298,9 +1361,10 @@
// Set service.
enableService();
+ if (BUG_36171235_FIXED)
// And activity.
mActivity.onUsername((v) -> {
- // v.setAutofillMode(AUTOFILL_MODE_MANUAL);
+ v.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
// TODO: 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("");
@@ -1327,7 +1391,11 @@
}
// Long-press field to trigger AUTOFILL menu.
- sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ if (BUG_36171235_FIXED) {
+ sUiBot.getAutofillMenuOption(ID_USERNAME).click();
+ } else {
+ mActivity.onUsername((v) -> mActivity.getAutofillManager().requestAutofill(v));
+ }
final FillRequest fillRequest = sReplier.getNextFillRequest();
assertThat(fillRequest.flags).isEqualTo(FLAG_MANUAL_REQUEST);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
index 32844d4..026cf08 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ManualAuthenticationActivity.java
@@ -54,9 +54,11 @@
if (structure != null) {
Parcelable result;
if (sResponse != null) {
- result = sResponse.asFillResponse(structure);
+ result = sResponse.asFillResponse(
+ (id) -> Helper.findNodeByResourceId(structure, id));
} else if (sDataset != null) {
- result = sDataset.asDataset(structure);
+ result = sDataset.asDataset(
+ (id) -> Helper.findNodeByResourceId(structure, id));
} else {
throw new IllegalStateException("no dataset or response");
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
index 76c8c70..d474dc8 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
@@ -24,8 +24,12 @@
import static com.google.common.truth.Truth.assertThat;
+import android.app.assist.AssistStructure;
+import android.app.assist.AssistStructure.ViewNode;
+import android.os.Bundle;
import android.support.test.rule.ActivityTestRule;
import android.util.Log;
+import android.view.autofill.AutofillValue;
import android.widget.EditText;
import org.junit.Before;
@@ -52,11 +56,17 @@
public void loginOnTwoFragments() throws Exception {
enableService();
try {
- // Set expectations.
+ Bundle clientState = new Bundle();
+ clientState.putString("key", "value1");
sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText1").build());
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField("editText1", "editText1-autofilled")
+ .setPresentation(createPresentation("dataset1"))
+ .build())
+ .setExtras(clientState)
+ .build());
- final InstrumentedAutoFillService.FillRequest[] request =
+ final InstrumentedAutoFillService.FillRequest[] fillRequest =
new InstrumentedAutoFillService.FillRequest[1];
// Trigger autofill
@@ -67,37 +77,123 @@
});
try {
- request[0] = sReplier.getNextFillRequest();
+ fillRequest[0] = sReplier.getNextFillRequest();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, (int) (FILL_TIMEOUT_MS * 2));
- assertThat(findNodeByResourceId(request[0].structure, "editText1")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText2")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText3")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText4")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText5")).isNull();
+ assertThat(fillRequest[0].data).isNull();
- Log.i(LOG_TAG, "Switching Fragments");
+ AssistStructure structure = fillRequest[0].contexts.get(0).getStructure();
+ assertThat(fillRequest[0].contexts.size()).isEqualTo(1);
+ assertThat(findNodeByResourceId(structure, "editText1")).isNotNull();
+ assertThat(findNodeByResourceId(structure, "editText2")).isNotNull();
+ assertThat(findNodeByResourceId(structure, "editText3")).isNull();
+ assertThat(findNodeByResourceId(structure, "editText4")).isNull();
+ assertThat(findNodeByResourceId(structure, "editText5")).isNull();
+
+ // Wait until autofill has been applied
+ sUiBot.selectDataset("dataset1");
+ sUiBot.assertShownByText("editText1-autofilled");
+
+ // Manually fill view
+ mActivity.syncRunOnUiThread(() -> mEditText2.setText("editText2-manually-filled"));
// Replacing the fragment focused a previously unknown view which triggers a new
// partition
+ clientState.putString("key", "value2");
sReplier.addResponse(new CannedFillResponse.Builder()
- .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText3").build());
+ .addDataset(new CannedFillResponse.CannedDataset.Builder()
+ .setField("editText3", "editText3-autofilled")
+ .setField("editText4", "editText4-autofilled")
+ .setPresentation(createPresentation("dataset2"))
+ .build())
+ .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, "editText2", "editText5")
+ .setExtras(clientState)
+ .build());
+ Log.i(LOG_TAG, "Switching Fragments");
mActivity.syncRunOnUiThread(
() -> mActivity.getFragmentManager().beginTransaction().replace(
R.id.rootContainer, new FragmentWithMoreEditTexts(),
FRAGMENT_TAG).commitNow());
+ EditText mEditText5 = mActivity.findViewById(R.id.editText5);
- request[0] = sReplier.getNextFillRequest();
+ fillRequest[0] = sReplier.getNextFillRequest();
- assertThat(findNodeByResourceId(request[0].structure, "editText1")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText2")).isNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText3")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText4")).isNotNull();
- assertThat(findNodeByResourceId(request[0].structure, "editText5")).isNotNull();
+ // The fillRequest should have a fillContext for each partition. The first partition
+ // should be filled in
+ assertThat(fillRequest[0].contexts.size()).isEqualTo(2);
+
+ assertThat(fillRequest[0].data.getString("key")).isEqualTo("value1");
+
+ AssistStructure structure1 = fillRequest[0].contexts.get(0).getStructure();
+ ViewNode editText1Node = findNodeByResourceId(structure1, "editText1");
+ // The actual value in the structure is not updated in FillRequest-contexts, but the
+ // autofill value is. For text views in SaveRequest both are updated, but this is the
+ // only exception.
+ assertThat(editText1Node.getAutofillValue()).isEqualTo(
+ AutofillValue.forText("editText1-autofilled"));
+
+ ViewNode editText2Node = findNodeByResourceId(structure1, "editText2");
+ // Manually filled fields are not send to onFill. They appear in onSave if they are set
+ // as saveable fields.
+ assertThat(editText2Node.getText().toString()).isEqualTo("");
+
+ assertThat(findNodeByResourceId(structure1, "editText3")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText4")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText5")).isNull();
+
+ AssistStructure structure2 = fillRequest[0].contexts.get(1).getStructure();
+
+ assertThat(findNodeByResourceId(structure2, "editText1")).isNull();
+ assertThat(findNodeByResourceId(structure2, "editText2")).isNull();
+ assertThat(findNodeByResourceId(structure2, "editText3")).isNotNull();
+ assertThat(findNodeByResourceId(structure2, "editText4")).isNotNull();
+ assertThat(findNodeByResourceId(structure2, "editText5")).isNotNull();
+
+ // Wait until autofill has been applied
+ sUiBot.selectDataset("dataset2");
+ sUiBot.assertShownByText("editText3-autofilled");
+ sUiBot.assertShownByText("editText4-autofilled");
+
+ // Manually fill view
+ mActivity.syncRunOnUiThread(() -> mEditText5.setText("editText5-manually-filled"));
+
+ // Finish activity and save data
+ mActivity.finish();
+ sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+
+ // The saveRequest should have a fillContext for each partition with all the data
+ InstrumentedAutoFillService.SaveRequest saveRequest = sReplier.getNextSaveRequest();
+ assertThat(saveRequest.contexts.size()).isEqualTo(2);
+
+ assertThat(saveRequest.data.getString("key")).isEqualTo("value2");
+
+ structure1 = saveRequest.contexts.get(0).getStructure();
+ editText1Node = findNodeByResourceId(structure1, "editText1");
+ assertThat(editText1Node.getText().toString()).isEqualTo("editText1-autofilled");
+
+ editText2Node = findNodeByResourceId(structure1, "editText2");
+ assertThat(editText2Node.getText().toString()).isEqualTo("editText2-manually-filled");
+
+ assertThat(findNodeByResourceId(structure1, "editText3")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText4")).isNull();
+ assertThat(findNodeByResourceId(structure1, "editText5")).isNull();
+
+ structure2 = saveRequest.contexts.get(1).getStructure();
+ assertThat(findNodeByResourceId(structure2, "editText1")).isNull();
+ assertThat(findNodeByResourceId(structure2, "editText2")).isNull();
+
+ ViewNode editText3Node = findNodeByResourceId(structure2, "editText3");
+ assertThat(editText3Node.getText().toString()).isEqualTo("editText3-autofilled");
+
+ ViewNode editText4Node = findNodeByResourceId(structure2, "editText4");
+ assertThat(editText4Node.getText().toString()).isEqualTo("editText4-autofilled");
+
+ ViewNode editText5Node = findNodeByResourceId(structure2, "editText5");
+ assertThat(editText5Node.getText().toString()).isEqualTo("editText5-manually-filled");
} finally {
disableService();
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
index 3b8c12a..fa7780a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/UiBot.java
@@ -31,6 +31,7 @@
import android.app.UiAutomation;
import android.content.res.Resources;
import android.os.SystemClock;
+import android.service.autofill.SaveInfo;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
@@ -249,6 +250,10 @@
}
UiObject2 assertSaveShowing(String description, int... types) {
+ return assertSaveShowing(SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL, description, types);
+ }
+
+ UiObject2 assertSaveShowing(int negativeButtonStyle, String description, int... types) {
final UiObject2 snackbar = waitForObject(By.res("android", RESOURCE_ID_SAVE_SNACKBAR),
SAVE_TIMEOUT_MS);
@@ -288,6 +293,12 @@
assertWithMessage("save subtitle(%s)", description).that(saveSubTitle).isNotNull();
}
+ final String negativeButtonText = (negativeButtonStyle
+ == SaveInfo.NEGATIVE_BUTTON_STYLE_REJECT) ? "NOT NOW" : "NO THANKS";
+ UiObject2 negativeButton = snackbar.findObject(By.text(negativeButtonText));
+ assertWithMessage("negative button (%s)", negativeButtonText)
+ .that(negativeButton).isNotNull();
+
final String expectedAccessibilityTitle =
getString(RESOURCE_STRING_SAVE_SNACKBAR_ACCESSIBILITY_TITLE);
assertAccessibilityTitle(snackbar, expectedAccessibilityTitle);
@@ -302,7 +313,19 @@
* @param types expected types of save info.
*/
void saveForAutofill(boolean yesDoIt, int... types) {
- final UiObject2 saveSnackBar = assertSaveShowing(null, types);
+ final UiObject2 saveSnackBar = assertSaveShowing(
+ SaveInfo.NEGATIVE_BUTTON_STYLE_CANCEL,null, types);
+ saveForAutofill(saveSnackBar, yesDoIt);
+ }
+
+ /**
+ * Taps an option in the save snackbar.
+ *
+ * @param yesDoIt {@code true} for 'YES', {@code false} for 'NO THANKS'.
+ * @param types expected types of save info.
+ */
+ void saveForAutofill(int negativeButtonStyle, boolean yesDoIt, int... types) {
+ final UiObject2 saveSnackBar = assertSaveShowing(negativeButtonStyle,null, types);
saveForAutofill(saveSnackBar, yesDoIt);
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
index 670832c..2102773 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerView.java
@@ -41,7 +41,6 @@
import android.view.autofill.AutofillValue;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -161,7 +160,8 @@
@Override
public void dispatchProvideAutofillStructure(ViewStructure structure, int flags) {
if (mOverrideDispatchProvideAutofillStructure) {
- Log.d(TAG, "Overriding dispatchProvideAutofillStructure");
+ Log.d(TAG, "Overriding dispatchProvideAutofillStructure()");
+ structure.setAutofillId(getAutofillId());
onProvideAutofillVirtualStructure(structure, flags);
} else {
super.dispatchProvideAutofillStructure(structure, flags);
@@ -184,7 +184,7 @@
final ViewStructure child = mSync
? structure.newChild(index)
: structure.asyncNewChild(index);
- child.setAutofillId(structure, item.id);
+ child.setAutofillId(structure.getAutofillId(), item.id);
child.setDataIsSensitive(item.sensitive);
index++;
final String className = item.editable ? TEXT_CLASS : LABEL_CLASS;
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index e4ca5af..ba902bf 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: 37704262
}
]
diff --git a/tests/jdwp/AndroidTest.xml b/tests/jdwp/AndroidTest.xml
index 3cd1be2..9bab5b1 100644
--- a/tests/jdwp/AndroidTest.xml
+++ b/tests/jdwp/AndroidTest.xml
@@ -30,10 +30,11 @@
<option name="classpath" value="/data/local/tmp/ctsjdwp/CtsJdwpTestCases.jar" />
<option name="dalvik-arg" value="-Xcompiler-option" />
<option name="dalvik-arg" value="--debuggable" />
+ <option name="dalvik-arg" value="-Xusejit:true" />
<option name="dalvik-arg" value="-Djpda.settings.verbose=false" />
<option name="dalvik-arg" value="-Djpda.settings.timeout=10000" />
<option name="dalvik-arg" value="-Djpda.settings.waitingTime=10000" />
- <option name="dalvik-arg" value="-Djpda.settings.debuggeeJavaPath='dalvikvm|#ABI#| -XXlib:libart.so -Xcompiler-option --debuggable'" />
+ <option name="dalvik-arg" value="-Djpda.settings.debuggeeJavaPath='dalvikvm|#ABI#| -XXlib:libart.so -Xcompiler-option --debuggable -Xusejit:true'" />
<option name="known-failures" value="/expectations/jdwp-known-failures.txt" />
<option name="runtime-hint" value="16m" />
diff --git a/tests/tests/app/AndroidManifest.xml b/tests/tests/app/AndroidManifest.xml
index be903e3..707b22b 100644
--- a/tests/tests/app/AndroidManifest.xml
+++ b/tests/tests/app/AndroidManifest.xml
@@ -23,6 +23,11 @@
<activity android:name=".ApplyOverrideConfigurationActivity"
android:configChanges="orientation|screenSize" />
+
+ <activity android:name=".PictureInPictureActivity"
+ android:resizeableActivity="false"
+ android:supportsPictureInPicture="true"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" />
</application>
<instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
index d08b29f..da02a81 100644
--- a/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureActionsTest.java
@@ -15,12 +15,16 @@
*/
package android.app.cts;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
-import android.app.ActivityManager;
+import android.app.Activity;
+import android.app.Instrumentation;
import android.support.test.filters.SmallTest;
+import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -32,9 +36,20 @@
@RunWith(AndroidJUnit4.class)
public class PictureInPictureActionsTest {
+ private Activity mActivity;
+
+ @Rule
+ public ActivityTestRule<PictureInPictureActivity> mActivityRule =
+ new ActivityTestRule<>(PictureInPictureActivity.class);
+
+ @Before
+ public void setup() {
+ mActivity = mActivityRule.getActivity();
+ }
+
@Test
public void testNumPictureInPictureActions() throws Exception {
- // Currently enforce that there are a max of three actions
- assertEquals(ActivityManager.getMaxNumPictureInPictureActions(), 3);
+ // Currently enforce that there are at least 3 actions
+ assertTrue(mActivity.getMaxNumPictureInPictureActions() >= 3);
}
}
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java b/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java
new file mode 100644
index 0000000..75245b7
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.app.cts;
+
+import android.app.Activity;
+
+public class PictureInPictureActivity extends Activity {
+ // Empty
+}
diff --git a/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
new file mode 100644
index 0000000..639c4d1
--- /dev/null
+++ b/tests/tests/app/src/android/app/cts/PictureInPictureParamsBuilderTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+package android.app.cts;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.app.PictureInPictureParams;
+import android.app.PictureInPictureParams.Builder;
+import android.graphics.Rect;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Rational;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+/**
+ * Tests the {@link PictureInPictureParams} builder.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class PictureInPictureParamsBuilderTest {
+
+ @Test
+ public void testBuildParams() throws Exception {
+ // Set the params
+ Builder builder = new Builder()
+ .setAspectRatio(new Rational(1, 2))
+ .setActions(new ArrayList<>())
+ .setSourceRectHint(new Rect(0, 0, 100, 100));
+
+ PictureInPictureParams params = builder.build();
+ assertTrue(Float.compare(0.5f, params.getAspectRatio()) == 0);
+ assertTrue(params.getActions().isEmpty());
+ assertEquals(new Rect(0, 0, 100, 100), params.getSourceRectHint());
+
+ // Reset the params
+ builder.setAspectRatio(null)
+ .setActions(null)
+ .setSourceRectHint(null);
+ params = builder.build();
+
+ assertTrue(Float.compare(0f, params.getAspectRatio()) == 0);
+ assertNull(params.getActions());
+ assertNull(params.getSourceRectHint());
+ }
+}
diff --git a/tests/tests/content/res/values/attrs.xml b/tests/tests/content/res/values/attrs.xml
index 12b731b..236ee6c 100644
--- a/tests/tests/content/res/values/attrs.xml
+++ b/tests/tests/content/res/values/attrs.xml
@@ -49,6 +49,7 @@
<attr name="type15" format="reference"/>
<attr name="type16" format="string"/>
<attr name="type17" format="reference|color"/>
+ <attr name="type18" format="reference|string"/>
<attr name="typeEmpty" format="reference"/>
<attr name="typeUndefined" format="reference"/>
<declare-styleable name="style1">
@@ -69,6 +70,7 @@
<attr name="type15"/>
<attr name="type16"/>
<attr name="type17"/>
+ <attr name="type18"/>
<attr name="typeEmpty"/>
<attr name="typeUndefined"/>
</declare-styleable>
diff --git a/tests/tests/content/res/values/styles.xml b/tests/tests/content/res/values/styles.xml
index d1c30d7..b4db3ac 100644
--- a/tests/tests/content/res/values/styles.xml
+++ b/tests/tests/content/res/values/styles.xml
@@ -34,6 +34,7 @@
<item name="type15">@array/difficultyLevel</item>
<item name="type16">Typed Value!</item>
<item name="type17">@color/testcolor_orientation</item>
+ <item name="type18">@font/samplefont</item>
<item name="typeEmpty">@empty</item>
<item name="typeUndefined">@null</item>
</style>
@@ -181,4 +182,8 @@
<style name="Theme_OrientationDependent">
<item name="themeDimension">999px</item>
</style>
+
+ <style name="Theme_InlineString">
+ <item name="testString">"This is a string"</item>
+ </style>
</resources>
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index e5e8fe4..d1c03d2 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -427,7 +427,7 @@
Bundle queryArgs = new Bundle();
queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10);
queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3);
- queryArgs.putInt(TestPagingContentProvider.RECORDSET_SIZE, 100);
+ queryArgs.putInt(TestPagingContentProvider.RECORD_COUNT, 100);
mCursor = mContentResolver.query(
TestPagingContentProvider.PAGED_DATA_URI, null, queryArgs, null);
@@ -436,8 +436,8 @@
extras = extras != null ? extras : Bundle.EMPTY;
assertEquals(3, mCursor.getCount());
- assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_SIZE));
- assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_SIZE));
+ assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_COUNT));
+ assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT));
String[] honoredArgs = extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS);
assertNotNull(honoredArgs);
diff --git a/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java b/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java
index 42e0019..6e38809 100644
--- a/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java
+++ b/tests/tests/content/src/android/content/cts/TestPagingContentProvider.java
@@ -42,7 +42,7 @@
static final Uri UNPAGED_DATA_URI = Uri.parse("content://" + AUTHORITY + "/un-paged/");
/** Required queryArgument specifying corpus size. */
- static final String RECORDSET_SIZE = "test-recordset-size";
+ static final String RECORD_COUNT = "test-record-count";
static final String COLUMN_POS = "ColumnPos";
static final String COLUMN_A = "ColumnA";
static final String COLUMN_B = "ColumnB";
@@ -69,26 +69,28 @@
queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY;
- int recordsetSize = queryArgs.getInt(RECORDSET_SIZE, Integer.MIN_VALUE);
- if (recordsetSize == Integer.MIN_VALUE) {
+ int recordCount = queryArgs.getInt(RECORD_COUNT, Integer.MIN_VALUE);
+ if (recordCount == Integer.MIN_VALUE) {
throw new RuntimeException("Recordset size must be specified.");
}
- if (recordsetSize < 0) {
+ if (recordCount < 0) {
throw new RuntimeException("Recordset size must be >= 0");
}
Cursor cursor = null;
if (PAGED_DATA_URI.equals(uri)) {
- cursor = buildPagedResults(queryArgs, recordsetSize);
+ cursor = buildPagedResults(queryArgs, recordCount);
} else if (UNPAGED_DATA_URI.equals(uri)) {
- cursor = buildUnpagedResults(recordsetSize);
+ cursor = buildUnpagedResults(recordCount);
}
if (cursor == null) {
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
+ cursor.setNotificationUri(getContext().getContentResolver(), uri);
+
Log.v(TAG, "Final cursor contains " + cursor.getCount() + " rows.");
return cursor;
}
@@ -118,7 +120,7 @@
ContentResolver.QUERY_ARG_OFFSET,
ContentResolver.QUERY_ARG_LIMIT
});
- extras.putInt(ContentResolver.EXTRA_TOTAL_SIZE, recordsetSize);
+ extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize);
return c;
}
diff --git a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
index b7a621f..24c61ae 100644
--- a/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/Resources_ThemeTest.java
@@ -83,6 +83,16 @@
}
@SmallTest
+ public void testObtainStyledAttributesWithInlineStringInTheme() {
+ mResTheme.applyStyle(R.style.Theme_InlineString, false);
+ final TypedArray ta = mResTheme.obtainStyledAttributes(new int[] { R.attr.testString });
+ assertNotNull(ta);
+ assertEquals(1, ta.length());
+ assertEquals(TypedValue.TYPE_STRING, ta.getType(0));
+ assertEquals("This is a string", ta.getString(0));
+ }
+
+ @SmallTest
public void testResolveAttribute() {
final TypedValue value = new TypedValue();
getContext().getResources().getValue(R.raw.testmp3, value, true);
diff --git a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
index b31b446..5739554 100644
--- a/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
+++ b/tests/tests/content/src/android/content/res/cts/TypedArrayTest.java
@@ -25,6 +25,7 @@
import android.content.pm.ActivityInfo;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.graphics.Typeface;
import android.test.AndroidTestCase;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -48,9 +49,9 @@
private static final String EXPECTED_TEXT = "TypedArray Test!";
private static final String[] EXPECTED_TEXT_ARRAY = {"Easy", "Medium", "Hard"};
private static final TypedValue DEF_VALUE = new TypedValue();
- private static final int EXPECTED_INDEX_COUNT = 17;
+ private static final int EXPECTED_INDEX_COUNT = 18;
private static final String EXPTECTED_POS_DESCRIP = "<internal>";
- private static final int EXPECTED_LENGTH = 19;
+ private static final int EXPECTED_LENGTH = 20;
private static final String EXPECTED_NON_RESOURCE_STRING = "testNonResourcesString";
private static final String XML_BEGIN = "resources";
private static final int EXPECTED_INT_ATT = 86400;
@@ -62,7 +63,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mTypedArray = getContext().getTheme().obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
+ mTypedArray = getContext().getTheme()
+ .obtainStyledAttributes(R.style.Whatever, R.styleable.style1);
}
@Override
@@ -167,6 +169,9 @@
actual_indices[idx] = attr_index;
}
+ final Typeface font = t.getFont(R.styleable.style1_type18);
+ assertEquals(mContext.getResources().getFont(R.font.samplefont), font);
+
// NOTE: order does not matter here.
// R.styleable.style1_typeEmpty and R.styleable.style1_typeUndefined are not
// expected because TYPE_NULL values do not get included in the index list.
@@ -187,7 +192,8 @@
R.styleable.style1_type14,
R.styleable.style1_type15,
R.styleable.style1_type16,
- R.styleable.style1_type17);
+ R.styleable.style1_type17,
+ R.styleable.style1_type18);
}
public void testPeekValue() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
index a296659..e255f8e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapColorSpaceTest.java
@@ -122,6 +122,18 @@
assertSame(sRGB, cs);
}
+ @Test
+ public void createDefaultColorSpace() {
+ ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB);
+ Bitmap.Config[] configs = new Bitmap.Config[] {
+ Bitmap.Config.ALPHA_8, Bitmap.Config.RGB_565, Bitmap.Config.ARGB_8888
+ };
+ for (Bitmap.Config config : configs) {
+ Bitmap bitmap = Bitmap.createBitmap(32, 32, config, true);
+ assertSame(sRGB, bitmap.getColorSpace());
+ }
+ }
+
@Test(expected = IllegalArgumentException.class)
public void createWithoutColorSpace() {
Bitmap.createBitmap(32, 32, Bitmap.Config.ARGB_8888, true, null);
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
index 4156ed5..0d43322 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapTest.java
@@ -129,7 +129,7 @@
@Test
public void testCopyConfigs() {
Config[] supportedConfigs = new Config[] {
- Config.ALPHA_8, Config.RGB_565, Config.ARGB_8888
+ Config.ALPHA_8, Config.RGB_565, Config.ARGB_8888, Config.RGBA_F16,
};
for (Config src : supportedConfigs) {
for (Config dst : supportedConfigs) {
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
index 61d46b2..358e401 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorMatrixColorFilterTest.java
@@ -15,7 +15,9 @@
*/
package android.graphics.cts;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
@@ -97,5 +99,26 @@
canvas.drawPoint(0, 0, paint);
ColorUtils.verifyColor(Color.BLUE, bitmap.getPixel(0, 0));
}
+
+ @Test
+ public void testGetColorMatrix() {
+ ColorMatrixColorFilter filter = new ColorMatrixColorFilter(new ColorMatrix());
+ ColorMatrix getMatrix = new ColorMatrix();
+
+ filter.getColorMatrix(getMatrix);
+ assertEquals(new ColorMatrix(), getMatrix);
+
+ ColorMatrix scaleTranslate = new ColorMatrix(new float[] {
+ 1, 0, 0, 0, 8,
+ 0, 2, 0, 0, 7,
+ 0, 0, 3, 0, 6,
+ 0, 0, 0, 4, 5
+ });
+
+ filter = new ColorMatrixColorFilter(scaleTranslate);
+ filter.getColorMatrix(getMatrix);
+ assertEquals(scaleTranslate, getMatrix);
+ assertArrayEquals(scaleTranslate.getArray(), getMatrix.getArray(), 0);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
index 3f82150..fdbf92e 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ColorSpaceTest.java
@@ -435,12 +435,14 @@
assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getSource());
assertSame(ColorSpace.get(ColorSpace.Named.DCI_P3), connector.getDestination());
+ assertSame(ColorSpace.RenderIntent.PERCEPTUAL, connector.getRenderIntent());
connector = ColorSpace.connect(
ColorSpace.get(ColorSpace.Named.SRGB),
ColorSpace.get(ColorSpace.Named.SRGB));
assertSame(connector.getDestination(), connector.getSource());
+ assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent());
connector = ColorSpace.connect(ColorSpace.get(ColorSpace.Named.DCI_P3));
assertSame(ColorSpace.get(ColorSpace.Named.SRGB), connector.getDestination());
@@ -543,6 +545,7 @@
ColorSpace.get(ColorSpace.Named.SRGB));
assertSame(connector.getSource(), connector.getDestination());
+ assertSame(ColorSpace.RenderIntent.RELATIVE, connector.getRenderIntent());
float[] source = new float[] { 0.11112f, 0.22227f, 0.444448f };
diff --git a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
index da2b934..c7befa8 100644
--- a/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/LightingColorFilterTest.java
@@ -35,6 +35,10 @@
public class LightingColorFilterTest {
private static final int TOLERANCE = 2;
+ private void verifyColor(int expected, int actual) {
+ ColorUtils.verifyColor(expected, actual, TOLERANCE);
+ }
+
@Test
public void testLightingColorFilter() {
Bitmap bitmap = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
@@ -86,7 +90,22 @@
verifyColor(Color.argb(0x80, 30, 30, 30), bitmap.getPixel(0, 0));
}
- private void verifyColor(int expected, int actual) {
- ColorUtils.verifyColor(expected, actual, TOLERANCE);
+ @Test
+ public void testGetColorAdd() {
+ LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
+ ColorUtils.verifyColor(Color.BLACK, filter.getColorAdd());
+
+ filter = new LightingColorFilter(0x87654321, 0x12345678);
+ ColorUtils.verifyColor(0x12345678, filter.getColorAdd());
+ }
+
+
+ @Test
+ public void testGetColorMultiply() {
+ LightingColorFilter filter = new LightingColorFilter(Color.WHITE, Color.BLACK);
+ ColorUtils.verifyColor(Color.WHITE, filter.getColorMultiply());
+
+ filter = new LightingColorFilter(0x87654321, 0x12345678);
+ ColorUtils.verifyColor(0x87654321, filter.getColorMultiply());
}
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/PathTest.java b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
index db3884c..ade4a97 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PathTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PathTest.java
@@ -16,6 +16,11 @@
package android.graphics.cts;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -25,11 +30,10 @@
import android.graphics.RectF;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
+
import org.junit.Test;
import org.junit.runner.RunWith;
-import static org.junit.Assert.*;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class PathTest {
@@ -440,6 +444,41 @@
assertEquals(expectedRect, offsettedRect);
}
+ @Test
+ public void testApproximate_rect_cw() {
+ Path path = new Path();
+ path.addRect(0, 0, 100, 100, Path.Direction.CW);
+ assertArrayEquals(new float[] {
+ 0, 0, 0,
+ 0.25f, 100, 0,
+ 0.50f, 100, 100,
+ 0.75f, 0, 100,
+ 1, 0, 0,
+ }, path.approximate(1f), 0);
+ }
+
+ @Test
+ public void testApproximate_rect_ccw() {
+ Path path = new Path();
+ path.addRect(0, 0, 100, 100, Path.Direction.CCW);
+ assertArrayEquals(new float[] {
+ 0, 0, 0,
+ 0.25f, 0, 100,
+ 0.50f, 100, 100,
+ 0.75f, 100, 0,
+ 1, 0, 0,
+ }, path.approximate(1f), 0);
+ }
+
+ @Test
+ public void testApproximate_empty() {
+ Path path = new Path();
+ assertArrayEquals(new float[] {
+ 0, 0, 0,
+ 1, 0, 0,
+ }, path.approximate(0.5f), 0);
+ }
+
private static void verifyPathsAreEquivalent(Path actual, Path expected) {
Bitmap actualBitmap = drawAndGetBitmap(actual);
Bitmap expectedBitmap = drawAndGetBitmap(expected);
diff --git a/tests/tests/media/src/android/media/cts/AudioManagerTest.java b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
index ba657bf..4c6eb27 100644
--- a/tests/tests/media/src/android/media/cts/AudioManagerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioManagerTest.java
@@ -78,6 +78,11 @@
&& (packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
|| packageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION));
}
+ @Override
+ protected void tearDown() throws Exception {
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), false);
+ }
public void testMicrophoneMute() throws Exception {
mAudioManager.setMicrophoneMute(true);
@@ -94,7 +99,7 @@
mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
} finally {
Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
+ mContext.getPackageName(), getInstrumentation(), false);
}
Settings.System.putInt(mContext.getContentResolver(), SOUND_EFFECTS_ENABLED, 1);
@@ -193,165 +198,150 @@
if (mUseFixedVolume || !mHasVibrator) {
return;
}
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- // VIBRATE_SETTING_ON
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ // VIBRATE_SETTING_ON
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
+ assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- // VIBRATE_SETTING_OFF
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ // VIBRATE_SETTING_OFF
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
+ assertEquals(VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- // VIBRATE_SETTING_ONLY_SILENT
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ // VIBRATE_SETTING_ONLY_SILENT
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
+ assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_NOTIFICATION));
- // VIBRATE_TYPE_NOTIFICATION
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF, mAudioManager
- .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- }
+ // VIBRATE_TYPE_NOTIFICATION
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ON);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_OFF);
+ assertEquals(VIBRATE_SETTING_OFF, mAudioManager
+ .getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_NOTIFICATION, VIBRATE_SETTING_ONLY_SILENT);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_NOTIFICATION));
}
public void testVibrateRinger() throws Exception {
if (mUseFixedVolume || !mHasVibrator) {
return;
}
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- // VIBRATE_TYPE_RINGER
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ // VIBRATE_TYPE_RINGER
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
+ assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- // VIBRATE_SETTING_OFF
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ // VIBRATE_SETTING_OFF
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
+ assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
- // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
- // disable the vibration for incoming calls only.
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
+ // Note: as of Froyo, if VIBRATE_TYPE_RINGER is set to OFF, it will
+ // not vibrate, even in RINGER_MODE_VIBRATE. This allows users to
+ // disable the vibration for incoming calls only.
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- // VIBRATE_SETTING_ONLY_SILENT
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ // VIBRATE_SETTING_ONLY_SILENT
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertFalse(mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
+ assertEquals(mHasVibrator, mAudioManager.shouldVibrate(VIBRATE_TYPE_RINGER));
- // VIBRATE_TYPE_NOTIFICATION
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
- assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
- assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
- mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- }
+ // VIBRATE_TYPE_NOTIFICATION
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ON);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ON : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_OFF);
+ assertEquals(VIBRATE_SETTING_OFF, mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
+ mAudioManager.setVibrateSetting(VIBRATE_TYPE_RINGER, VIBRATE_SETTING_ONLY_SILENT);
+ assertEquals(mHasVibrator ? VIBRATE_SETTING_ONLY_SILENT : VIBRATE_SETTING_OFF,
+ mAudioManager.getVibrateSetting(VIBRATE_TYPE_RINGER));
}
public void testAccessRingMode() throws Exception {
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ // AudioService#setRingerMode() has:
+ // if (isTelevision) return;
+ if (mUseFixedVolume || mIsTelevision) {
assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ } else {
+ assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+ }
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- // AudioService#setRingerMode() has:
- // if (isTelevision) return;
- if (mUseFixedVolume || mIsTelevision) {
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } else {
- assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- }
-
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- if (mUseFixedVolume || mIsTelevision) {
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } else {
- assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
- mAudioManager.getRingerMode());
- }
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ if (mUseFixedVolume || mIsTelevision) {
+ assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ } else {
+ assertEquals(mHasVibrator ? RINGER_MODE_VIBRATE : RINGER_MODE_SILENT,
+ mAudioManager.getRingerMode());
}
}
@@ -359,32 +349,47 @@
if (mUseFixedVolume || mIsTelevision) {
return;
}
+ // Apps without policy access cannot change silent -> normal or silent -> vibrate.
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), false);
+
try {
- // Apps without policy access cannot change silent -> normal or silent -> vibrate.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- assertEquals(RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
-
- // Apps without policy access cannot change normal -> silent.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ fail("Apps without notification policy access cannot change ringer mode");
+ } catch (SecurityException e) {
+ }
+
+ try {
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ fail("Apps without notification policy access cannot change ringer mode");
+ } catch (SecurityException e) {
+ }
+
+ // Apps without policy access cannot change normal -> silent.
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), false);
+
+ try {
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ fail("Apps without notification policy access cannot change ringer mode");
+ } catch (SecurityException e) {
+ }
+ assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+
+ if (mHasVibrator) {
+ // Apps without policy access cannot change vibrate -> silent.
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
Utils.toggleNotificationPolicyAccess(
mContext.getPackageName(), getInstrumentation(), false);
@@ -393,33 +398,13 @@
fail("Apps without notification policy access cannot change ringer mode");
} catch (SecurityException e) {
}
+
+ // Apps without policy access can change vibrate -> normal and vice versa.
+ assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
-
- if (mHasVibrator) {
- // Apps without policy access cannot change vibrate -> silent.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
-
- try {
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- fail("Apps without notification policy access cannot change ringer mode");
- } catch (SecurityException e) {
- }
-
- // Apps without policy access can change vibrate -> normal and vice versa.
- assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- assertEquals(RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
- assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
- }
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
+ mAudioManager.setRingerMode(RINGER_MODE_VIBRATE);
+ assertEquals(RINGER_MODE_VIBRATE, mAudioManager.getRingerMode());
}
}
@@ -464,150 +449,145 @@
}
public void testVolume() throws Exception {
- try {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- int volume, volumeDelta;
- int[] streams = {AudioManager.STREAM_ALARM,
- AudioManager.STREAM_MUSIC,
- AudioManager.STREAM_VOICE_CALL,
- AudioManager.STREAM_RING};
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ int volume, volumeDelta;
+ int[] streams = {AudioManager.STREAM_ALARM,
+ AudioManager.STREAM_MUSIC,
+ AudioManager.STREAM_VOICE_CALL,
+ AudioManager.STREAM_RING};
- mAudioManager.adjustVolume(ADJUST_RAISE, 0);
- // adjusting volume is aynchronous, wait before other volume checks
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- mAudioManager.adjustSuggestedStreamVolume(
- ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
+ mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+ // adjusting volume is aynchronous, wait before other volume checks
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ mAudioManager.adjustSuggestedStreamVolume(
+ ADJUST_LOWER, USE_DEFAULT_STREAM_TYPE, 0);
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ int maxMusicVolume = mAudioManager.getStreamMaxVolume(STREAM_MUSIC);
- for (int stream : streams) {
- // set ringer mode to back normal to not interfere with volume tests
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ for (int stream : streams) {
+ // set ringer mode to back normal to not interfere with volume tests
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- int maxVolume = mAudioManager.getStreamMaxVolume(stream);
- int minVolume = mAudioManager.getStreamMinVolume(stream);
+ int maxVolume = mAudioManager.getStreamMaxVolume(stream);
+ int minVolume = mAudioManager.getStreamMinVolume(stream);
- // validate min
- assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
- assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
- maxVolume),
- minVolume < maxVolume);
+ // validate min
+ assertTrue(String.format("minVolume(%d) must be >= 0", minVolume), minVolume >= 0);
+ assertTrue(String.format("minVolume(%d) must be < maxVolume(%d)", minVolume,
+ maxVolume),
+ minVolume < maxVolume);
- mAudioManager.setStreamVolume(stream, 1, 0);
- if (mUseFixedVolume) {
- assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
- continue;
- }
- assertEquals(String.format("stream=%d", stream),
- 1, mAudioManager.getStreamVolume(stream));
-
- if (stream == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
- // due to new regulations, music sent over a wired headset may be volume limited
- // until the user explicitly increases the limit, so we can't rely on being able
- // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
- // by increasing the volume until it won't go any higher, then use that volume as
- // the maximum for the purposes of this test
- int curvol = 0;
- int prevvol = 0;
- do {
- prevvol = curvol;
- mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
- curvol = mAudioManager.getStreamVolume(stream);
- } while (curvol != prevvol);
- maxVolume = maxMusicVolume = curvol;
- }
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
- assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
-
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
- mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(stream));
-
- // volume lower
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- volume = mAudioManager.getStreamVolume(stream);
- while (volume > minVolume) {
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
- mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0);
- assertEquals(Math.max(0, volume - volumeDelta),
- mAudioManager.getStreamVolume(stream));
- volume = mAudioManager.getStreamVolume(stream);
- }
-
- mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
-
- // volume raise
- mAudioManager.setStreamVolume(stream, 1, 0);
- volume = mAudioManager.getStreamVolume(stream);
- while (volume < maxVolume) {
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
- mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
- assertEquals(Math.min(volume + volumeDelta, maxVolume),
- mAudioManager.getStreamVolume(stream));
- volume = mAudioManager.getStreamVolume(stream);
- }
-
- // volume same
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- for (int k = 0; k < maxVolume; k++) {
- mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
- assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
- }
-
- mAudioManager.setStreamVolume(stream, maxVolume, 0);
- }
-
+ mAudioManager.setStreamVolume(stream, 1, 0);
if (mUseFixedVolume) {
- return;
+ assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
+ continue;
+ }
+ assertEquals(String.format("stream=%d", stream),
+ 1, mAudioManager.getStreamVolume(stream));
+
+ if (stream == AudioManager.STREAM_MUSIC && mAudioManager.isWiredHeadsetOn()) {
+ // due to new regulations, music sent over a wired headset may be volume limited
+ // until the user explicitly increases the limit, so we can't rely on being able
+ // to set the volume to getStreamMaxVolume(). Instead, determine the current limit
+ // by increasing the volume until it won't go any higher, then use that volume as
+ // the maximum for the purposes of this test
+ int curvol = 0;
+ int prevvol = 0;
+ do {
+ prevvol = curvol;
+ mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
+ curvol = mAudioManager.getStreamVolume(stream);
+ } while (curvol != prevvol);
+ maxVolume = maxMusicVolume = curvol;
+ }
+ mAudioManager.setStreamVolume(stream, maxVolume, 0);
+ mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
+ assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
+
+ volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
+ mAudioManager.adjustSuggestedStreamVolume(ADJUST_LOWER, stream, 0);
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ assertEquals(maxVolume - volumeDelta, mAudioManager.getStreamVolume(stream));
+
+ // volume lower
+ mAudioManager.setStreamVolume(stream, maxVolume, 0);
+ volume = mAudioManager.getStreamVolume(stream);
+ while (volume > minVolume) {
+ volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
+ mAudioManager.adjustStreamVolume(stream, ADJUST_LOWER, 0);
+ assertEquals(Math.max(0, volume - volumeDelta),
+ mAudioManager.getStreamVolume(stream));
+ volume = mAudioManager.getStreamVolume(stream);
}
- // adjust volume
- mAudioManager.adjustVolume(ADJUST_RAISE, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
- MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
- assertNotNull(mp);
- mp.setAudioStreamType(STREAM_MUSIC);
- mp.setLooping(true);
- mp.start();
- Thread.sleep(TIME_TO_PLAY);
- assertTrue(mAudioManager.isMusicActive());
-
- // adjust volume as ADJUST_SAME
- for (int k = 0; k < maxMusicVolume; k++) {
- mAudioManager.adjustVolume(ADJUST_SAME, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
+ // volume raise
+ mAudioManager.setStreamVolume(stream, 1, 0);
+ volume = mAudioManager.getStreamVolume(stream);
+ while (volume < maxVolume) {
+ volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(stream));
+ mAudioManager.adjustStreamVolume(stream, ADJUST_RAISE, 0);
+ assertEquals(Math.min(volume + volumeDelta, maxVolume),
+ mAudioManager.getStreamVolume(stream));
+ volume = mAudioManager.getStreamVolume(stream);
}
- // adjust volume as ADJUST_RAISE
- mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
- mAudioManager.adjustVolume(ADJUST_RAISE, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertEquals(Math.min(volumeDelta, maxMusicVolume),
- mAudioManager.getStreamVolume(STREAM_MUSIC));
+ // volume same
+ mAudioManager.setStreamVolume(stream, maxVolume, 0);
+ for (int k = 0; k < maxVolume; k++) {
+ mAudioManager.adjustStreamVolume(stream, ADJUST_SAME, 0);
+ assertEquals(maxVolume, mAudioManager.getStreamVolume(stream));
+ }
- // adjust volume as ADJUST_LOWER
- mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
- maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
- volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
- mAudioManager.adjustVolume(ADJUST_LOWER, 0);
- Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
- assertEquals(Math.max(0, maxMusicVolume - volumeDelta),
- mAudioManager.getStreamVolume(STREAM_MUSIC));
-
- mp.stop();
- mp.release();
- Thread.sleep(TIME_TO_PLAY);
- assertFalse(mAudioManager.isMusicActive());
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
+ mAudioManager.setStreamVolume(stream, maxVolume, 0);
}
+
+ if (mUseFixedVolume) {
+ return;
+ }
+
+ // adjust volume
+ mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+
+ MediaPlayer mp = MediaPlayer.create(mContext, MP3_TO_PLAY);
+ assertNotNull(mp);
+ mp.setAudioStreamType(STREAM_MUSIC);
+ mp.setLooping(true);
+ mp.start();
+ Thread.sleep(TIME_TO_PLAY);
+ assertTrue(mAudioManager.isMusicActive());
+
+ // adjust volume as ADJUST_SAME
+ for (int k = 0; k < maxMusicVolume; k++) {
+ mAudioManager.adjustVolume(ADJUST_SAME, 0);
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ assertEquals(maxMusicVolume, mAudioManager.getStreamVolume(STREAM_MUSIC));
+ }
+
+ // adjust volume as ADJUST_RAISE
+ mAudioManager.setStreamVolume(STREAM_MUSIC, 0, 0);
+ volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
+ mAudioManager.adjustVolume(ADJUST_RAISE, 0);
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ assertEquals(Math.min(volumeDelta, maxMusicVolume),
+ mAudioManager.getStreamVolume(STREAM_MUSIC));
+
+ // adjust volume as ADJUST_LOWER
+ mAudioManager.setStreamVolume(STREAM_MUSIC, maxMusicVolume, 0);
+ maxMusicVolume = mAudioManager.getStreamVolume(STREAM_MUSIC);
+ volumeDelta = getVolumeDelta(mAudioManager.getStreamVolume(STREAM_MUSIC));
+ mAudioManager.adjustVolume(ADJUST_LOWER, 0);
+ Thread.sleep(ASYNC_TIMING_TOLERANCE_MS);
+ assertEquals(Math.max(0, maxMusicVolume - volumeDelta),
+ mAudioManager.getStreamVolume(STREAM_MUSIC));
+
+ mp.stop();
+ mp.release();
+ Thread.sleep(TIME_TO_PLAY);
+ assertFalse(mAudioManager.isMusicActive());
}
public void testAccessibilityVolume() throws Exception {
@@ -681,77 +661,72 @@
return;
}
int[] streams = { AudioManager.STREAM_RING };
- try {
- // Mute streams
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_SILENT);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- // Verify streams cannot be unmuted without policy access.
- for (int stream : streams) {
- try {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
- 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.setStreamMute(stream, false);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_SILENT, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
+ // Mute streams
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ mAudioManager.setRingerMode(RINGER_MODE_SILENT);
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), false);
+ // Verify streams cannot be unmuted without policy access.
+ for (int stream : streams) {
+ try {
+ mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_UNMUTE, 0);
+ assertEquals("Apps without Notification policy access can't change ringer mode",
+ RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+ } catch (SecurityException e) {
}
- // This ensures we're out of vibrate or silent modes.
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- for (int stream : streams) {
- // ensure each stream is on and turned up.
- mAudioManager.setStreamVolume(stream,
- mAudioManager.getStreamMaxVolume(stream),
+ try {
+ mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
0);
-
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- try {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
- try {
- mAudioManager.adjustStreamVolume(
- stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
-
- try {
- mAudioManager.setStreamMute(stream, true);
- assertEquals("Apps without Notification policy access can't change ringer mode",
- RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
- } catch (SecurityException e) {
- }
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- testStreamMuting(stream);
+ assertEquals("Apps without Notification policy access can't change ringer mode",
+ RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+ } catch (SecurityException e) {
}
- } finally {
+
+ try {
+ mAudioManager.setStreamMute(stream, false);
+ assertEquals("Apps without Notification policy access can't change ringer mode",
+ RINGER_MODE_SILENT, mAudioManager.getRingerMode());
+ } catch (SecurityException e) {
+ }
+ }
+
+ // This ensures we're out of vibrate or silent modes.
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ for (int stream : streams) {
+ // ensure each stream is on and turned up.
+ mAudioManager.setStreamVolume(stream,
+ mAudioManager.getStreamMaxVolume(stream),
+ 0);
+
Utils.toggleNotificationPolicyAccess(
mContext.getPackageName(), getInstrumentation(), false);
+ try {
+ mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
+ assertEquals("Apps without Notification policy access can't change ringer mode",
+ RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ } catch (SecurityException e) {
+ }
+ try {
+ mAudioManager.adjustStreamVolume(
+ stream, AudioManager.ADJUST_TOGGLE_MUTE, 0);
+ assertEquals("Apps without Notification policy access can't change ringer mode",
+ RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ } catch (SecurityException e) {
+ }
+
+ try {
+ mAudioManager.setStreamMute(stream, true);
+ assertEquals("Apps without Notification policy access can't change ringer mode",
+ RINGER_MODE_NORMAL, mAudioManager.getRingerMode());
+ } catch (SecurityException e) {
+ }
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ testStreamMuting(stream);
}
}
@@ -765,44 +740,39 @@
AudioManager.STREAM_ALARM
};
- try {
- int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
- System.MUTE_STREAMS_AFFECTED,
- // Same defaults as in AudioService. Should be kept in
- // sync.
- ((1 << AudioManager.STREAM_MUSIC) |
- (1 << AudioManager.STREAM_RING) |
- (1 << AudioManager.STREAM_NOTIFICATION) |
- (1 << AudioManager.STREAM_SYSTEM)));
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), true);
- // This ensures we're out of vibrate or silent modes.
- mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
- for (int stream : streams) {
- // ensure each stream is on and turned up.
- mAudioManager.setStreamVolume(stream,
- mAudioManager.getStreamMaxVolume(stream),
+ int muteAffectedStreams = System.getInt(mContext.getContentResolver(),
+ System.MUTE_STREAMS_AFFECTED,
+ // Same defaults as in AudioService. Should be kept in
+ // sync.
+ ((1 << AudioManager.STREAM_MUSIC) |
+ (1 << AudioManager.STREAM_RING) |
+ (1 << AudioManager.STREAM_NOTIFICATION) |
+ (1 << AudioManager.STREAM_SYSTEM)));
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), true);
+ // This ensures we're out of vibrate or silent modes.
+ mAudioManager.setRingerMode(RINGER_MODE_NORMAL);
+ Utils.toggleNotificationPolicyAccess(
+ mContext.getPackageName(), getInstrumentation(), false);
+ for (int stream : streams) {
+ // ensure each stream is on and turned up.
+ mAudioManager.setStreamVolume(stream,
+ mAudioManager.getStreamMaxVolume(stream),
+ 0);
+ if (((1 << stream) & muteAffectedStreams) == 0) {
+ mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
+ assertFalse("Stream " + stream + " should not be affected by mute.",
+ mAudioManager.isStreamMute(stream));
+ mAudioManager.setStreamMute(stream, true);
+ assertFalse("Stream " + stream + " should not be affected by mute.",
+ mAudioManager.isStreamMute(stream));
+ mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
0);
- if (((1 << stream) & muteAffectedStreams) == 0) {
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_MUTE, 0);
- assertFalse("Stream " + stream + " should not be affected by mute.",
- mAudioManager.isStreamMute(stream));
- mAudioManager.setStreamMute(stream, true);
- assertFalse("Stream " + stream + " should not be affected by mute.",
- mAudioManager.isStreamMute(stream));
- mAudioManager.adjustStreamVolume(stream, AudioManager.ADJUST_TOGGLE_MUTE,
- 0);
- assertFalse("Stream " + stream + " should not be affected by mute.",
- mAudioManager.isStreamMute(stream));
- continue;
- }
- testStreamMuting(stream);
+ assertFalse("Stream " + stream + " should not be affected by mute.",
+ mAudioManager.isStreamMute(stream));
+ continue;
}
- } finally {
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
+ testStreamMuting(stream);
}
}
@@ -863,8 +833,6 @@
} finally {
setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
}
}
@@ -888,8 +856,6 @@
} finally {
setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
}
}
@@ -912,8 +878,6 @@
assertEquals(7, mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
} finally {
setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
}
}
@@ -935,8 +899,6 @@
assertEquals(7, mAudioManager.getStreamVolume(AudioManager.STREAM_RING));
} finally {
setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_ALL);
- Utils.toggleNotificationPolicyAccess(
- mContext.getPackageName(), getInstrumentation(), false);
}
}
diff --git a/tests/tests/media/src/android/media/cts/Utils.java b/tests/tests/media/src/android/media/cts/Utils.java
index fb461fe..33cc1b7 100644
--- a/tests/tests/media/src/android/media/cts/Utils.java
+++ b/tests/tests/media/src/android/media/cts/Utils.java
@@ -27,7 +27,7 @@
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.provider.Settings;
-
+import com.google.android.collect.Lists;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -87,44 +87,77 @@
protected static void toggleNotificationPolicyAccess(String packageName,
Instrumentation instrumentation, boolean on) throws IOException {
- Context context = instrumentation.getContext();
+
+ // Read the setting listing the package allowed to manage notification policy configuration
+ String alreadyEnabledServices = querryNotificationPolicyAccessPakages(instrumentation);
+
+ // The property is a list of : separated package
+ List<String> enabledServices = Lists.newArrayList(alreadyEnabledServices.split(":"));
+
+ // Actually add or remove the package from the list
+ if (on) {
+ // Only add the package if it is not already in the list
+ if (!enabledServices.contains(packageName)) {
+ enabledServices.add(packageName);
+ setNotificationPolicyAccessPackages(enabledServices, instrumentation);
+ }
+ } else {
+ // Remove all instance of the package in the list
+ if (enabledServices.removeIf(packageName::equals)) {
+ // Only update the settings if there was a change
+ setNotificationPolicyAccessPackages(enabledServices, instrumentation);
+ }
+ }
+ }
+
+ /** Read the setting listing the package allowed to manage notification policy configuration */
+ private static String querryNotificationPolicyAccessPakages(Instrumentation instrumentation) {
+ ContentResolver cr = instrumentation.getContext().getContentResolver();
+ String enabledService = Settings.Secure.getString(
+ cr,Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
+
+ // A non existing property is equivalent to no package listed
+ if (enabledService == null) {
+ enabledService = "";
+ }
+ return enabledService;
+ }
+
+ private static void setNotificationPolicyAccessPackages(final List<String> enabledServicesList,
+ final Instrumentation instrumentation) throws IOException {
+ // Format the list back to a string
+ String enabledServices = String.join(":", enabledServicesList);
+
+ // If the list is empty, remove the property by setting it to null
+ String enabledServicesStrOrNull = enabledServices.isEmpty() ? "null" : enabledServices;
+
+ // Write back the property to the settings database
+ String command = "settings --user cur put secure "
+ + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
+ + enabledServicesStrOrNull;
// Get permission to enable accessibility
UiAutomation uiAutomation = instrumentation.getUiAutomation();
- ContentResolver cr = context.getContentResolver();
- String alreadyEnabledServices = Settings.Secure.getString(
- cr, Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES);
- ParcelFileDescriptor fd = null;
- if (on) {
- if ((alreadyEnabledServices == null) || !alreadyEnabledServices.contains(packageName)) {
- // Change the settings to enable the media cts package
- final String newEnabledServices = (alreadyEnabledServices == null) ? packageName
- : alreadyEnabledServices + ":" + packageName;
- fd = uiAutomation.executeShellCommand(
- "settings --user cur put secure "
- + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
- + newEnabledServices);
+ // Execute command
+ try (ParcelFileDescriptor fd = uiAutomation.executeShellCommand(command)) {
+ Assert.assertNotNull("Failed to execute shell command: " + command, fd);
+ // Wait for the command to finish by reading until EOF
+ try (InputStream in = new FileInputStream(fd.getFileDescriptor())) {
+ byte[] buffer = new byte[4096];
+ while (in.read(buffer) > 0) {}
+ } catch (IOException e) {
+ throw new IOException("Could not read stdout of command: " + command, e);
}
- } else if (alreadyEnabledServices != null) {
- int index = alreadyEnabledServices.indexOf(":" + packageName);
- if (index >= 0) {
- fd = uiAutomation.executeShellCommand(
- "settings --user cur put secure "
- + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " "
- + alreadyEnabledServices.substring(0, index));
- } else if (alreadyEnabledServices.equals(packageName)) {
- // "packageName" is the only enabled service
- fd = uiAutomation.executeShellCommand("settings --user cur put secure "
- + Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES + " null");
- }
+ } finally {
+ uiAutomation.destroy();
}
- if (fd != null) {
- InputStream in = new FileInputStream(fd.getFileDescriptor());
- byte[] buffer = new byte[4096];
- while (in.read(buffer) > 0) ;
- }
- uiAutomation.destroy();
+
+ // Read the settings again to make sure it is updated
+ String nowEnabledServices = querryNotificationPolicyAccessPakages(instrumentation);
+ Assert.assertEquals("Wrote setting should be the same as the read one",
+ enabledServices, nowEnabledServices);
+
}
/**
diff --git a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java b/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
deleted file mode 100644
index bcecee1..0000000
--- a/tests/tests/net/src/android/net/cts/IpSecManagerTest.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.net.cts;
-
-import android.content.Context;
-import android.net.ConnectivityManager;
-import android.net.IpSecAlgorithm;
-import android.net.IpSecManager;
-import android.net.IpSecTransform;
-import android.os.ParcelFileDescriptor;
-import android.system.Os;
-import android.system.OsConstants;
-import android.test.AndroidTestCase;
-import java.io.ByteArrayOutputStream;
-import java.net.DatagramSocket;
-import java.io.FileDescriptor;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Arrays;
-
-public class IpSecManagerTest extends AndroidTestCase {
-
- private static final String TAG = IpSecManagerTest.class.getSimpleName();
-
- private IpSecManager mISM;
-
- private ConnectivityManager mCM;
-
- private static final InetAddress GOOGLE_DNS_4;
- private static final InetAddress GOOGLE_DNS_6;
-
- static {
- try {
- // Google Public DNS Addresses;
- GOOGLE_DNS_4 = InetAddress.getByName("8.8.8.8");
- GOOGLE_DNS_6 = InetAddress.getByName("2001:4860:4860::8888");
- } catch (UnknownHostException e) {
- throw new RuntimeException("Could not resolve DNS Addresses", e);
- }
- }
-
- private static final InetAddress[] GOOGLE_DNS_LIST =
- new InetAddress[] {GOOGLE_DNS_4, GOOGLE_DNS_6};
-
- private static final int DROID_SPI = 0xD1201D;
-
- private static final byte[] CRYPT_KEY =
- new byte[] {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
- 0x0E, 0x0F
- };
- private static final byte[] AUTH_KEY =
- new byte[] {
- 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x7F
- };
-
- protected void setUp() throws Exception {
- super.setUp();
- mCM = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
- mISM = (IpSecManager) getContext().getSystemService(Context.IPSEC_SERVICE);
- }
-
- /*
- * Allocate a random SPI
- * Allocate a specific SPI using previous randomly created SPI value
- * Realloc the same SPI that was specifically created (expect SpiUnavailable)
- * Close SPIs
- */
- public void testAllocSpi() throws Exception {
- for (InetAddress addr : GOOGLE_DNS_LIST) {
- IpSecManager.SecurityParameterIndex randomSpi = null, droidSpi = null;
- randomSpi = mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, addr);
- assertTrue(
- "Failed to receive a valid SPI",
- randomSpi.getSpi() != IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
-
- droidSpi =
- mISM.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
- assertTrue(
- "Failed to allocate specified SPI, " + DROID_SPI,
- droidSpi.getSpi() == DROID_SPI);
-
- try {
- mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_IN, addr, DROID_SPI);
- fail("Duplicate SPI was allowed to be created");
- } catch (IpSecManager.SpiUnavailableException expected) {
- // This is a success case because we expect a dupe SPI to throw
- }
-
- randomSpi.close();
- droidSpi.close();
- }
- }
-
- /*
- * Alloc outbound SPI
- * Alloc inbound SPI
- * Create transport mode transform
- * open socket
- * apply transform to socket
- * send data on socket
- * release transform
- * send data (expect exception)
- */
- public void testCreateTransform() throws Exception {
- InetAddress local = InetAddress.getLoopbackAddress();
- IpSecManager.SecurityParameterIndex outSpi =
- mISM.reserveSecurityParameterIndex(IpSecTransform.DIRECTION_OUT, local);
-
- IpSecManager.SecurityParameterIndex inSpi =
- mISM.reserveSecurityParameterIndex(
- IpSecTransform.DIRECTION_IN, local, outSpi.getSpi());
-
- IpSecTransform transform =
- new IpSecTransform.Builder(mContext)
- .setSpi(IpSecTransform.DIRECTION_OUT, outSpi)
- .setEncryption(
- IpSecTransform.DIRECTION_OUT,
- new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
- .setAuthentication(
- IpSecTransform.DIRECTION_OUT,
- new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256,
- AUTH_KEY,
- AUTH_KEY.length * 8))
- .setSpi(IpSecTransform.DIRECTION_IN, inSpi)
- .setEncryption(
- IpSecTransform.DIRECTION_IN,
- new IpSecAlgorithm(IpSecAlgorithm.CRYPT_AES_CBC, CRYPT_KEY))
- .setAuthentication(
- IpSecTransform.DIRECTION_IN,
- new IpSecAlgorithm(
- IpSecAlgorithm.AUTH_HMAC_SHA256,
- AUTH_KEY,
- CRYPT_KEY.length * 8))
- .buildTransportModeTransform(local);
-
- // Hack to ensure the socket doesn't block indefinitely on failure
- DatagramSocket localSocket = new DatagramSocket(8888);
- localSocket.setSoTimeout(500);
- ParcelFileDescriptor pin = ParcelFileDescriptor.fromDatagramSocket(localSocket);
- FileDescriptor udpSocket = pin.getFileDescriptor();
-
- mISM.applyTransportModeTransform(udpSocket, transform);
- byte[] data = new String("Best test data ever!").getBytes("UTF-8");
-
- byte[] in = new byte[data.length];
- Os.sendto(udpSocket, data, 0, data.length, 0, local, 8888);
- Os.read(udpSocket, in, 0, in.length);
- assertTrue("Encapsulated data did not match.", Arrays.equals(data, in));
- mISM.removeTransportModeTransform(udpSocket, transform);
- Os.close(udpSocket);
- transform.close();
- }
-}
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index d489a6a..c9650bd 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -33,6 +33,7 @@
import junit.framework.TestCase;
+import static android.os.Build.VERSION.CODENAME;
import static android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
public class BuildTest extends TestCase {
@@ -223,21 +224,7 @@
assertTrue(TYPE_PATTERN.matcher(Build.TYPE).matches());
assertNotEmpty(Build.USER);
- }
- public void testBuildConstants_forPrereleaseOrRelease() {
- checkBuildConstants(CUR_DEVELOPMENT);
- }
-
- @RestrictedBuildTest // Expected to fail on prelease/dev builds, http://b/35922665
- public void testBuildConstants_forRelease() {
- checkBuildConstants(CUR_DEVELOPMENT - 1);
- }
-
- /**
- * @param maxAllowedValue the maximum permitted value for constants other than CUR_DEVELOPMENT
- */
- private static void checkBuildConstants(int maxAllowedValue) {
// CUR_DEVELOPMENT must be larger than any released version.
Field[] fields = Build.VERSION_CODES.class.getDeclaredFields();
for (Field field : fields) {
@@ -253,9 +240,12 @@
// It should be okay to change the value of this constant in future, but it
// should at least be a conscious decision.
assertEquals(10000, fieldValue);
+ } else if (fieldName.equals(CODENAME) && !CODENAME.equals("REL")) {
+ // This is the current development version.
+ assertEquals(CUR_DEVELOPMENT, fieldValue);
} else {
- assertTrue("Expected " + fieldName + " value to be <= " + maxAllowedValue
- + ", got " + fieldValue, fieldValue <= maxAllowedValue);
+ assertTrue("Expected " + fieldName + " value to be < " + CUR_DEVELOPMENT
+ + ", got " + fieldValue, fieldValue < CUR_DEVELOPMENT);
}
}
}
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java
index 2e30e0c..8e521b9 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceDataStoreTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalMatchers.or;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
@@ -35,9 +36,11 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.SharedPreferences;
+import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceDataStore;
import android.preference.PreferenceManager;
@@ -149,6 +152,40 @@
assertEquals(TEST_DEFAULT_STR, mPreference.defaultValue);
}
+ /**
+ * Test that the initial value is taken from the data store (before the preference gets assigned
+ * to the preference hierarchy).
+ */
+ @Test
+ public void testInitialValueIsTakenFromDSOnPref() {
+ when(mDataStore.getBoolean(anyString(), anyBoolean())).thenReturn(true);
+
+ CheckBoxPreference pref = new CheckBoxPreference(mActivityRule.getActivity());
+ pref.setKey("CheckboxTestPref");
+ pref.setPreferenceDataStore(mDataStore);
+
+ mScreen.addPreference(pref);
+
+ assertTrue(pref.isChecked());
+ }
+
+ /**
+ * Test that the initial value is taken from the data store (before the preference gets assigned
+ * to the preference hierarchy).
+ */
+ @Test
+ public void testInitialValueIsTakenFromDSOnMgr() {
+ when(mDataStore.getBoolean(anyString(), anyBoolean())).thenReturn(true);
+ mManager.setPreferenceDataStore(mDataStore);
+
+ CheckBoxPreference pref = new CheckBoxPreference(mActivityRule.getActivity());
+ pref.setKey("CheckboxTestPref");
+
+ mScreen.addPreference(pref);
+
+ assertTrue(pref.isChecked());
+ }
+
@Test
public void testPutStringSetWithDataStoreOnPref() {
mPreference.setPreferenceDataStore(mDataStore);
diff --git a/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java b/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java
index 5de6e81..a645dc8 100644
--- a/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java
+++ b/tests/tests/preference2/src/android/preference2/cts/PreferenceParentGroupTest.java
@@ -26,6 +26,7 @@
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
+import android.test.UiThreadTest;
import org.junit.Before;
import org.junit.Rule;
@@ -56,6 +57,7 @@
* from code.
*/
@Test
+ @UiThreadTest
public void parentViaCodeTest() {
PreferenceScreen screen = mActivity.getPreferenceScreen();
assertNull(screen.getParent());
@@ -84,6 +86,7 @@
* To see the tested hierarchy check pref_nested.xml.
*/
@Test
+ @UiThreadTest
public void parentViaInflationTest() {
PreferenceScreen screen = mActivity.getPreferenceScreen();
@@ -112,6 +115,7 @@
* Adds preference into two different groups without removing it first.
*/
@Test
+ @UiThreadTest
public void parentDoubleAddTest() throws InterruptedException {
PreferenceScreen screen = mActivity.getPreferenceScreen();
diff --git a/tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java b/tests/tests/provider/src/android/provider/cts/FontRequestTest.java
similarity index 62%
rename from tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java
rename to tests/tests/provider/src/android/provider/cts/FontRequestTest.java
index 1b00975..d9b8a7f 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/cts/FontRequestTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontRequestTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.graphics.fonts.cts;
+package android.provider.cts;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import android.graphics.fonts.FontRequest;
+import android.provider.FontRequest;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
@@ -35,7 +35,7 @@
import java.util.List;
/**
- * Tests for {@link android.graphics.fonts.FontRequest}.
+ * Tests for {@link android.provider.FontRequest}.
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -47,46 +47,6 @@
Base64.decode("e04fd020ea3a6910a2d808002b30", Base64.DEFAULT);
private static final List<List<byte[]>> CERTS = Arrays.asList(Arrays.asList(BYTE_ARRAY));
- @Test
- public void testWriteToParcel() {
- // GIVEN a FontRequest created with the long constructor
- FontRequest request = new FontRequest(PROVIDER, PACKAGE, QUERY, CERTS);
-
- // WHEN we write it to a Parcel
- Parcel dest = Parcel.obtain();
- request.writeToParcel(dest, 0);
- dest.setDataPosition(0);
-
- // THEN we create from that parcel and get the same values.
- FontRequest result = FontRequest.CREATOR.createFromParcel(dest);
- assertEquals(PROVIDER, result.getProviderAuthority());
- assertEquals(PACKAGE, result.getProviderPackage());
- assertEquals(QUERY, result.getQuery());
- assertEquals(CERTS.size(), result.getCertificates().size());
- List<byte[]> cert = CERTS.get(0);
- List<byte[]> resultCert = result.getCertificates().get(0);
- assertEquals(cert.size(), resultCert.size());
- assertTrue(Arrays.equals(cert.get(0), resultCert.get(0)));
- }
-
- @Test
- public void testWriteToParcel_shortConstructor() {
- // GIVEN a FontRequest created with the short constructor
- FontRequest request = new FontRequest(PROVIDER, PACKAGE, QUERY);
-
- // WHEN we write it to a Parcel
- Parcel dest = Parcel.obtain();
- request.writeToParcel(dest, 0);
- dest.setDataPosition(0);
-
- // THEN we create from that parcel and get the same values.
- FontRequest result = FontRequest.CREATOR.createFromParcel(dest);
- assertEquals(PROVIDER, result.getProviderAuthority());
- assertEquals(PACKAGE, result.getProviderPackage());
- assertEquals(QUERY, result.getQuery());
- assertNotNull(result.getCertificates());
- assertEquals(0, result.getCertificates().size());
- }
@Test(expected = NullPointerException.class)
public void testShortConstructor_nullAuthority() {
diff --git a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
index 472aed8..745a490 100644
--- a/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
+++ b/tests/tests/provider/src/android/provider/cts/FontsContractTest.java
@@ -29,8 +29,8 @@
import android.content.pm.PackageInfo;
import android.content.Context;
import android.graphics.Typeface;
-import android.graphics.fonts.FontRequest;
import android.graphics.fonts.FontVariationAxis;
+import android.provider.FontRequest;
import android.provider.FontsContract;
import android.provider.FontsContract.FontFamilyResult;
import android.provider.FontsContract.FontInfo;
diff --git a/tests/tests/security/res/raw/bug_34097672.mp4 b/tests/tests/security/res/raw/bug_34097672.mp4
new file mode 100644
index 0000000..79acdf4
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_34097672.mp4
Binary files differ
diff --git a/tests/tests/security/res/raw/bug_34360591.mp4 b/tests/tests/security/res/raw/bug_34360591.mp4
new file mode 100644
index 0000000..28c47d3
--- /dev/null
+++ b/tests/tests/security/res/raw/bug_34360591.mp4
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index f120426..031b9f7 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -73,6 +73,10 @@
before any existing test methods
***********************************************************/
+ public void testStagefright_bug_34360591() throws Exception {
+ doStagefrightTest(R.raw.bug_34360591);
+ }
+
public void testStagefright_bug_35763994() throws Exception {
doStagefrightTest(R.raw.bug_35763994);
}
@@ -183,6 +187,11 @@
***********************************************************/
@SecurityTest
+ public void testStagefright_bug_34097672() throws Exception {
+ doStagefrightTest(R.raw.bug_34097672);
+ }
+
+ @SecurityTest
public void testStagefright_bug_33818508() throws Exception {
doStagefrightTest(R.raw.bug_33818508);
}
diff --git a/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java b/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java
index 872820a..3920bcf 100644
--- a/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ActivityTransitionTest.java
@@ -88,18 +88,18 @@
}
@After
- public void cleanup() {
+ public void cleanup() throws Throwable {
if (TargetActivity.sLastCreated != null) {
- mInstrumentation.runOnMainSync(() -> TargetActivity.sLastCreated.finish());
+ mActivityRule.runOnUiThread(() -> TargetActivity.sLastCreated.finish());
}
TargetActivity.sLastCreated = null;
}
// When using ActivityOptions.makeBasic(), no transitions should run
@Test
- public void testMakeBasic() {
+ public void testMakeBasic() throws Throwable {
assertFalse(mActivity.isActivityTransitionRunning());
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
Intent intent = new Intent(mActivity, TargetActivity.class);
ActivityOptions activityOptions =
ActivityOptions.makeBasic();
@@ -110,7 +110,7 @@
TargetActivity targetActivity = waitForTargetActivity();
assertFalse(targetActivity.isActivityTransitionRunning());
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
targetActivity.finish();
});
@@ -123,7 +123,7 @@
@Test
public void viewsNotStripped() throws Throwable {
enterScene(R.layout.scene10);
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
View sharedElement = mActivity.findViewById(R.id.blueSquare);
Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
sharedElement, "holder").toBundle();
@@ -156,7 +156,7 @@
assertEquals(1, targetActivity.findViewById(R.id.greenSquare).getAlpha(), 0.01f);
assertEquals(1, targetActivity.findViewById(R.id.holder).getAlpha(), 0.01f);
- mInstrumentation.runOnMainSync(() -> targetActivity.finishAfterTransition());
+ mActivityRule.runOnUiThread(() -> targetActivity.finishAfterTransition());
verify(mReenterListener, within(3000)).onTransitionEnd(any());
verify(mSharedElementReenterListener, within(3000)).onTransitionEnd(any());
verify(targetActivity.returnListener, times(1)).onTransitionEnd(any());
@@ -195,7 +195,7 @@
@Test
public void viewsStripped() throws Throwable {
enterScene(R.layout.scene13);
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
View sharedElement = mActivity.findViewById(R.id.redSquare);
Bundle options = ActivityOptions.makeSceneTransitionAnimation(mActivity,
sharedElement, "redSquare").toBundle();
@@ -227,7 +227,7 @@
assertEquals(1, targetActivity.findViewById(R.id.greenSquare).getAlpha(), 0.01f);
assertEquals(1, targetActivity.findViewById(R.id.holder).getAlpha(), 0.01f);
- mInstrumentation.runOnMainSync(() -> targetActivity.finishAfterTransition());
+ mActivityRule.runOnUiThread(() -> targetActivity.finishAfterTransition());
verify(mReenterListener, within(3000)).onTransitionEnd(any());
verify(mSharedElementReenterListener, within(3000)).onTransitionEnd(any());
verify(targetActivity.returnListener, times(1)).onTransitionEnd(any());
@@ -267,7 +267,7 @@
final View hello = mActivity.findViewById(R.id.hello);
final View red = mActivity.findViewById(R.id.redSquare);
final View green = mActivity.findViewById(R.id.greenSquare);
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
Fade fade = new Fade();
fade.setDuration(10000);
fade.addListener(mExitListener);
@@ -282,7 +282,7 @@
verify(targetActivity.enterListener, within(3000)).onTransitionEnd(any());
verify(mExitListener, within(3000)).onTransitionEnd(any());
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
// Verify that the exited views have an alpha of 1 and are visible
assertEquals(1.0f, hello.getAlpha(), 0.01f);
assertEquals(1.0f, red.getAlpha(), 0.01f);
@@ -296,9 +296,9 @@
}
@Test
- public void testAnimationQuery() {
+ public void testAnimationQuery() throws Throwable {
assertFalse(mActivity.isActivityTransitionRunning());
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
mActivity.getWindow().setExitTransition(new Fade());
Intent intent = new Intent(mActivity, TargetActivity.class);
ActivityOptions activityOptions =
@@ -310,12 +310,19 @@
TargetActivity targetActivity = waitForTargetActivity();
assertTrue(targetActivity.isActivityTransitionRunning());
- mInstrumentation.runOnMainSync(() -> {
- targetActivity.finish();
+ mActivityRule.runOnUiThread(() -> { });
+ PollingCheck.waitFor(() -> !targetActivity.isActivityTransitionRunning());
+
+ assertFalse(mActivity.isActivityTransitionRunning());
+ mActivityRule.runOnUiThread(() -> {
+ targetActivity.finishAfterTransition();
+ // The target activity transition should start right away
+ assertTrue(targetActivity.isActivityTransitionRunning());
});
- assertTrue(targetActivity.isActivityTransitionRunning());
- assertTrue(mActivity.isActivityTransitionRunning());
+ // The source activity transition should start sometime later
+ PollingCheck.waitFor(() -> mActivity.isActivityTransitionRunning());
+ PollingCheck.waitFor(() -> !mActivity.isActivityTransitionRunning());
}
// Views that are excluded from the exit/enter transition shouldn't change visibility
@@ -380,10 +387,10 @@
TargetActivity.sLastCreated = null;
}
- private TargetActivity waitForTargetActivity() {
+ private TargetActivity waitForTargetActivity() throws Throwable {
PollingCheck.waitFor(() -> TargetActivity.sLastCreated != null);
// Just make sure that we're not in the middle of running on the UI thread.
- mInstrumentation.runOnMainSync(() -> {});
+ mActivityRule.runOnUiThread(() -> { });
return TargetActivity.sLastCreated;
}
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
index 4b55057..d11051f 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeBoundsTest.java
@@ -77,7 +77,7 @@
startTransition(R.layout.scene6);
// The update listener will validate that it is changing throughout the animation
- waitForEnd(400);
+ waitForEnd(800);
validateInScene6();
}
@@ -96,7 +96,7 @@
startTransition(R.layout.scene6);
// The update listener will validate that it is changing throughout the animation
- waitForEnd(400);
+ waitForEnd(800);
validateInScene6();
}
@@ -112,7 +112,7 @@
startTransition(R.layout.scene1);
// The update listener will validate that it is changing throughout the animation
- waitForEnd(400);
+ waitForEnd(800);
validateInScene1();
}
@@ -131,7 +131,7 @@
startTransition(R.layout.scene6);
assertFalse(isRestartingAnimation());
- waitForEnd(500);
+ waitForEnd(1000);
validateInScene6();
}
@@ -153,7 +153,7 @@
assertFalse(isRestartingAnimation());
assertFalse(isRestartingClip());
- waitForEnd(500);
+ waitForEnd(1000);
validateInScene6();
}
@@ -172,7 +172,7 @@
startTransition(R.layout.scene1);
assertFalse(isRestartingAnimation());
- waitForEnd(500);
+ waitForEnd(1000);
validateInScene1();
}
@@ -195,7 +195,7 @@
assertFalse(isRestartingAnimation());
assertFalse(isRestartingClip());
- waitForEnd(500);
+ waitForEnd(1000);
validateInScene1();
}
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java b/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
index b27364e..6ae8a9f 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeImageTransformTest.java
@@ -236,7 +236,7 @@
});
waitForStart();
verify(mListener, (startScale == endScale) ? times(1) : never()).onTransitionEnd(any());
- waitForEnd(200);
+ waitForEnd(1000);
}
private ImageView enterImageViewScene(final ScaleType scaleType) throws Throwable {
diff --git a/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java b/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
index fb231fa..38474a2 100644
--- a/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
+++ b/tests/tests/transition/src/android/transition/cts/ChangeTransformTest.java
@@ -66,7 +66,7 @@
verify(mListener, never()).onTransitionEnd(any()); // still running
// There is no way to validate the intermediate matrix because it uses
// hidden properties of the View to execute.
- waitForEnd(400);
+ waitForEnd(800);
assertEquals(500f, redSquare.getTranslationX(), 0.0f);
assertEquals(600f, redSquare.getTranslationY(), 0.0f);
}
@@ -86,7 +86,7 @@
verify(mListener, never()).onTransitionEnd(any()); // still running
// There is no way to validate the intermediate matrix because it uses
// hidden properties of the View to execute.
- waitForEnd(400);
+ waitForEnd(800);
assertEquals(45f, redSquare.getRotation(), 0.0f);
}
@@ -106,7 +106,7 @@
verify(mListener, never()).onTransitionEnd(any()); // still running
// There is no way to validate the intermediate matrix because it uses
// hidden properties of the View to execute.
- waitForEnd(400);
+ waitForEnd(800);
assertEquals(2f, redSquare.getScaleX(), 0.0f);
assertEquals(3f, redSquare.getScaleY(), 0.0f);
}
@@ -117,7 +117,7 @@
enterScene(R.layout.scene5);
startTransition(R.layout.scene9);
verify(mListener, never()).onTransitionEnd(any()); // still running
- waitForEnd(400);
+ waitForEnd(800);
resetListener();
mChangeTransform.setReparent(false);
@@ -142,7 +142,7 @@
mSceneRoot.getOverlay().remove(view);
assertTrue(mActivity.findViewById(R.id.text).getVisibility() != View.VISIBLE);
});
- waitForEnd(400);
+ waitForEnd(800);
mChangeTransform.setReparentWithOverlay(false);
assertEquals(false, mChangeTransform.getReparentWithOverlay());
@@ -159,7 +159,7 @@
mSceneRoot.getOverlay().remove(view);
assertEquals(View.VISIBLE, mActivity.findViewById(R.id.text).getVisibility());
});
- waitForEnd(400);
+ waitForEnd(800);
}
}
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
index d4375cc..f48f780 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionManagerTest.java
@@ -54,7 +54,7 @@
});
waitForStart();
- waitForEnd(300);
+ waitForEnd(800);
verify(mListener, never()).onTransitionResume(any());
verify(mListener, never()).onTransitionPause(any());
verify(mListener, never()).onTransitionCancel(any());
@@ -109,7 +109,7 @@
public void testGo() throws Throwable {
startTransition(R.layout.scene1);
waitForStart();
- waitForEnd(300);
+ waitForEnd(800);
verify(mListener, never()).onTransitionResume(any());
verify(mListener, never()).onTransitionPause(any());
@@ -156,7 +156,7 @@
});
waitForStart();
- waitForEnd(300);
+ waitForEnd(800);
verify(mListener, never()).onTransitionResume(any());
verify(mListener, never()).onTransitionPause(any());
verify(mListener, never()).onTransitionCancel(any());
@@ -195,7 +195,7 @@
mActivityRule.runOnUiThread(() -> transitionManager.transitionTo(scenes[1]));
waitForStart();
- waitForEnd(300);
+ waitForEnd(800);
verify(mListener, never()).onTransitionResume(any());
verify(mListener, never()).onTransitionPause(any());
verify(mListener, never()).onTransitionCancel(any());
@@ -220,7 +220,7 @@
startTransition(R.layout.scene1);
waitForStart();
endTransition();
- waitForEnd(100);
+ waitForEnd(400);
}
@Test
diff --git a/tests/tests/transition/src/android/transition/cts/TransitionTest.java b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
index 9aaaeec..cc13eda 100644
--- a/tests/tests/transition/src/android/transition/cts/TransitionTest.java
+++ b/tests/tests/transition/src/android/transition/cts/TransitionTest.java
@@ -605,7 +605,7 @@
enterScene(scene1);
- mInstrumentation.runOnMainSync(() -> {
+ mActivityRule.runOnUiThread(() -> {
// scene1
assertSame(layout1, mActivity.findViewById(R.id.holder));
assertNotNull(mActivity.findViewById(R.id.hello));
diff --git a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
index a71748a..6b608e4 100644
--- a/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
+++ b/tests/tests/transition/src/android/transition/cts/VisibilityTest.java
@@ -61,19 +61,19 @@
enterScene(R.layout.scene4);
startTransition(R.layout.scene1);
verify(mListener, never()).onTransitionEnd(any());
- waitForEnd(400);
+ waitForEnd(800);
resetListener();
startTransition(R.layout.scene4);
verify(mListener, never()).onTransitionEnd(any());
- waitForEnd(400);
+ waitForEnd(800);
// Now only animate in
resetListener();
mVisibilityTransition.setMode(Visibility.MODE_IN);
startTransition(R.layout.scene1);
verify(mListener, never()).onTransitionEnd(any());
- waitForEnd(400);
+ waitForEnd(800);
// No animation since it should only animate in
resetListener();
@@ -90,7 +90,7 @@
resetListener();
startTransition(R.layout.scene4);
verify(mListener, never()).onTransitionEnd(any());
- waitForEnd(400);
+ waitForEnd(800);
}
@Test
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
index c47b4b1..aac14e6 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
@@ -77,6 +77,8 @@
/** It is defined in R.anim.decelerate_alpha */
private static final int DECELERATE_ALPHA_DURATION = 2000;
+ private static final int CANCELATION_TIMEOUT = 1000;
+
private Instrumentation mInstrumentation;
private Activity mActivity;
@@ -658,7 +660,7 @@
MyAnimation anim = new MyAnimation();
final CountDownLatch latch1 = new CountDownLatch(1);
runCanceledAnimation(anim, latch1, false, false);
- assertTrue(latch1.await(200, TimeUnit.MILLISECONDS));
+ assertTrue(latch1.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
assertFalse(anim.isStillAnimating());
}
@@ -667,7 +669,7 @@
MyAnimation anim = new MyAnimation();
final CountDownLatch latch2 = new CountDownLatch(1);
runCanceledAnimation(anim, latch2, true, false);
- assertTrue(latch2.await(200, TimeUnit.MILLISECONDS));
+ assertTrue(latch2.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
assertFalse(anim.isStillAnimating());
}
@@ -676,7 +678,7 @@
MyAnimation anim = new MyAnimation();
final CountDownLatch latch3 = new CountDownLatch(1);
runCanceledAnimation(anim, latch3, false, true);
- assertTrue(latch3.await(250, TimeUnit.MILLISECONDS));
+ assertTrue(latch3.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
assertFalse(anim.isStillAnimating());
}
@@ -685,7 +687,7 @@
MyAnimation anim = new MyAnimation();
final CountDownLatch latch4 = new CountDownLatch(1);
runCanceledAnimation(anim, latch4, true, true);
- assertTrue(latch4.await(250, TimeUnit.MILLISECONDS));
+ assertTrue(latch4.await(CANCELATION_TIMEOUT, TimeUnit.MILLISECONDS));
assertFalse(anim.isStillAnimating());
}
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index e912981..1d86477 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -190,4 +190,7 @@
<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/37105075 -->
+ <option name="compatibility:exclude-filter" value="CtsIncidentHostTestCases com.android.server.cts.BatteryStatsValidationTest#testWifiUpload" />
+
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-sts.xml b/tools/cts-tradefed/res/config/security-bulletin.xml
similarity index 95%
rename from tools/cts-tradefed/res/config/cts-sts.xml
rename to tools/cts-tradefed/res/config/security-bulletin.xml
index 8e4c030..02175a9 100644
--- a/tools/cts-tradefed/res/config/cts-sts.xml
+++ b/tools/cts-tradefed/res/config/security-bulletin.xml
@@ -15,7 +15,7 @@
-->
<configuration description="Runs Security Patch test cases">
- <option name="plan" value="cts-sts" />
+ <option name="plan" value="security-bulletin" />
<include name="cts"/>