Home | History | Annotate | Download | only in externalstorageapp
      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 com.android.cts.externalstorageapp;
     18 
     19 import android.content.Context;
     20 import android.os.Environment;
     21 import android.test.AndroidTestCase;
     22 import android.util.Log;
     23 
     24 import java.io.DataInputStream;
     25 import java.io.DataOutputStream;
     26 import java.io.File;
     27 import java.io.FileInputStream;
     28 import java.io.FileOutputStream;
     29 import java.io.IOException;
     30 import java.util.ArrayList;
     31 import java.util.Collections;
     32 import java.util.List;
     33 
     34 /**
     35  * Tests common functionality that should be supported regardless of external
     36  * storage status.
     37  */
     38 public class CommonExternalStorageTest extends AndroidTestCase {
     39     public static final String TAG = "CommonExternalStorageTest";
     40 
     41     public static final String PACKAGE_NONE = "com.android.cts.externalstorageapp";
     42     public static final String PACKAGE_READ = "com.android.cts.readexternalstorageapp";
     43     public static final String PACKAGE_WRITE = "com.android.cts.writeexternalstorageapp";
     44 
     45     /**
     46      * Primary storage must always be mounted.
     47      */
     48     public void testExternalStorageMounted() {
     49         assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
     50     }
     51 
     52     /**
     53      * Verify that single path is always first item in multiple.
     54      */
     55     public void testMultipleCacheDirs() throws Exception {
     56         final File single = getContext().getExternalCacheDir();
     57         assertNotNull("Primary storage must always be available", single);
     58         final File firstMultiple = getContext().getExternalCacheDirs()[0];
     59         assertEquals(single, firstMultiple);
     60     }
     61 
     62     /**
     63      * Verify that single path is always first item in multiple.
     64      */
     65     public void testMultipleFilesDirs() throws Exception {
     66         final File single = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
     67         assertNotNull("Primary storage must always be available", single);
     68         final File firstMultiple = getContext()
     69                 .getExternalFilesDirs(Environment.DIRECTORY_PICTURES)[0];
     70         assertEquals(single, firstMultiple);
     71     }
     72 
     73     /**
     74      * Verify that single path is always first item in multiple.
     75      */
     76     public void testMultipleObbDirs() throws Exception {
     77         final File single = getContext().getObbDir();
     78         assertNotNull("Primary storage must always be available", single);
     79         final File firstMultiple = getContext().getObbDirs()[0];
     80         assertEquals(single, firstMultiple);
     81     }
     82 
     83     /**
     84      * Verify we can write to our own package dirs.
     85      */
     86     public void testAllPackageDirsWritable() throws Exception {
     87         final List<File> paths = getAllPackageSpecificPaths(getContext());
     88         for (File path : paths) {
     89             assertNotNull("Valid media must be inserted during CTS", path);
     90             assertEquals("Valid media must be inserted during CTS", Environment.MEDIA_MOUNTED,
     91                     Environment.getStorageState(path));
     92 
     93             assertDirReadWriteAccess(path);
     94 
     95             final File directChild = new File(path, "directChild");
     96             final File subdir = new File(path, "subdir");
     97             final File subdirChild = new File(path, "subdirChild");
     98 
     99             writeInt(directChild, 32);
    100             subdir.mkdirs();
    101             assertDirReadWriteAccess(subdir);
    102             writeInt(subdirChild, 64);
    103 
    104             assertEquals(32, readInt(directChild));
    105             assertEquals(64, readInt(subdirChild));
    106         }
    107 
    108         for (File path : paths) {
    109             deleteContents(path);
    110         }
    111     }
    112 
    113     /**
    114      * Return a set of several package-specific external storage paths.
    115      */
    116     public static List<File> getAllPackageSpecificPaths(Context context) {
    117         final List<File> paths = new ArrayList<File>();
    118         Collections.addAll(paths, context.getExternalCacheDirs());
    119         Collections.addAll(paths, context.getExternalFilesDirs(null));
    120         Collections.addAll(paths, context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES));
    121         Collections.addAll(paths, context.getObbDirs());
    122         return paths;
    123     }
    124 
    125     public static List<File> getAllPackageSpecificPathsExceptObb(Context context) {
    126         final List<File> paths = new ArrayList<File>();
    127         Collections.addAll(paths, context.getExternalCacheDirs());
    128         Collections.addAll(paths, context.getExternalFilesDirs(null));
    129         Collections.addAll(paths, context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES));
    130         return paths;
    131     }
    132 
    133     public static List<File> getPrimaryPackageSpecificPaths(Context context) {
    134         final List<File> paths = new ArrayList<File>();
    135         Collections.addAll(paths, context.getExternalCacheDir());
    136         Collections.addAll(paths, context.getExternalFilesDir(null));
    137         Collections.addAll(paths, context.getExternalFilesDir(Environment.DIRECTORY_PICTURES));
    138         Collections.addAll(paths, context.getObbDir());
    139         return paths;
    140     }
    141 
    142     public static List<File> getSecondaryPackageSpecificPaths(Context context) {
    143         final List<File> paths = new ArrayList<File>();
    144         Collections.addAll(paths, dropFirst(context.getExternalCacheDirs()));
    145         Collections.addAll(paths, dropFirst(context.getExternalFilesDirs(null)));
    146         Collections.addAll(
    147                 paths, dropFirst(context.getExternalFilesDirs(Environment.DIRECTORY_PICTURES)));
    148         Collections.addAll(paths, dropFirst(context.getObbDirs()));
    149         return paths;
    150     }
    151 
    152     private static File[] dropFirst(File[] before) {
    153         final File[] after = new File[before.length - 1];
    154         System.arraycopy(before, 1, after, 0, after.length);
    155         return after;
    156     }
    157 
    158     public static File buildGiftForPackage(Context context, String packageName) {
    159         final File myCache = context.getExternalCacheDir();
    160         return new File(myCache.getAbsolutePath().replace(context.getPackageName(), packageName),
    161                 packageName + ".gift");
    162     }
    163 
    164     public static File buildProbeFile(File dir) {
    165         return new File(dir, ".probe_" + System.nanoTime());
    166     }
    167 
    168     public static void assertDirReadOnlyAccess(File path) {
    169         Log.d(TAG, "Asserting read-only access to " + path);
    170 
    171         assertTrue("exists", path.exists());
    172         assertTrue("read", path.canRead());
    173         assertTrue("execute", path.canExecute());
    174         assertNotNull("list", path.list());
    175 
    176         try {
    177             final File probe = buildProbeFile(path);
    178             probe.createNewFile();
    179             probe.delete();
    180             fail("able to create probe!");
    181         } catch (IOException e) {
    182             // expected
    183         }
    184     }
    185 
    186     public static void assertDirReadWriteAccess(File path) {
    187         Log.d(TAG, "Asserting read/write access to " + path);
    188 
    189         assertTrue("exists", path.exists());
    190         assertTrue("read", path.canRead());
    191         assertTrue("execute", path.canExecute());
    192         assertNotNull("list", path.list());
    193 
    194         try {
    195             final File probe = buildProbeFile(path);
    196             probe.createNewFile();
    197             probe.delete();
    198         } catch (IOException e) {
    199             fail("failed to create probe!");
    200         }
    201     }
    202 
    203     public static void assertDirNoAccess(File path) {
    204         Log.d(TAG, "Asserting no access to " + path);
    205 
    206         assertFalse("read", path.canRead());
    207         assertNull("list", path.list());
    208 
    209         try {
    210             final File probe = buildProbeFile(path);
    211             probe.createNewFile();
    212             probe.delete();
    213             fail("able to create probe!");
    214         } catch (IOException e) {
    215             // expected
    216         }
    217     }
    218 
    219     public static void assertDirNoWriteAccess(File path) {
    220         Log.d(TAG, "Asserting no write access to " + path);
    221 
    222         try {
    223             final File probe = buildProbeFile(path);
    224             probe.createNewFile();
    225             probe.delete();
    226             fail("able to create probe!");
    227         } catch (IOException e) {
    228             // expected
    229         }
    230     }
    231 
    232     public static void assertFileReadOnlyAccess(File path) {
    233         try {
    234             new FileInputStream(path).close();
    235         } catch (IOException e) {
    236             fail("failed to read!");
    237         }
    238 
    239         try {
    240             new FileOutputStream(path, true).close();
    241             fail("able to write!");
    242         } catch (IOException e) {
    243             // expected
    244         }
    245     }
    246 
    247     public static void assertFileReadWriteAccess(File path) {
    248         try {
    249             new FileInputStream(path).close();
    250         } catch (IOException e) {
    251             fail("failed to read!");
    252         }
    253 
    254         try {
    255             new FileOutputStream(path, true).close();
    256         } catch (IOException e) {
    257             fail("failed to write!");
    258         }
    259     }
    260 
    261     public static void assertFileNoAccess(File path) {
    262         try {
    263             new FileInputStream(path).close();
    264             fail("able to read!");
    265         } catch (IOException e) {
    266             // expected
    267         }
    268 
    269         try {
    270             new FileOutputStream(path, true).close();
    271             fail("able to write!");
    272         } catch (IOException e) {
    273             // expected
    274         }
    275     }
    276 
    277     private static boolean isWhiteList(File file) {
    278         final String[] whiteLists = {
    279                 "autorun.inf", ".android_secure", "android_secure"
    280         };
    281         if (file.getParentFile().getAbsolutePath().equals(
    282                 Environment.getExternalStorageDirectory().getAbsolutePath())) {
    283             for (String whiteList : whiteLists) {
    284                 if (file.getName().equalsIgnoreCase(whiteList)) {
    285                     return true;
    286                 }
    287             }
    288         }
    289         return false;
    290     }
    291 
    292     private static File[] removeWhiteList(File[] files) {
    293         List<File> fileList = new ArrayList<File>();
    294         if (files == null) {
    295             return null;
    296         }
    297 
    298         for (File file : files) {
    299             if (!isWhiteList(file)) {
    300                 fileList.add(file);
    301             }
    302         }
    303         return fileList.toArray(new File[fileList.size()]);
    304     }
    305 
    306     public static void deleteContents(File dir) throws IOException {
    307         File[] files = dir.listFiles();
    308         files = removeWhiteList(files);
    309         if (files != null) {
    310             for (File file : files) {
    311                 if (file.isDirectory()) {
    312                     deleteContents(file);
    313                 }
    314                 assertTrue(file.delete());
    315             }
    316 
    317             File[] dirs = removeWhiteList(dir.listFiles());
    318             assertEquals(0, dirs.length);
    319         }
    320     }
    321 
    322     public static void writeInt(File file, int value) throws IOException {
    323         final DataOutputStream os = new DataOutputStream(new FileOutputStream(file));
    324         try {
    325             os.writeInt(value);
    326         } finally {
    327             os.close();
    328         }
    329     }
    330 
    331     public static int readInt(File file) throws IOException {
    332         final DataInputStream is = new DataInputStream(new FileInputStream(file));
    333         try {
    334             return is.readInt();
    335         } finally {
    336             is.close();
    337         }
    338     }
    339 }
    340