a6adc96909b1262c6abd5e1858ed448fa48257a9
[platform/framework/web/crosswalk.git] / src / content / public / android / javatests / src / org / chromium / content / browser / MediaResourceGetterTest.java
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.content.browser;
6
7 import android.annotation.SuppressLint;
8 import android.content.Context;
9 import android.content.pm.PackageManager;
10 import android.media.MediaMetadataRetriever;
11 import android.net.ConnectivityManager;
12 import android.test.InstrumentationTestCase;
13 import android.test.mock.MockContext;
14 import android.test.suitebuilder.annotation.SmallTest;
15 import android.util.SparseArray;
16
17 import org.chromium.content.browser.MediaResourceGetter.MediaMetadata;
18
19 import java.io.File;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23
24 /**
25  * Tests for MediaResourceGetter.
26  */
27 @SuppressLint("SdCardPath")
28 public class MediaResourceGetterTest extends InstrumentationTestCase {
29     private static final String TEST_HTTP_URL = "http://example.com";
30     private static final String TEST_USER_AGENT = // Anything, really
31             "Mozilla/5.0 (Windows NT 6.2; Win64; x64) AppleWebKit/537.36 " +
32             "(KHTML, like Gecko) Chrome/32.0.1667.0 Safari/537.36";
33     private static final String TEST_FILE_PATH = "/mnt/sdcard/test";
34     private static final String TEST_FILE_URL = "file://" + TEST_FILE_PATH;
35     private static final String TEST_COOKIES = "yum yum yum!";
36     private static final MediaMetadata sEmptyMetadata = new MediaMetadata(0, 0, 0, false);
37     private static final String sExternalStorageDirectory = "/test_external_storage";
38
39     private static final Map<String,String> sHeadersCookieOnly;
40     private static final Map<String,String> sHeadersCookieAndUA;
41     private static final Map<String,String> sHeadersUAOnly;
42     static {
43         Map<String,String> headers = new HashMap<String, String>();
44         headers.put("Cookie", TEST_COOKIES);
45         sHeadersCookieOnly = Collections.unmodifiableMap(headers);
46
47         headers = new HashMap<String, String>();
48         headers.put("User-Agent", TEST_USER_AGENT);
49         sHeadersUAOnly = Collections.unmodifiableMap(headers);
50
51         headers = new HashMap<String, String>();
52         headers.putAll(sHeadersCookieOnly);
53         headers.putAll(sHeadersUAOnly);
54         sHeadersCookieAndUA = Collections.unmodifiableMap(headers);
55     }
56
57     private static class FakeFile extends File {
58         final boolean mExists;
59
60         public FakeFile(String path, boolean exists) {
61             super(path);
62             mExists = exists;
63         }
64
65         @Override
66         public int hashCode() {
67             final int prime = 31;
68             int result = super.hashCode();
69             result = prime * result + (mExists ? 1231 : 1237);
70             return result;
71         }
72
73         @Override
74         public boolean equals(Object obj) {
75             if (this == obj)
76                 return true;
77             if (!super.equals(obj))
78                 return false;
79             if (getClass() != obj.getClass())
80                 return false;
81             FakeFile other = (FakeFile) obj;
82             if (mExists != other.mExists)
83                 return false;
84             return true;
85         }
86
87         @Override
88         public boolean exists() {
89             return mExists;
90         }
91     }
92
93     /**
94      * Helper class that fakes functionality we cannot perform without real
95      * media resources. The class being faked here has been architected
96      * carefully to allow most of the functionality to be tested. What remains
97      * here is overrides of trivial functionality.
98      */
99     private static class FakeMediaResourceGetter extends MediaResourceGetter {
100         // Read these back in tests to ensure proper values passed through
101         String mUri = null;
102         Map<String,String> mHeaders = null;
103         String mPath = null;
104         int mFd;
105         long mOffset;
106         long mLength;
107
108         // Write these before tests to configure functionality
109         SparseArray<String> mMetadata = null;
110         Integer mNetworkType = null;
111         boolean mThrowExceptionInConfigure = false;
112         boolean mThrowExceptionInExtract = false;
113         boolean mFileExists = false;
114
115         // Can't use a real MediaMetadataRetriever as we have no media
116         @Override
117         public void configure(int fd, long offset, long length) {
118             if (mThrowExceptionInConfigure) {
119                 throw new RuntimeException("test exception");
120             }
121             mFd = fd;
122             mOffset = offset;
123             mLength = length;
124         }
125
126         // Can't use a real MediaMetadataRetriever as we have no media
127         @Override
128         public void configure(String uri, Map<String, String> headers) {
129             if (mThrowExceptionInConfigure) {
130                 throw new RuntimeException("test exception");
131             }
132             mUri = uri;
133             mHeaders = headers;
134         }
135
136         // Can't use a real MediaMetadataRetriever as we have no media
137         @Override
138         public void configure(String path) {
139             if (mThrowExceptionInConfigure) {
140                 throw new RuntimeException("test exception");
141             }
142             mPath = path;
143         }
144
145         // Can't use a real MediaMetadataRetriever as we have no media
146         @Override
147         public String extractMetadata(int key) {
148             if (mThrowExceptionInExtract) {
149                 throw new RuntimeException("test exception");
150             }
151             if (mMetadata == null) {
152                 return null;
153             }
154             return mMetadata.get(key);
155         }
156
157         // Can't use a real NetworkInfo object because there is no way to
158         // mock the ConnectivityManager in Android.
159         @Override
160         Integer getNetworkType(Context context) {
161             return mNetworkType;
162         }
163
164         // Can't use Environment.getExternalStorageDirectory because it could
165         // be inconsistent depending upon the state of the real or emulated
166         // device upon which we are testing.
167         @Override
168         String getExternalStorageDirectory() {
169             return sExternalStorageDirectory;
170         }
171
172         // Can't use regular File because we need to control the return from
173         // File.exists() on arbitrary paths.
174         @Override
175         File uriToFile(String path) {
176             FakeFile result = new FakeFile(path, mFileExists);
177             return result;
178         }
179
180         /**
181          * Convenience method to bind a metadata value to a key.
182          * @param key the key
183          * @param value the value
184          */
185         void bind(int key, String value) {
186             if (mMetadata == null) {
187                 mMetadata = new SparseArray<String>();
188             }
189             mMetadata.put(key, value);
190         }
191
192     }
193
194     /**
195      * Helper class to control the result of permission checks.
196      */
197     private static class InternalMockContext extends MockContext {
198         boolean allowPermission = false;
199         @Override
200         public int checkCallingOrSelfPermission(String permission) {
201             assertEquals(android.Manifest.permission.ACCESS_NETWORK_STATE,
202                     permission);
203             return allowPermission ? PackageManager.PERMISSION_GRANTED :
204                 PackageManager.PERMISSION_DENIED;
205         }
206     }
207
208     // Our test objects.
209     private FakeMediaResourceGetter mFakeMRG;
210     private InternalMockContext mMockContext;
211
212     @Override
213     protected void setUp() throws Exception {
214         super.setUp();
215         mFakeMRG = new FakeMediaResourceGetter();
216         mMockContext = new InternalMockContext();
217     }
218
219     @SmallTest
220     public void testMediaMetadataEquals() {
221         assertEquals(sEmptyMetadata, sEmptyMetadata);
222         assertEquals(sEmptyMetadata, new MediaMetadata(0, 0, 0, false));
223         assertFalse(sEmptyMetadata.equals(null));
224         assertFalse(sEmptyMetadata.equals("test"));
225         assertFalse(sEmptyMetadata.equals(new MediaMetadata(1, 0, 0, false)));
226         assertFalse(sEmptyMetadata.equals(new MediaMetadata(0, 1, 0, false)));
227         assertFalse(sEmptyMetadata.equals(new MediaMetadata(0, 0, 1, false)));
228         assertFalse(sEmptyMetadata.equals(new MediaMetadata(0, 0, 0, true)));
229     }
230
231     @SmallTest
232     public void testMediaMetadataHashCode() {
233         assertEquals(sEmptyMetadata.hashCode(), sEmptyMetadata.hashCode());
234         assertEquals(sEmptyMetadata.hashCode(), new MediaMetadata(0, 0, 0, false).hashCode());
235         assertFalse(sEmptyMetadata.hashCode() == new MediaMetadata(1, 0, 0, false).hashCode());
236         assertFalse(sEmptyMetadata.hashCode() == new MediaMetadata(0, 1, 0, false).hashCode());
237         assertFalse(sEmptyMetadata.hashCode() == new MediaMetadata(0, 0, 1, false).hashCode());
238         assertFalse(sEmptyMetadata.hashCode() == new MediaMetadata(0, 0, 0, true).hashCode());
239     }
240
241     @SmallTest
242     public void testMediaMetadataGetters() {
243         MediaMetadata data = new MediaMetadata(1, 2, 3, true);
244         assertEquals(1, data.getDurationInMilliseconds());
245         assertEquals(2, data.getWidth());
246         assertEquals(3, data.getHeight());
247         assertTrue(data.isSuccess());
248
249         // Validate no overlap of test values with defaults
250         data = new MediaMetadata(4, 5, 6, false);
251         assertEquals(4, data.getDurationInMilliseconds());
252         assertEquals(5, data.getWidth());
253         assertEquals(6, data.getHeight());
254         assertFalse(data.isSuccess());
255     }
256
257     @SmallTest
258     public void testConfigure_Net_NoPermissions() {
259         mMockContext.allowPermission = false;
260         assertFalse(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
261                                        TEST_COOKIES, TEST_USER_AGENT));
262     }
263
264     @SmallTest
265     public void testConfigure_Net_NoActiveNetwork() {
266         mMockContext.allowPermission = true;
267         mFakeMRG.mNetworkType = null;
268         assertFalse(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
269                                        TEST_COOKIES, TEST_USER_AGENT));
270     }
271
272     @SmallTest
273     public void testConfigure_Net_Disallowed_Mobile() {
274         mMockContext.allowPermission = true;
275         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_MOBILE;
276         assertFalse(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
277                                        TEST_COOKIES, TEST_USER_AGENT));
278     }
279
280     @SmallTest
281     public void testConfigure_Net_Disallowed_Wimax() {
282         mMockContext.allowPermission = true;
283         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_WIMAX;
284         assertFalse(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
285                                        TEST_COOKIES, TEST_USER_AGENT));
286     }
287
288     @SmallTest
289     public void testConfigure_Net_Allowed_Ethernet_Cookies_NoUA() {
290         mMockContext.allowPermission = true;
291         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_ETHERNET;
292         assertTrue(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
293                                       TEST_COOKIES, null));
294         assertEquals(TEST_HTTP_URL, mFakeMRG.mUri);
295         assertEquals(sHeadersCookieOnly, mFakeMRG.mHeaders);
296         assertNull(mFakeMRG.mPath);
297     }
298
299     @SmallTest
300     public void testConfigure_Net_Allowed_Wifi_Cookies_NoUA() {
301         mMockContext.allowPermission = true;
302         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_WIFI;
303         assertTrue(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
304                                       TEST_COOKIES, null));
305         assertEquals(TEST_HTTP_URL, mFakeMRG.mUri);
306         assertEquals(sHeadersCookieOnly, mFakeMRG.mHeaders);
307         assertNull(mFakeMRG.mPath);
308     }
309
310     @SmallTest
311     public void testConfigure_Net_Allowed_Ethernet_NoCookies_NoUA() {
312         mMockContext.allowPermission = true;
313         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_ETHERNET;
314         assertTrue(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
315                                       "", null));
316         assertEquals(TEST_HTTP_URL, mFakeMRG.mUri);
317         assertEquals(Collections.emptyMap(), mFakeMRG.mHeaders);
318         assertNull(mFakeMRG.mPath);
319     }
320
321     @SmallTest
322     public void testConfigure_Net_Allowed_Ethernet_Cookies_WithUA() {
323         mMockContext.allowPermission = true;
324         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_ETHERNET;
325         assertTrue(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
326                                       TEST_COOKIES, TEST_USER_AGENT));
327         assertEquals(TEST_HTTP_URL, mFakeMRG.mUri);
328         assertEquals(sHeadersCookieAndUA, mFakeMRG.mHeaders);
329         assertNull(mFakeMRG.mPath);
330     }
331
332     @SmallTest
333     public void testConfigure_Net_Allowed_Ethernet_NoCookies_WithUA() {
334         mMockContext.allowPermission = true;
335         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_ETHERNET;
336         assertTrue(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
337                                       "", TEST_USER_AGENT));
338         assertEquals(TEST_HTTP_URL, mFakeMRG.mUri);
339         assertEquals(sHeadersUAOnly, mFakeMRG.mHeaders);
340         assertNull(mFakeMRG.mPath);
341     }
342
343     @SmallTest
344     public void testConfigure_Net_Allowed_Ethernet_Exception() {
345         mMockContext.allowPermission = true;
346         mFakeMRG.mThrowExceptionInConfigure = true;
347         mFakeMRG.mNetworkType = ConnectivityManager.TYPE_ETHERNET;
348         assertFalse(mFakeMRG.configure(mMockContext, TEST_HTTP_URL,
349                                        "", TEST_USER_AGENT));
350         assertNull(mFakeMRG.mUri);
351         assertNull(mFakeMRG.mHeaders);
352     }
353
354     @SmallTest
355     public void testConfigure_Net_Allowed_LocalHost_WithNoNetwork() {
356         String[] localHostUrls = {
357             "http://LocalHost",
358             "https://127.0.0.1/",
359             "http://[::1]:8888/",
360         };
361         mMockContext.allowPermission = true;
362         mFakeMRG.mNetworkType = null;
363         for (String localHostUrl : localHostUrls) {
364             assertTrue(mFakeMRG.configure(mMockContext, localHostUrl,
365                                           TEST_COOKIES, TEST_USER_AGENT));
366             assertEquals(localHostUrl, mFakeMRG.mUri);
367             assertEquals(sHeadersCookieAndUA, mFakeMRG.mHeaders);
368             assertNull(mFakeMRG.mPath);
369         }
370     }
371
372     @SmallTest
373     public void testConfigure_File_Allowed_MntSdcard() {
374         final String path = "/mnt/sdcard/test";
375         final String url = "file://" + path;
376         mFakeMRG.mFileExists = true;
377         assertTrue(mFakeMRG.configure(mMockContext, url, "", null));
378         assertEquals(path, mFakeMRG.mPath);
379         assertNull(mFakeMRG.mUri);
380         assertNull(mFakeMRG.mHeaders);
381     }
382
383     @SmallTest
384     public void testConfigure_File_Allowed_Sdcard() {
385         final String path = "/sdcard/test";
386         final String url = "file://" + path;
387         mFakeMRG.mFileExists = true;
388         assertTrue(mFakeMRG.configure(mMockContext, url, "", null));
389         assertEquals(path, mFakeMRG.mPath);
390         assertNull(mFakeMRG.mUri);
391         assertNull(mFakeMRG.mHeaders);
392     }
393
394     @SmallTest
395     public void testConfigure_File_Allowed_Sdcard_DoesntExist() {
396         final String path = "/sdcard/test";
397         final String url = "file://" + path;
398         mFakeMRG.mFileExists = false;
399         assertFalse(mFakeMRG.configure(mMockContext, url, "", null));
400         assertNull(mFakeMRG.mPath);
401     }
402
403     @SmallTest
404     public void testConfigure_File_Allowed_ExternalStorage() {
405         final String path = sExternalStorageDirectory + "/test";
406         final String url = "file://" + path;
407         mFakeMRG.mFileExists = true;
408         assertTrue(mFakeMRG.configure(mMockContext, url, "", null));
409         assertEquals(path, mFakeMRG.mPath);
410         assertNull(mFakeMRG.mUri);
411         assertNull(mFakeMRG.mHeaders);
412     }
413
414     @SmallTest
415     public void testConfigure_File_Disallowed_Innocent() {
416         final String path = "/malicious/path";
417         final String url = "file://" + path;
418         mFakeMRG.mFileExists = true;
419         assertFalse(mFakeMRG.configure(mMockContext, url, "", null));
420         assertNull(mFakeMRG.mPath);
421     }
422
423     @SmallTest
424     public void testConfigure_File_Disallowed_Malicious() {
425         final String path = "/mnt/sdcard/../../data";
426         final String url = "file://" + path;
427         mFakeMRG.mFileExists = true;
428         assertFalse(mFakeMRG.configure(mMockContext, url, "", null));
429         assertNull(mFakeMRG.mPath);
430     }
431
432     @SmallTest
433     public void testConfigure_File_Allowed_Exception() {
434         final String path = "/mnt/sdcard/test";
435         final String url = "file://" + path;
436         mFakeMRG.mFileExists = true;
437         mFakeMRG.mThrowExceptionInConfigure = true;
438         assertFalse(mFakeMRG.configure(mMockContext, url, "", null));
439         assertNull(mFakeMRG.mPath);
440     }
441
442     @SmallTest
443     public void testExtract_NoMetadata() {
444         mFakeMRG.mFileExists = true;
445         assertEquals(sEmptyMetadata, mFakeMRG.extract(
446                 mMockContext, TEST_FILE_URL, null, null));
447         assertEquals("configured successfully when we shouldn't have",
448                      TEST_FILE_PATH, mFakeMRG.mPath); // tricky
449     }
450
451     @SmallTest
452     public void testExtract_WithMetadata_ValidDuration() {
453         mFakeMRG.mFileExists = true;
454         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
455         final MediaMetadata expected = new MediaMetadata(1, 0, 0, true);
456         assertEquals(expected, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
457     }
458
459     @SmallTest
460     public void testExtract_WithMetadata_InvalidDuration() {
461         mFakeMRG.mFileExists = true;
462         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "i am not an integer");
463         assertEquals(sEmptyMetadata, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
464     }
465
466     @SmallTest
467     public void testExtract_WithMetadata_ValidDuration_HasVideo_NoWidth_NoHeight() {
468         mFakeMRG.mFileExists = true;
469         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
470         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes");
471         assertEquals(sEmptyMetadata, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
472     }
473
474     @SmallTest
475     public void testExtract_WithMetadata_ValidDuration_HasVideo_ValidWidth_NoHeight() {
476         mFakeMRG.mFileExists = true;
477         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
478         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes");
479         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, "1");
480         assertEquals(sEmptyMetadata, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
481     }
482
483     @SmallTest
484     public void testExtract_WithMetadata_ValidDuration_HasVideo_InvalidWidth_NoHeight() {
485         mFakeMRG.mFileExists = true;
486         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
487         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes");
488         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, "i am not an integer");
489         assertEquals(sEmptyMetadata, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
490     }
491
492     @SmallTest
493     public void testExtract_WithMetadata_ValidDuration_HasVideo_ValidWidth_ValidHeight() {
494         mFakeMRG.mFileExists = true;
495         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
496         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes");
497         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, "2");
498         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, "3");
499         final MediaMetadata expected = new MediaMetadata(1, 2, 3, true);
500         assertEquals(expected, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
501     }
502
503     @SmallTest
504     public void testExtract_WithMetadata_ValidDuration_HasVideo_ValidWidth_InvalidHeight() {
505         mFakeMRG.mFileExists = true;
506         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
507         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes");
508         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, "1");
509         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, "i am not an integer");
510         assertEquals(sEmptyMetadata, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
511     }
512
513     @SmallTest
514     public void testExtract_WithMetadata_ValidDuration_ExceptionInExtract() {
515         mFakeMRG.mFileExists = true;
516         mFakeMRG.mThrowExceptionInExtract = true;
517         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
518         assertEquals(sEmptyMetadata, mFakeMRG.extract(mMockContext, TEST_FILE_URL, null, null));
519     }
520
521     @SmallTest
522     public void testExtractFromFileDescriptor_ValidMetadata() {
523         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_DURATION, "1");
524         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_HAS_VIDEO, "yes");
525         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH, "2");
526         mFakeMRG.bind(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT, "3");
527         final MediaMetadata expected = new MediaMetadata(1, 2, 3, true);
528         int fd = 1234;
529         long offset = 1000;
530         long length = 9000;
531         assertEquals(expected, mFakeMRG.extract(fd, offset, length));
532         assertEquals(fd, mFakeMRG.mFd);
533         assertEquals(offset, mFakeMRG.mOffset);
534         assertEquals(length, mFakeMRG.mLength);
535     }
536
537     @SmallTest
538     public void testAndroidDeviceOk_BadModel_BadVersion() {
539         assertFalse(MediaResourceGetter.androidDeviceOk(
540                 "GT-I9100", android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1));
541     }
542
543     @SmallTest
544     public void testAndroidDeviceOk_BadModel_GoodVersion() {
545         assertTrue(MediaResourceGetter.androidDeviceOk(
546                 "GT-I9100", android.os.Build.VERSION_CODES.JELLY_BEAN));
547     }
548
549     @SmallTest
550     public void testAndroidDeviceOk_GoodModel_AnyVersion() {
551         assertTrue(MediaResourceGetter.androidDeviceOk(
552                 "Happy Device", android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH));
553     }
554 }