• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 
20 import android.content.ContentResolver;
21 import android.content.ContentValues;
22 import android.database.Cursor;
23 import android.net.Uri;
24 import android.provider.MediaStore;
25 import android.provider.MediaStore.Audio.Media;
26 import android.provider.MediaStore.Audio.Playlists;
27 import android.provider.MediaStore.Audio.Playlists.Members;
28 import android.provider.cts.MediaStoreAudioTestHelper.Audio1;
29 import android.provider.cts.MediaStoreAudioTestHelper.Audio2;
30 import android.provider.cts.MediaStoreAudioTestHelper.Audio3;
31 import android.provider.cts.MediaStoreAudioTestHelper.Audio4;
32 import android.provider.cts.MediaStoreAudioTestHelper.Audio5;
33 import android.provider.cts.MediaStoreAudioTestHelper.MockAudioMediaInfo;
34 import android.test.InstrumentationTestCase;
35 
36 import java.util.regex.Pattern;
37 
38 public class MediaStore_Audio_Playlists_MembersTest extends InstrumentationTestCase {
39     private String[] mAudioProjection = {
40             Members._ID,
41             Members.ALBUM,
42             Members.ALBUM_ID,
43             Members.ALBUM_KEY,
44             Members.ARTIST,
45             Members.ARTIST_ID,
46             Members.ARTIST_KEY,
47             Members.COMPOSER,
48             Members.DATA,
49             Members.DATE_ADDED,
50             Members.DATE_MODIFIED,
51             Members.DISPLAY_NAME,
52             Members.DURATION,
53             Members.IS_ALARM,
54             Members.IS_DRM,
55             Members.IS_MUSIC,
56             Members.IS_NOTIFICATION,
57             Members.IS_RINGTONE,
58             Members.MIME_TYPE,
59             Members.SIZE,
60             Members.TITLE,
61             Members.TITLE_KEY,
62             Members.TRACK,
63             Members.YEAR,
64     };
65 
66     private String[] mMembersProjection = {
67             Members._ID,
68             Members.AUDIO_ID,
69             Members.PLAYLIST_ID,
70             Members.PLAY_ORDER,
71             Members.ALBUM,
72             Members.ALBUM_ID,
73             Members.ALBUM_KEY,
74             Members.ARTIST,
75             Members.ARTIST_ID,
76             Members.ARTIST_KEY,
77             Members.COMPOSER,
78             Members.DATA,
79             Members.DATE_ADDED,
80             Members.DATE_MODIFIED,
81             Members.DISPLAY_NAME,
82             Members.DURATION,
83             Members.IS_ALARM,
84             Members.IS_DRM,
85             Members.IS_MUSIC,
86             Members.IS_NOTIFICATION,
87             Members.IS_RINGTONE,
88             Members.MIME_TYPE,
89             Members.SIZE,
90             Members.TITLE,
91             Members.TITLE_KEY,
92             Members.TRACK,
93             Members.YEAR,
94     };
95 
96     private ContentResolver mContentResolver;
97 
98     private long mIdOfAudio1;
99     private long mIdOfAudio2;
100     private long mIdOfAudio3;
101     private long mIdOfAudio4;
102     private long mIdOfAudio5;
103 
insertAudioItem(MockAudioMediaInfo which)104     private long insertAudioItem(MockAudioMediaInfo which) {
105         Uri uri = which.insertToExternal(mContentResolver);
106         Cursor c = mContentResolver.query(uri, null, null, null, null);
107         c.moveToFirst();
108         long id = c.getLong(c.getColumnIndex(Media._ID));
109         c.close();
110         return id;
111     }
112 
113     @Override
setUp()114     protected void setUp() throws Exception {
115         super.setUp();
116 
117         mContentResolver = getInstrumentation().getContext().getContentResolver();
118         mIdOfAudio1 = insertAudioItem(Audio1.getInstance());
119         mIdOfAudio2 = insertAudioItem(Audio2.getInstance());
120         mIdOfAudio3 = insertAudioItem(Audio3.getInstance());
121         mIdOfAudio4 = insertAudioItem(Audio4.getInstance());
122         mIdOfAudio5 = insertAudioItem(Audio5.getInstance());
123     }
124 
125     @Override
tearDown()126     protected void tearDown() throws Exception {
127         mContentResolver.delete(Media.EXTERNAL_CONTENT_URI, Media._ID + "=" + mIdOfAudio1, null);
128         mContentResolver.delete(Media.EXTERNAL_CONTENT_URI, Media._ID + "=" + mIdOfAudio2, null);
129         mContentResolver.delete(Media.EXTERNAL_CONTENT_URI, Media._ID + "=" + mIdOfAudio3, null);
130         mContentResolver.delete(Media.EXTERNAL_CONTENT_URI, Media._ID + "=" + mIdOfAudio4, null);
131         mContentResolver.delete(Media.EXTERNAL_CONTENT_URI, Media._ID + "=" + mIdOfAudio5, null);
132         super.tearDown();
133     }
134 
testGetContentUri()135     public void testGetContentUri() {
136         assertEquals("content://media/external/audio/playlists/1337/members",
137                 Members.getContentUri("external", 1337).toString());
138         assertEquals("content://media/internal/audio/playlists/3007/members",
139                 Members.getContentUri("internal", 3007).toString());
140     }
141 
insertPlaylistItem(Uri playlistMembersUri, long itemid, int order)142     private Uri insertPlaylistItem(Uri playlistMembersUri, long itemid, int order) {
143         ContentValues values = new ContentValues();
144         values.put(Members.AUDIO_ID, itemid);
145         values.put(Members.PLAY_ORDER, order);
146         return mContentResolver.insert(playlistMembersUri, values);
147     }
148 
149     /**
150      * check that the specified playlist contains the given members in the given order
151      */
verifyPlaylist(Uri playlistMembersUri, long [] members, int [] ordering)152     private void verifyPlaylist(Uri playlistMembersUri, long [] members, int [] ordering) {
153         Cursor c = mContentResolver.query(playlistMembersUri,
154                 new String[] { Members.AUDIO_ID, Members.PLAY_ORDER },
155                 null, null, // selection, selection args
156                 Members.PLAY_ORDER);
157         assertFalse("neither members nor ordering specified",
158                 members == null && ordering == null);
159         if (members != null) {
160             assertEquals("members length doesn't match cursor length",
161                     members.length, c.getCount());
162             if (ordering != null) {
163                 assertEquals("members and ordering must have same length",
164                         members.length, ordering.length);
165             }
166         }
167         if (ordering != null) {
168             assertEquals("ordering length doesn't match cursor length",
169                     ordering.length, c.getCount());
170         }
171         while (c.moveToNext()) {
172             int pos = c.getPosition();
173             if (members != null) {
174                 assertEquals("mismatched member at position " + pos,
175                         members[pos], c.getInt(c.getColumnIndex(Members.AUDIO_ID)));
176             }
177             if (ordering != null) {
178                 assertEquals("mismatched ordering at position " + pos,
179                         ordering[pos], c.getInt(c.getColumnIndex(Members.PLAY_ORDER)));
180             }
181         }
182         c.close();
183     }
184 
testStoreAudioPlaylistsMembersExternal()185     public void testStoreAudioPlaylistsMembersExternal() {
186         ContentValues values = new ContentValues();
187         values.put(Playlists.NAME, "My favourites");
188         values.put(Playlists.DATA, "");
189         long dateAdded = System.currentTimeMillis();
190         values.put(Playlists.DATE_ADDED, dateAdded);
191         long dateModified = System.currentTimeMillis();
192         values.put(Playlists.DATE_MODIFIED, dateModified);
193         // insert
194         Uri uri = mContentResolver.insert(Playlists.EXTERNAL_CONTENT_URI, values);
195         assertNotNull(uri);
196         Cursor c = mContentResolver.query(uri, null, null, null, null);
197         c.moveToFirst();
198         long playlistId = c.getLong(c.getColumnIndex(Playlists._ID));
199         long playlist2Id = -1; // used later
200 
201         // verify that the Uri has the correct format and playlist value
202         assertEquals(uri.toString(), "content://media/external/audio/playlists/" + playlistId);
203 
204         // insert audio as the member of the playlist
205         Uri membersUri = Members.getContentUri(MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME,
206                 playlistId);
207         Uri audioUri = insertPlaylistItem(membersUri, mIdOfAudio1, 1);
208 
209         assertNotNull(audioUri);
210         assertTrue(audioUri.toString().startsWith(membersUri.toString()));
211 
212         try {
213             // query the audio info
214             c = mContentResolver.query(audioUri, mAudioProjection, null, null, null);
215             assertEquals(1, c.getCount());
216             c.moveToFirst();
217             long memberId = c.getLong(c.getColumnIndex(Members._ID));
218             assertEquals(memberId, Long.parseLong(audioUri.getPathSegments().get(5)));
219             assertEquals(Audio1.EXTERNAL_DATA, c.getString(c.getColumnIndex(Members.DATA)));
220             assertTrue(c.getLong(c.getColumnIndex(Members.DATE_ADDED)) > 0);
221             assertEquals(Audio1.DATE_MODIFIED, c.getLong(c.getColumnIndex(Members.DATE_MODIFIED)));
222             assertEquals(Audio1.IS_DRM, c.getInt(c.getColumnIndex(Members.IS_DRM)));
223             assertEquals(Audio1.FILE_NAME, c.getString(c.getColumnIndex(Members.DISPLAY_NAME)));
224             assertEquals(Audio1.MIME_TYPE, c.getString(c.getColumnIndex(Members.MIME_TYPE)));
225             assertEquals(Audio1.SIZE, c.getInt(c.getColumnIndex(Members.SIZE)));
226             assertEquals(Audio1.TITLE, c.getString(c.getColumnIndex(Members.TITLE)));
227             assertEquals(Audio1.ALBUM, c.getString(c.getColumnIndex(Members.ALBUM)));
228             assertNotNull(c.getString(c.getColumnIndex(Members.ALBUM_KEY)));
229             assertTrue(c.getLong(c.getColumnIndex(Members.ALBUM_ID)) > 0);
230             assertEquals(Audio1.ARTIST, c.getString(c.getColumnIndex(Members.ARTIST)));
231             assertNotNull(c.getString(c.getColumnIndex(Members.ARTIST_KEY)));
232             assertTrue(c.getLong(c.getColumnIndex(Members.ARTIST_ID)) > 0);
233             assertEquals(Audio1.COMPOSER, c.getString(c.getColumnIndex(Members.COMPOSER)));
234             assertEquals(Audio1.DURATION, c.getLong(c.getColumnIndex(Members.DURATION)));
235             assertEquals(Audio1.IS_ALARM, c.getInt(c.getColumnIndex(Members.IS_ALARM)));
236             assertEquals(Audio1.IS_MUSIC, c.getInt(c.getColumnIndex(Members.IS_MUSIC)));
237             assertEquals(Audio1.IS_NOTIFICATION,
238                     c.getInt(c.getColumnIndex(Members.IS_NOTIFICATION)));
239             assertEquals(Audio1.IS_RINGTONE, c.getInt(c.getColumnIndex(Members.IS_RINGTONE)));
240             assertEquals(Audio1.TRACK, c.getInt(c.getColumnIndex(Members.TRACK)));
241             assertEquals(Audio1.YEAR, c.getInt(c.getColumnIndex(Members.YEAR)));
242             assertNotNull(c.getString(c.getColumnIndex(Members.TITLE_KEY)));
243             c.close();
244 
245             // query the play order of the audio
246             verifyPlaylist(membersUri, new long [] {mIdOfAudio1}, new int [] {1});
247 
248             // update the member
249             values.clear();
250             values.put(Members.PLAY_ORDER, 2);
251             values.put(Members.AUDIO_ID, mIdOfAudio2);
252             int result = mContentResolver.update(membersUri, values, Members.AUDIO_ID + "="
253                     + mIdOfAudio1, null);
254             assertEquals(1, result);
255 
256             // query all info
257             c = mContentResolver.query(membersUri, mMembersProjection, null, null,
258                     Members.DEFAULT_SORT_ORDER);
259             assertEquals(1, c.getCount());
260             c.moveToFirst();
261             assertEquals(2, c.getInt(c.getColumnIndex(Members.PLAY_ORDER)));
262             assertEquals(memberId, c.getLong(c.getColumnIndex(Members._ID)));
263             assertEquals(Audio2.EXTERNAL_DATA, c.getString(c.getColumnIndex(Members.DATA)));
264             assertTrue(c.getLong(c.getColumnIndex(Members.DATE_ADDED)) > 0);
265             assertEquals(Audio2.DATE_MODIFIED, c.getLong(c.getColumnIndex(Members.DATE_MODIFIED)));
266             assertEquals(Audio2.IS_DRM, c.getInt(c.getColumnIndex(Members.IS_DRM)));
267             assertEquals(Audio2.FILE_NAME, c.getString(c.getColumnIndex(Members.DISPLAY_NAME)));
268             assertEquals(Audio2.MIME_TYPE, c.getString(c.getColumnIndex(Members.MIME_TYPE)));
269             assertEquals(Audio2.SIZE, c.getInt(c.getColumnIndex(Members.SIZE)));
270             assertEquals(Audio2.TITLE, c.getString(c.getColumnIndex(Members.TITLE)));
271             assertEquals(Audio2.ALBUM, c.getString(c.getColumnIndex(Members.ALBUM)));
272             assertNotNull(c.getString(c.getColumnIndex(Members.ALBUM_KEY)));
273             assertTrue(c.getLong(c.getColumnIndex(Members.ALBUM_ID)) > 0);
274             assertEquals(Audio2.ARTIST, c.getString(c.getColumnIndex(Members.ARTIST)));
275             assertNotNull(c.getString(c.getColumnIndex(Members.ARTIST_KEY)));
276             assertTrue(c.getLong(c.getColumnIndex(Members.ARTIST_ID)) > 0);
277             assertEquals(Audio2.COMPOSER, c.getString(c.getColumnIndex(Members.COMPOSER)));
278             assertEquals(Audio2.DURATION, c.getLong(c.getColumnIndex(Members.DURATION)));
279             assertEquals(Audio2.IS_ALARM, c.getInt(c.getColumnIndex(Members.IS_ALARM)));
280             assertEquals(Audio2.IS_MUSIC, c.getInt(c.getColumnIndex(Members.IS_MUSIC)));
281             assertEquals(Audio2.IS_NOTIFICATION,
282                     c.getInt(c.getColumnIndex(Members.IS_NOTIFICATION)));
283             assertEquals(Audio2.IS_RINGTONE, c.getInt(c.getColumnIndex(Members.IS_RINGTONE)));
284             assertEquals(Audio2.TRACK, c.getInt(c.getColumnIndex(Members.TRACK)));
285             assertEquals(Audio2.YEAR, c.getInt(c.getColumnIndex(Members.YEAR)));
286             assertNotNull(c.getString(c.getColumnIndex(Members.TITLE_KEY)));
287             c.close();
288 
289             // update the member back to its original state
290             values.clear();
291             values.put(Members.PLAY_ORDER, 1);
292             values.put(Members.AUDIO_ID, mIdOfAudio1);
293             result = mContentResolver.update(membersUri, values, Members.AUDIO_ID + "="
294                     + mIdOfAudio2, null);
295             assertEquals(1, result);
296 
297             // insert another member into the playlist
298             Uri audioUri2 = insertPlaylistItem(membersUri, mIdOfAudio2, 2);
299             // the playlist should now have id1 at position 1 and id2 at position2, check that
300             verifyPlaylist(membersUri, new long [] {mIdOfAudio1, mIdOfAudio2}, new int [] {1,2});
301 
302             // swap the items around
303             assertTrue(MediaStore.Audio.Playlists.Members.moveItem(mContentResolver, playlistId, 1, 0));
304 
305             // check the new positions
306             verifyPlaylist(membersUri, new long [] {mIdOfAudio2, mIdOfAudio1}, new int [] {1,2});
307 
308             // swap the items around in the other direction
309             assertTrue(MediaStore.Audio.Playlists.Members.moveItem(mContentResolver, playlistId, 0, 1));
310 
311             // check the positions again
312             verifyPlaylist(membersUri, new long [] {mIdOfAudio1, mIdOfAudio2}, new int [] {1,2});
313 
314             // insert a third item into the playlist
315             Uri audioUri3 = insertPlaylistItem(membersUri, mIdOfAudio3, 3);
316             // the playlist should now have id1 at position 1, id2 at position2, and
317             // id3 at position3, check that
318             verifyPlaylist(membersUri,
319                     new long [] {mIdOfAudio1, mIdOfAudio2, mIdOfAudio3}, new int [] {1,2,3});
320 
321             // delete the middle item
322             mContentResolver.delete(Media.EXTERNAL_CONTENT_URI, Media._ID + "=" + mIdOfAudio2, null);
323 
324             // check the remaining items are still in the right order, and the play_order of the
325             // last item has been adjusted
326             verifyPlaylist(membersUri, new long [] {mIdOfAudio1, mIdOfAudio3}, new int [] {1,2});
327 
328             // try to swap the remaining two items
329             assertTrue(MediaStore.Audio.Playlists.Members.moveItem(mContentResolver, playlistId, 1, 0));
330 
331             // check that they're swapped
332             verifyPlaylist(membersUri, new long [] {mIdOfAudio3, mIdOfAudio1}, new int [] {1,2});
333 
334             // add 3 items, do some more moving and checking
335             mIdOfAudio2 = insertAudioItem(Audio2.getInstance());
336             insertPlaylistItem(membersUri, mIdOfAudio2, 3);
337             insertPlaylistItem(membersUri, mIdOfAudio4, 4);
338             insertPlaylistItem(membersUri, mIdOfAudio5, 5);
339             verifyPlaylist(membersUri,
340                     new long [] {mIdOfAudio3, mIdOfAudio1, mIdOfAudio2, mIdOfAudio4, mIdOfAudio5},
341                     new int[] {1, 2, 3, 4, 5});
342             assertTrue(MediaStore.Audio.Playlists.Members.moveItem(mContentResolver, playlistId, 1, 3));
343             verifyPlaylist(membersUri,
344                     new long [] {mIdOfAudio3, mIdOfAudio2, mIdOfAudio4, mIdOfAudio1, mIdOfAudio5},
345                     new int[] {1, 2, 3, 4, 5});
346             c = mContentResolver.query(membersUri, null, null, null, null);
347             c.close();
348 
349             // create another playlist
350             values.clear();
351             values.put(Playlists.NAME, "My favourites 2");
352             values.put(Playlists.DATA, "");
353             values.put(Playlists.DATE_ADDED, dateAdded);
354             values.put(Playlists.DATE_MODIFIED, dateModified);
355             // insert
356             uri = mContentResolver.insert(Playlists.EXTERNAL_CONTENT_URI, values);
357             assertNotNull(uri);
358             c = mContentResolver.query(uri, null, null, null, null);
359             c.moveToFirst();
360             playlist2Id = c.getLong(c.getColumnIndex(Playlists._ID));
361             c.close();
362 
363             // insert audio into 2nd playlist
364             Uri members2Uri = Members.getContentUri(MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME,
365                     playlist2Id);
366             Uri audio2Uri = insertPlaylistItem(members2Uri, mIdOfAudio1, 1);
367 
368             c = mContentResolver.query(membersUri, null, null, null, null);
369             int allcolscount = c.getCount();
370             c.close();
371             c = mContentResolver.query(membersUri,
372                     new String[] { Members.AUDIO_ID, Members.PLAY_ORDER }, null, null, null);
373             int somecolscount = c.getCount();
374             c.close();
375             assertEquals("Different count depending on columns", allcolscount, somecolscount);
376 
377             // check that the audio exists in both playlist
378             c = mContentResolver.query(membersUri, null, null, null, null);
379             assertEquals(5, c.getCount());
380             int cnt = 0;
381             int colidx = c.getColumnIndex(Members.AUDIO_ID);
382             assertTrue(colidx >= 0);
383             while(c.moveToNext()) {
384                 if (c.getLong(colidx) == mIdOfAudio1) {
385                     cnt++;
386                 }
387             }
388             assertEquals(1, cnt);
389             c.close();
390             c = mContentResolver.query(members2Uri, null, null, null, null);
391             assertEquals(1, c.getCount());
392             cnt = 0;
393             while(c.moveToNext()) {
394                 if (c.getLong(colidx) == mIdOfAudio1) {
395                     cnt++;
396                 }
397             }
398             assertEquals(1, cnt);
399             c.close();
400 
401             // delete the members
402             result = mContentResolver.delete(membersUri, null, null);
403             assertEquals(5, result);
404             result = mContentResolver.delete(members2Uri, null, null);
405             assertEquals(1, result);
406 
407             // insert again, then verify that deleting the audio entry cleans up its playlist member
408             // entry as well
409             membersUri = Members.getContentUri(MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME,
410                     playlistId);
411             audioUri = insertPlaylistItem(membersUri, mIdOfAudio1, 1);
412             assertNotNull(audioUri);
413             // Query members of the playlist
414             c = mContentResolver.query(membersUri,
415                     new String[] { Members.AUDIO_ID, Members.PLAYLIST_ID}, null, null, null);
416             colidx = c.getColumnIndex(Members.AUDIO_ID);
417             cnt = 0;
418             // The song should appear only once, for the playlist we used when inserting it
419             while(c.moveToNext()) {
420                 if (c.getLong(colidx) == mIdOfAudio1) {
421                     cnt++;
422                     assertEquals(playlistId, c.getLong(c.getColumnIndex(Members.PLAYLIST_ID)));
423                 }
424             }
425             assertEquals(1, cnt);
426             c.close();
427             mContentResolver.delete(Media.EXTERNAL_CONTENT_URI,
428                     Media._ID + "=" + mIdOfAudio1, null);
429             // Query members of the playlist
430             c = mContentResolver.query(membersUri,
431                     new String[] { Members.AUDIO_ID, Members.PLAYLIST_ID}, null, null, null);
432             colidx = c.getColumnIndex(Members.AUDIO_ID);
433             cnt = 0;
434             // The song should no longer appear in the playlist
435             while(c.moveToNext()) {
436                 if (c.getLong(colidx) == mIdOfAudio1) {
437                     cnt++;
438                 }
439             }
440             assertEquals(0, cnt);
441             c.close();
442 
443         } finally {
444             // delete the playlists
445             mContentResolver.delete(Playlists.EXTERNAL_CONTENT_URI,
446                     Playlists._ID + "=" + playlistId, null);
447             if (playlist2Id >= 0) {
448                 mContentResolver.delete(Playlists.EXTERNAL_CONTENT_URI,
449                         Playlists._ID + "=" + playlist2Id, null);
450             }
451         }
452     }
453 
testStoreAudioPlaylistsMembersInternal()454     public void testStoreAudioPlaylistsMembersInternal() {
455         ContentValues values = new ContentValues();
456         values.put(Playlists.NAME, "My favourites");
457         values.put(Playlists.DATA, "/data/data/com.android.cts.provider/files/my_favorites.pl");
458         long dateAdded = System.currentTimeMillis();
459         values.put(Playlists.DATE_ADDED, dateAdded);
460         long dateModified = System.currentTimeMillis();
461         values.put(Playlists.DATE_MODIFIED, dateModified);
462         // insert
463         Uri uri = mContentResolver.insert(Playlists.INTERNAL_CONTENT_URI, values);
464         assertNotNull(uri);
465 
466         try {
467             assertTrue(Pattern.matches("content://media/internal/audio/playlists/\\d+",
468                     uri.toString()));
469         } finally {
470             // delete the playlists
471             assertEquals(1, mContentResolver.delete(uri, null, null));
472         }
473     }
474 }
475