Tests setting default ringers to external storage.
In an app with WRITE_EXTERNAL_STORAGE, add an mp3 from external storage
to the media provider then set the default ringtone URI's to that entry.
In an app without READ_EXTERNAL_STORAGE, play the changed default URI's
as owner and additional users.
Test: cts-tradefed run cts --module CtsAppSecurityHostTestCases -t android.appsecurity.cts.ExternalStorageHostTest#testExternalStorageReadDefaultUris
Bug: 36571322
Bug: 30572189
Change-Id: I6818c751b21a26f3d25fbafb37c9e37688eb33b8
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
index b2f4685..6ee51ae 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ExternalStorageHostTest.java
@@ -280,6 +280,49 @@
}
}
+ /** Verify that app without READ_EXTERNAL can play default URIs in external storage. */
+ public void testExternalStorageReadDefaultUris() throws Exception {
+ final int[] users = createUsersForTest();
+ try {
+ wipePrimaryExternalStorage();
+
+ getDevice().uninstallPackage(NONE_PKG);
+ getDevice().uninstallPackage(WRITE_PKG);
+ final String[] options = {AbiUtils.createAbiFlag(mAbi.getName())};
+
+ assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
+ enableWriteSettings(WRITE_PKG);
+ runDeviceTests(
+ WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testChangeDefaultUris", users[0]);
+
+ assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
+
+ for (int user : users) {
+ runDeviceTests(
+ NONE_PKG, NONE_PKG + ".ReadDefaultUris", "testPlayDefaultUris", user);
+ }
+ } finally {
+ // Make sure the provider and uris are reset on failure.
+ runDeviceTests(
+ WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testResetDefaultUris", users[0]);
+ getDevice().uninstallPackage(NONE_PKG);
+ getDevice().uninstallPackage(WRITE_PKG);
+ removeUsersForTest(users);
+ }
+ }
+
+ private void enableWriteSettings(String packageName) throws DeviceNotAvailableException {
+ StringBuilder cmd = new StringBuilder();
+ cmd.append("appops set ");
+ cmd.append(packageName);
+ cmd.append(" android:write_settings allow");
+ getDevice().executeShellCommand(cmd.toString());
+ try {
+ Thread.sleep(2200);
+ } catch (InterruptedException e) {
+ }
+ }
+
private void wipePrimaryExternalStorage() throws DeviceNotAvailableException {
getDevice().executeShellCommand("rm -rf /sdcard/Android");
getDevice().executeShellCommand("rm -rf /sdcard/DCIM");
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ReadDefaultUris.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ReadDefaultUris.java
new file mode 100644
index 0000000..37476f7
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ReadDefaultUris.java
@@ -0,0 +1,72 @@
+/*
+ * 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.externalstorageapp;
+
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.provider.Settings;
+import android.test.AndroidTestCase;
+
+/** Verify system default URI's can be read without READ_EXTERNAL_STORAGE permission. */
+public class ReadDefaultUris extends AndroidTestCase {
+
+ private AudioManager mAudioManager;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ }
+
+ public void testPlayDefaultUris() throws Exception {
+ final long timeToPlayMs = 1000;
+ playUri(
+ Settings.System.DEFAULT_NOTIFICATION_URI,
+ timeToPlayMs,
+ AudioAttributes.USAGE_NOTIFICATION,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION);
+ playUri(
+ Settings.System.DEFAULT_RINGTONE_URI,
+ timeToPlayMs,
+ AudioAttributes.USAGE_NOTIFICATION_RINGTONE,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION);
+ playUri(
+ Settings.System.DEFAULT_ALARM_ALERT_URI,
+ timeToPlayMs,
+ AudioAttributes.USAGE_ALARM,
+ AudioAttributes.CONTENT_TYPE_SONIFICATION);
+ }
+
+ private void playUri(final Uri uri, long timeToPlayMs, int usage, int contentType)
+ throws Exception {
+ MediaPlayer mp = new MediaPlayer();
+ assertNotNull(mp);
+ mp.setDataSource(mContext, uri);
+ mp.setAudioAttributes(
+ new AudioAttributes.Builder().setUsage(usage).setContentType(contentType).build());
+ mp.prepare();
+ mp.start();
+ Thread.sleep(timeToPlayMs);
+ mp.stop();
+ mp.release();
+ Thread.sleep(timeToPlayMs);
+ assertFalse(mAudioManager.isMusicActive());
+ }
+}
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
index 0729b66..61d2493 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
@@ -18,11 +18,14 @@
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test compatibility-device-util
+#ctsdeviceutil
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
../ExternalStorageApp/src/com/android/cts/externalstorageapp/CommonExternalStorageTest.java
+LOCAL_JAVA_RESOURCE_DIRS := $(LOCAL_PATH)/res
+
# tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/res/raw/ringer.mp3 b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/res/raw/ringer.mp3
new file mode 100644
index 0000000..aa052e7
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/res/raw/ringer.mp3
Binary files differ
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/ChangeDefaultUris.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/ChangeDefaultUris.java
new file mode 100644
index 0000000..7fa39b4
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/ChangeDefaultUris.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.writeexternalstorageapp;
+
+import android.content.ContentValues;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.MediaStore;
+import android.test.AndroidTestCase;
+import com.android.compatibility.common.util.FileCopyHelper;
+import java.io.File;
+
+/** Sets up providers and notifications using external storage. */
+public class ChangeDefaultUris extends AndroidTestCase {
+
+ /** Unique title for provider insert and delete. */
+ private static final String RINGER_TITLE = "CTS ringer title";
+
+ public void testChangeDefaultUris() throws Exception {
+ File mediaFile =
+ new File(
+ Environment.getExternalStorageDirectory(),
+ "ringer" + System.currentTimeMillis() + ".mp3");
+ FileCopyHelper copier = new FileCopyHelper(mContext);
+ copier.copyToExternalStorage(R.raw.ringer, mediaFile);
+
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.DATA, mediaFile.getPath());
+ values.put(MediaStore.MediaColumns.TITLE, RINGER_TITLE);
+ values.put(MediaStore.MediaColumns.MIME_TYPE, "audio/mp3");
+ values.put(MediaStore.Audio.AudioColumns.ARTIST, "CTS ringer artist");
+ values.put(MediaStore.Audio.AudioColumns.IS_RINGTONE, true);
+ values.put(MediaStore.Audio.AudioColumns.IS_NOTIFICATION, true);
+ values.put(MediaStore.Audio.AudioColumns.IS_ALARM, true);
+ values.put(MediaStore.Audio.AudioColumns.IS_MUSIC, false);
+
+ Uri uri =
+ mContext.getContentResolver()
+ .insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
+
+ RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, uri);
+ RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_ALARM, uri);
+ RingtoneManager.setActualDefaultRingtoneUri(
+ mContext, RingtoneManager.TYPE_NOTIFICATION, uri);
+ }
+
+ /** Resets and cleans up to a valid state. This method must not fail. */
+ public void testResetDefaultUris() {
+ mContext.getContentResolver()
+ .delete(
+ MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+ MediaStore.MediaColumns.TITLE + " = ?",
+ new String[] {RINGER_TITLE});
+
+ Uri uri = RingtoneManager.getValidRingtoneUri(mContext);
+ RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, uri);
+ RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_ALARM, uri);
+ RingtoneManager.setActualDefaultRingtoneUri(
+ mContext, RingtoneManager.TYPE_NOTIFICATION, uri);
+ }
+}