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.provider.cts.ProviderTestUtils;
36 import android.util.Log;
37 
38 import androidx.test.InstrumentationRegistry;
39 import androidx.test.filters.SdkSuppress;
40 
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.junit.runners.Parameterized;
45 import org.junit.runners.Parameterized.Parameter;
46 import org.junit.runners.Parameterized.Parameters;
47 
48 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
49 @RunWith(Parameterized.class)
50 public class MediaStore_Audio_PlaylistsTest {
51     private Context mContext;
52     private ContentResolver mContentResolver;
53 
54     @Parameter(0)
55     public String mVolumeName;
56 
57     @Parameters
data()58     public static Iterable<? extends Object> data() {
59         return ProviderTestUtils.getSharedVolumeNames();
60     }
61 
62     @Before
setUp()63     public void setUp() throws Exception {
64         mContext = InstrumentationRegistry.getTargetContext();
65         mContentResolver = mContext.getContentResolver();
66 
67         Log.d(TAG, "Using volume " + mVolumeName);
68     }
69 
70     @Test
testGetContentUri()71     public void testGetContentUri() {
72         Cursor c = null;
73         assertNotNull(c = mContentResolver.query(
74                 Playlists.getContentUri(mVolumeName), null, null,
75                 null, null));
76         c.close();
77     }
78 
79     @Test
testStoreAudioPlaylistsExternal()80     public void testStoreAudioPlaylistsExternal() throws Exception {
81         ContentValues values = new ContentValues();
82         values.put(Playlists.NAME, "My favourites " + System.nanoTime());
83         long dateAdded = System.currentTimeMillis() / 1000;
84         long dateModified = System.currentTimeMillis() / 1000;
85         values.put(Playlists.DATE_MODIFIED, dateModified);
86         // insert
87         Uri uri = mContentResolver.insert(Playlists.getContentUri(mVolumeName), values);
88         assertNotNull(uri);
89 
90         try {
91             // query
92             Cursor c = mContentResolver.query(uri, null, null, null, null);
93             assertEquals(1, c.getCount());
94             c.moveToFirst();
95             assertEquals(values.getAsString(Playlists.NAME),
96                     c.getString(c.getColumnIndex(Playlists.NAME)));
97 
98             long realDateAdded = c.getLong(c.getColumnIndex(Playlists.DATE_ADDED));
99             assertTrue(realDateAdded >= dateAdded);
100             assertEquals(dateModified, c.getLong(c.getColumnIndex(Playlists.DATE_MODIFIED)));
101             assertTrue(c.getLong(c.getColumnIndex(Playlists._ID)) > 0);
102             c.close();
103         } finally {
104             assertEquals(1, mContentResolver.delete(uri, null, null));
105         }
106     }
107 
108     /**
109      * Verify that creating playlists using only {@link Playlists#NAME} defined
110      * will flow into the {@link MediaColumns#DISPLAY_NAME}, both during initial
111      * insert and subsequent updates.
112      */
113     @Test
testName()114     public void testName() throws Exception {
115         final String name1 = "Playlist " + System.nanoTime();
116         final String name2 = "Playlist " + System.nanoTime();
117         assertNotEquals(name1, name2);
118 
119         final ContentValues values = new ContentValues();
120         values.clear();
121         values.put(Playlists.NAME, name1);
122         final Uri playlist = mContentResolver
123                 .insert(MediaStore.Audio.Playlists.getContentUri(mVolumeName), values);
124         MediaStore.waitForIdle(mContentResolver);
125         try (Cursor c = mContentResolver.query(playlist,
126                 new String[] { Playlists.NAME, MediaColumns.DISPLAY_NAME }, null, null)) {
127             assertTrue(c.moveToFirst());
128             assertTrue(c.getString(0).startsWith(name1));
129             assertTrue(c.getString(1).startsWith(name1));
130         }
131 
132         values.clear();
133         values.put(Playlists.NAME, name2);
134         mContentResolver.update(playlist, values, null);
135         MediaStore.waitForIdle(mContentResolver);
136         try (Cursor c = mContentResolver.query(playlist,
137                 new String[] { Playlists.NAME, MediaColumns.DISPLAY_NAME }, null, null)) {
138             assertTrue(c.moveToFirst());
139             assertTrue(c.getString(0).startsWith(name2));
140             assertTrue(c.getString(1).startsWith(name2));
141         }
142     }
143 }
144