1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.provider.cts.media; 18 19 import static android.provider.cts.media.MediaStoreTest.TAG; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertNotEquals; 23 import static org.junit.Assert.assertNotNull; 24 import static org.junit.Assert.assertTrue; 25 26 import android.content.ContentResolver; 27 import android.content.ContentValues; 28 import android.content.Context; 29 import android.database.Cursor; 30 import android.net.Uri; 31 import android.os.Build; 32 import android.provider.MediaStore; 33 import android.provider.MediaStore.Audio.Playlists; 34 import android.provider.MediaStore.MediaColumns; 35 import android.util.Log; 36 37 import androidx.test.InstrumentationRegistry; 38 import androidx.test.filters.SdkSuppress; 39 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.junit.runners.Parameterized; 44 import org.junit.runners.Parameterized.Parameter; 45 import org.junit.runners.Parameterized.Parameters; 46 47 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R) 48 @RunWith(Parameterized.class) 49 public class MediaStore_Audio_PlaylistsTest { 50 private Context mContext; 51 private ContentResolver mContentResolver; 52 53 @Parameter(0) 54 public String mVolumeName; 55 56 @Parameters data()57 public static Iterable<? extends Object> data() { 58 return MediaProviderTestUtils.getSharedVolumeNames(); 59 } 60 61 @Before setUp()62 public void setUp() throws Exception { 63 mContext = InstrumentationRegistry.getTargetContext(); 64 mContentResolver = mContext.getContentResolver(); 65 66 Log.d(TAG, "Using volume " + mVolumeName); 67 } 68 69 @Test testGetContentUri()70 public void testGetContentUri() { 71 Cursor c = null; 72 assertNotNull(c = mContentResolver.query( 73 Playlists.getContentUri(mVolumeName), null, null, 74 null, null)); 75 c.close(); 76 } 77 78 @Test testStoreAudioPlaylistsExternal()79 public void testStoreAudioPlaylistsExternal() throws Exception { 80 ContentValues values = new ContentValues(); 81 values.put(Playlists.NAME, "My favourites " + System.nanoTime()); 82 long dateAdded = System.currentTimeMillis() / 1000; 83 long dateModified = System.currentTimeMillis() / 1000; 84 values.put(Playlists.DATE_MODIFIED, dateModified); 85 // insert 86 Uri uri = mContentResolver.insert(Playlists.getContentUri(mVolumeName), values); 87 assertNotNull(uri); 88 89 try { 90 // query 91 Cursor c = mContentResolver.query(uri, null, null, null, null); 92 assertEquals(1, c.getCount()); 93 c.moveToFirst(); 94 assertEquals(values.getAsString(Playlists.NAME), 95 c.getString(c.getColumnIndex(Playlists.NAME))); 96 97 long realDateAdded = c.getLong(c.getColumnIndex(Playlists.DATE_ADDED)); 98 long realDateModified = c.getLong(c.getColumnIndex(Playlists.DATE_MODIFIED)); 99 assertTrue(realDateAdded >= dateAdded); 100 // Sometimes the realDateModified is less than dateModified by exactly one second. 101 // We've never seen any real issues with that and now the Playlists are deprecated. 102 // Just changing the test to remove flakiness. 103 assertTrue(Math.abs(dateModified - realDateModified) <= 1); 104 assertTrue(c.getLong(c.getColumnIndex(Playlists._ID)) > 0); 105 c.close(); 106 } finally { 107 assertEquals(1, mContentResolver.delete(uri, null, null)); 108 } 109 } 110 111 /** 112 * Verify that creating playlists using only {@link Playlists#NAME} defined 113 * will flow into the {@link MediaColumns#DISPLAY_NAME}, both during initial 114 * insert and subsequent updates. 115 */ 116 @Test testName()117 public void testName() throws Exception { 118 final String name1 = "Playlist " + System.nanoTime(); 119 final String name2 = "Playlist " + System.nanoTime(); 120 assertNotEquals(name1, name2); 121 122 final ContentValues values = new ContentValues(); 123 values.clear(); 124 values.put(Playlists.NAME, name1); 125 final Uri playlist = mContentResolver 126 .insert(MediaStore.Audio.Playlists.getContentUri(mVolumeName), values); 127 MediaStore.waitForIdle(mContentResolver); 128 try (Cursor c = mContentResolver.query(playlist, 129 new String[] { Playlists.NAME, MediaColumns.DISPLAY_NAME }, null, null)) { 130 assertTrue(c.moveToFirst()); 131 assertTrue(c.getString(0).startsWith(name1)); 132 assertTrue(c.getString(1).startsWith(name1)); 133 } 134 135 values.clear(); 136 values.put(Playlists.NAME, name2); 137 mContentResolver.update(playlist, values, null); 138 MediaStore.waitForIdle(mContentResolver); 139 try (Cursor c = mContentResolver.query(playlist, 140 new String[] { Playlists.NAME, MediaColumns.DISPLAY_NAME }, null, null)) { 141 assertTrue(c.moveToFirst()); 142 assertTrue(c.getString(0).startsWith(name2)); 143 assertTrue(c.getString(1).startsWith(name2)); 144 } 145 } 146 } 147