1 /* 2 * Copyright (C) 2012 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 import android.provider.cts.R; 20 21 import android.content.ContentResolver; 22 import android.content.ContentUris; 23 import android.content.ContentValues; 24 import android.database.Cursor; 25 import android.media.MediaCodecInfo; 26 import android.media.MediaCodecList; 27 import android.net.Uri; 28 import android.os.Environment; 29 import android.provider.MediaStore.Files; 30 import android.provider.MediaStore.Video.Media; 31 import android.provider.MediaStore.Video.Thumbnails; 32 import android.provider.MediaStore.Video.VideoColumns; 33 import android.test.AndroidTestCase; 34 import android.util.Log; 35 36 import com.android.compatibility.common.util.FileCopyHelper; 37 import com.android.compatibility.common.util.MediaUtils; 38 39 import java.io.File; 40 import java.io.IOException; 41 42 public class MediaStore_Video_ThumbnailsTest extends AndroidTestCase { 43 private static final String TAG = "MediaStore_Video_ThumbnailsTest"; 44 45 private ContentResolver mResolver; 46 47 private FileCopyHelper mFileHelper; 48 49 private boolean hasCodec() { 50 return MediaUtils.hasCodecForResourceAndDomain( 51 mContext, R.raw.testthumbvideo, "video/"); 52 } 53 54 @Override 55 protected void setUp() throws Exception { 56 super.setUp(); 57 mResolver = mContext.getContentResolver(); 58 mFileHelper = new FileCopyHelper(mContext); 59 } 60 61 @Override 62 protected void tearDown() throws Exception { 63 mFileHelper.clear(); 64 super.tearDown(); 65 } 66 67 public void testGetContentUri() { 68 Uri internalUri = Thumbnails.getContentUri(MediaStoreAudioTestHelper.INTERNAL_VOLUME_NAME); 69 Uri externalUri = Thumbnails.getContentUri(MediaStoreAudioTestHelper.EXTERNAL_VOLUME_NAME); 70 assertEquals(Thumbnails.INTERNAL_CONTENT_URI, internalUri); 71 assertEquals(Thumbnails.EXTERNAL_CONTENT_URI, externalUri); 72 } 73 74 public void testGetThumbnail() throws Exception { 75 // Insert a video into the provider. 76 Uri videoUri = insertVideo(); 77 long videoId = ContentUris.parseId(videoUri); 78 assertTrue(videoId != -1); 79 assertEquals(ContentUris.withAppendedId(Media.EXTERNAL_CONTENT_URI, videoId), 80 videoUri); 81 82 // Get the current thumbnail count for future comparison. 83 int count = getThumbnailCount(Thumbnails.EXTERNAL_CONTENT_URI); 84 85 // Don't run the test if the codec isn't supported. 86 if (!hasCodec()) { 87 // Calling getThumbnail should not generate a new thumbnail. 88 assertNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null)); 89 Log.i(TAG, "SKIPPING testGetThumbnail(): codec not supported"); 90 return; 91 } 92 93 // Calling getThumbnail should generate a new thumbnail. 94 assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MINI_KIND, null)); 95 assertNotNull(Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.MICRO_KIND, null)); 96 97 try { 98 Thumbnails.getThumbnail(mResolver, videoId, Thumbnails.FULL_SCREEN_KIND, null); 99 fail(); 100 } catch (IllegalArgumentException e) { 101 // Full screen thumbnails not supported by getThumbnail... 102 } 103 104 // Check that an additional thumbnails have been registered. 105 int count2 = getThumbnailCount(Thumbnails.EXTERNAL_CONTENT_URI); 106 assertTrue(count2 > count); 107 108 Cursor c = mResolver.query(Thumbnails.EXTERNAL_CONTENT_URI, 109 new String[] { Thumbnails._ID, Thumbnails.DATA, Thumbnails.VIDEO_ID }, 110 null, null, null); 111 112 if (c.moveToLast()) { 113 long vid = c.getLong(2); 114 assertEquals(videoId, vid); 115 String path = c.getString(1); 116 assertTrue("thumbnail file does not exist", new File(path).exists()); 117 long id = c.getLong(0); 118 mResolver.delete(ContentUris.withAppendedId(Thumbnails.EXTERNAL_CONTENT_URI, id), 119 null, null); 120 assertFalse("thumbnail file should no longer exist", new File(path).exists()); 121 } 122 c.close(); 123 124 assertEquals(1, mResolver.delete(videoUri, null, null)); 125 } 126 127 public void testThumbnailGenerationAndCleanup() throws Exception { 128 129 if (!hasCodec()) { 130 // we don't support video, so no need to run the test 131 Log.i(TAG, "SKIPPING testThumbnailGenerationAndCleanup(): codec not supported"); 132 return; 133 } 134 135 // insert a video 136 Uri uri = insertVideo(); 137 138 // request thumbnail creation 139 Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()), 140 Thumbnails.MINI_KIND, null /* options */); 141 142 // query the thumbnail 143 Cursor c = mResolver.query( 144 Thumbnails.EXTERNAL_CONTENT_URI, 145 new String [] {Thumbnails.DATA}, 146 "video_id=?", 147 new String[] {uri.getLastPathSegment()}, 148 null /* sort */ 149 ); 150 assertTrue("couldn't find thumbnail", c.moveToNext()); 151 String path = c.getString(0); 152 c.close(); 153 assertTrue("thumbnail does not exist", new File(path).exists()); 154 155 // delete the source video and check that the thumbnail is gone too 156 mResolver.delete(uri, null /* where clause */, null /* where args */); 157 assertFalse("thumbnail still exists after source file delete", new File(path).exists()); 158 159 // insert again 160 uri = insertVideo(); 161 162 // request thumbnail creation 163 Thumbnails.getThumbnail(mResolver, Long.valueOf(uri.getLastPathSegment()), 164 Thumbnails.MINI_KIND, null); 165 166 // query its thumbnail again 167 c = mResolver.query( 168 Thumbnails.EXTERNAL_CONTENT_URI, 169 new String [] {Thumbnails.DATA}, 170 "video_id=?", 171 new String[] {uri.getLastPathSegment()}, 172 null /* sort */ 173 ); 174 assertTrue("couldn't find thumbnail", c.moveToNext()); 175 path = c.getString(0); 176 c.close(); 177 assertTrue("thumbnail does not exist", new File(path).exists()); 178 179 // update the media type 180 ContentValues values = new ContentValues(); 181 values.put("media_type", 0); 182 assertEquals("unexpected number of updated rows", 183 1, mResolver.update(uri, values, null /* where */, null /* where args */)); 184 185 // video was marked as regular file in the database, which should have deleted its thumbnail 186 187 // query its thumbnail again 188 c = mResolver.query( 189 Thumbnails.EXTERNAL_CONTENT_URI, 190 new String [] {Thumbnails.DATA}, 191 "video_id=?", 192 new String[] {uri.getLastPathSegment()}, 193 null /* sort */ 194 ); 195 if (c != null) { 196 assertFalse("thumbnail entry exists for non-thumbnail file", c.moveToNext()); 197 c.close(); 198 } 199 assertFalse("thumbnail remains after source file type change", new File(path).exists()); 200 201 // check source no longer exists as video 202 c = mResolver.query(uri, 203 null /* projection */, null /* where */, null /* where args */, null /* sort */); 204 assertFalse("source entry should be gone", c.moveToNext()); 205 c.close(); 206 207 // check source still exists as file 208 Uri fileUri = ContentUris.withAppendedId( 209 Files.getContentUri("external"), 210 Long.valueOf(uri.getLastPathSegment())); 211 c = mResolver.query(fileUri, 212 null /* projection */, null /* where */, null /* where args */, null /* sort */); 213 assertTrue("source entry should be gone", c.moveToNext()); 214 String sourcePath = c.getString(c.getColumnIndex("_data")); 215 c.close(); 216 217 // clean up 218 mResolver.delete(uri, null /* where */, null /* where args */); 219 new File(sourcePath).delete(); 220 } 221 222 private Uri insertVideo() throws IOException { 223 File file = new File(Environment.getExternalStorageDirectory(), "testVideo.3gp"); 224 // clean up any potential left over entries from a previous aborted run 225 mResolver.delete(Media.EXTERNAL_CONTENT_URI, 226 "_data=?", new String[] { file.getAbsolutePath() }); 227 file.delete(); 228 mFileHelper.copyToExternalStorage(R.raw.testthumbvideo, file); 229 230 ContentValues values = new ContentValues(); 231 values.put(VideoColumns.DATA, file.getAbsolutePath()); 232 return mResolver.insert(Media.EXTERNAL_CONTENT_URI, values); 233 } 234 235 private int getThumbnailCount(Uri uri) { 236 Cursor cursor = mResolver.query(uri, null, null, null, null); 237 try { 238 return cursor.getCount(); 239 } finally { 240 cursor.close(); 241 } 242 } 243 } 244