Home | History | Annotate | Download | only in storage
      1 /*
      2  * Copyright (C) 2006 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.os.storage;
     18 
     19 import android.content.Context;
     20 import android.os.Environment;
     21 import android.os.IBinder;
     22 import android.os.RemoteException;
     23 import android.os.ServiceManager;
     24 import android.test.AndroidTestCase;
     25 import android.util.Log;
     26 
     27 import java.io.File;
     28 import java.io.FileOutputStream;
     29 
     30 public class AsecTests extends AndroidTestCase {
     31     private static final String SECURE_CONTAINER_PREFIX = "com.android.unittests.AsecTests.";
     32     private static final boolean localLOGV = true;
     33     public static final String TAG="AsecTests";
     34 
     35     private static final String FS_FAT = "fat";
     36     private static final String FS_EXT4 = "ext4";
     37 
     38     @Override
     39     protected void setUp() throws Exception {
     40         super.setUp();
     41         if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
     42         cleanupContainers();
     43     }
     44 
     45     @Override
     46     protected void tearDown() throws Exception {
     47         super.tearDown();
     48         if (localLOGV) Log.i(TAG, "Cleaning out old test containers");
     49         cleanupContainers();
     50     }
     51 
     52     private void cleanupContainers() throws RemoteException {
     53         IMountService ms = getMs();
     54         String[] containers = ms.getSecureContainerList();
     55 
     56         for (int i = 0; i < containers.length; i++) {
     57             if (containers[i].startsWith(SECURE_CONTAINER_PREFIX)) {
     58                 if (localLOGV)
     59                     Log.i(TAG, "Cleaning: " + containers[i]);
     60                 ms.destroySecureContainer(containers[i], true);
     61             }
     62         }
     63     }
     64 
     65     private boolean containerExists(String localId) throws RemoteException {
     66         IMountService ms = getMs();
     67         String[] containers = ms.getSecureContainerList();
     68         String fullId = SECURE_CONTAINER_PREFIX + localId;
     69 
     70         for (int i = 0; i < containers.length; i++) {
     71             if (containers[i].equals(fullId)) {
     72                 return true;
     73             }
     74         }
     75         return false;
     76     }
     77 
     78     private int createContainer(String localId, int size, String key, String filesystem,
     79             boolean isExternal) throws Exception {
     80         assertTrue("Media should be mounted", isMediaMounted());
     81         String fullId = SECURE_CONTAINER_PREFIX + localId;
     82 
     83         IMountService ms = getMs();
     84         return ms.createSecureContainer(fullId, size, filesystem, key, android.os.Process.myUid(),
     85                 isExternal);
     86     }
     87 
     88     private int mountContainer(String localId, String key) throws Exception {
     89         assertTrue("Media should be mounted", isMediaMounted());
     90         String fullId = SECURE_CONTAINER_PREFIX + localId;
     91 
     92         IMountService ms = getMs();
     93         return ms.mountSecureContainer(fullId, key, android.os.Process.myUid());
     94     }
     95 
     96     private int renameContainer(String localId1, String localId2) throws Exception {
     97         assertTrue("Media should be mounted", isMediaMounted());
     98         String fullId1 = SECURE_CONTAINER_PREFIX + localId1;
     99         String fullId2 = SECURE_CONTAINER_PREFIX + localId2;
    100 
    101         IMountService ms = getMs();
    102         return ms.renameSecureContainer(fullId1, fullId2);
    103     }
    104 
    105     private int unmountContainer(String localId, boolean force) throws Exception {
    106         assertTrue("Media should be mounted", isMediaMounted());
    107         String fullId = SECURE_CONTAINER_PREFIX + localId;
    108 
    109         IMountService ms = getMs();
    110         return ms.unmountSecureContainer(fullId, force);
    111     }
    112 
    113     private int destroyContainer(String localId, boolean force) throws Exception {
    114         assertTrue("Media should be mounted", isMediaMounted());
    115         String fullId = SECURE_CONTAINER_PREFIX + localId;
    116 
    117         IMountService ms = getMs();
    118         return ms.destroySecureContainer(fullId, force);
    119     }
    120 
    121     private boolean isContainerMounted(String localId) throws Exception {
    122         assertTrue("Media should be mounted", isMediaMounted());
    123         String fullId = SECURE_CONTAINER_PREFIX + localId;
    124 
    125         IMountService ms = getMs();
    126         return ms.isSecureContainerMounted(fullId);
    127     }
    128 
    129     private IMountService getMs() {
    130         IBinder service = ServiceManager.getService("mount");
    131         if (service != null) {
    132             return IMountService.Stub.asInterface(service);
    133         } else {
    134             Log.e(TAG, "Can't get mount service");
    135         }
    136         return null;
    137     }
    138 
    139     private boolean isMediaMounted() throws Exception {
    140         String mPath = Environment.getExternalStorageDirectory().toString();
    141         String state = getMs().getVolumeState(mPath);
    142         return Environment.MEDIA_MOUNTED.equals(state);
    143     }
    144 
    145 
    146     /*
    147      * CREATE
    148      */
    149 
    150     public void test_Fat_External_Create_Success() throws Exception {
    151         if (Environment.isExternalStorageEmulated()) {
    152             return;
    153         }
    154 
    155         assertEquals(StorageResultCode.OperationSucceeded,
    156                 createContainer("testCreateContainer", 4, "none", FS_FAT, true));
    157         assertTrue(containerExists("testCreateContainer"));
    158     }
    159 
    160     public void test_Ext4_External_Create_Success() throws Exception {
    161         if (Environment.isExternalStorageEmulated()) {
    162             return;
    163         }
    164 
    165         assertEquals(StorageResultCode.OperationSucceeded,
    166                 createContainer("testCreateContainer", 4, "none", FS_EXT4, true));
    167         assertTrue(containerExists("testCreateContainer"));
    168     }
    169 
    170     public void test_Fat_Internal_Create_Success() throws Exception {
    171         assertEquals(StorageResultCode.OperationSucceeded,
    172                 createContainer("testCreateContainer", 4, "none", FS_FAT, false));
    173         assertTrue(containerExists("testCreateContainer"));
    174     }
    175 
    176     public void test_Ext4_Internal_Create_Success() throws Exception {
    177         assertEquals(StorageResultCode.OperationSucceeded,
    178                 createContainer("testCreateContainer", 4, "none", FS_EXT4, false));
    179         assertTrue(containerExists("testCreateContainer"));
    180     }
    181 
    182 
    183     /*
    184      * CREATE MIN SIZE
    185      */
    186 
    187     public void test_Fat_External_CreateMinSize_Success() throws Exception {
    188         if (Environment.isExternalStorageEmulated()) {
    189             return;
    190         }
    191 
    192         assertEquals(StorageResultCode.OperationSucceeded,
    193                 createContainer("testCreateContainer", 1, "none", FS_FAT, true));
    194         assertTrue(containerExists("testCreateContainer"));
    195     }
    196 
    197     public void test_Ext4_External_CreateMinSize_Success() throws Exception {
    198         if (Environment.isExternalStorageEmulated()) {
    199             return;
    200         }
    201 
    202         assertEquals(StorageResultCode.OperationSucceeded,
    203                 createContainer("testCreateContainer", 1, "none", FS_EXT4, true));
    204         assertTrue(containerExists("testCreateContainer"));
    205     }
    206 
    207     public void test_Fat_Internal_CreateMinSize_Success() throws Exception {
    208         assertEquals(StorageResultCode.OperationSucceeded,
    209                 createContainer("testCreateContainer", 1, "none", FS_FAT, false));
    210         assertTrue(containerExists("testCreateContainer"));
    211     }
    212 
    213     public void test_Ext4_Internal_CreateMinSize_Success() throws Exception {
    214         assertEquals(StorageResultCode.OperationSucceeded,
    215                 createContainer("testCreateContainer", 1, "none", FS_EXT4, false));
    216         assertTrue(containerExists("testCreateContainer"));
    217     }
    218 
    219 
    220     /*
    221      * CREATE ZERO SIZE - FAIL CASE
    222      */
    223 
    224     public void test_Fat_External_CreateZeroSize_Failure() throws Exception {
    225         if (Environment.isExternalStorageEmulated()) {
    226             return;
    227         }
    228 
    229         assertEquals(StorageResultCode.OperationFailedInternalError,
    230                 createContainer("testCreateZeroContainer", 0, "none", FS_FAT, true));
    231     }
    232 
    233     public void test_Ext4_External_CreateZeroSize_Failure() throws Exception {
    234         if (Environment.isExternalStorageEmulated()) {
    235             return;
    236         }
    237 
    238         assertEquals(StorageResultCode.OperationFailedInternalError,
    239                 createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, true));
    240     }
    241 
    242     public void test_Fat_Internal_CreateZeroSize_Failure() throws Exception {
    243         assertEquals(StorageResultCode.OperationFailedInternalError,
    244                 createContainer("testCreateZeroContainer", 0, "none", FS_FAT, false));
    245     }
    246 
    247     public void test_Ext4_Internal_CreateZeroSize_Failure() throws Exception {
    248         assertEquals(StorageResultCode.OperationFailedInternalError,
    249                 createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, false));
    250     }
    251 
    252 
    253     /*
    254      * CREATE DUPLICATE - FAIL CASE
    255      */
    256 
    257     public void test_Fat_External_CreateDuplicate_Failure() throws Exception {
    258         if (Environment.isExternalStorageEmulated()) {
    259             return;
    260         }
    261 
    262         assertEquals(StorageResultCode.OperationSucceeded,
    263                 createContainer("testCreateDupContainer", 4, "none", FS_FAT, true));
    264 
    265         assertEquals(StorageResultCode.OperationFailedInternalError,
    266                 createContainer("testCreateDupContainer", 4, "none", FS_FAT, true));
    267     }
    268 
    269     public void test_Ext4_External_CreateDuplicate_Failure() throws Exception {
    270         if (Environment.isExternalStorageEmulated()) {
    271             return;
    272         }
    273 
    274         assertEquals(StorageResultCode.OperationSucceeded,
    275                 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true));
    276 
    277         assertEquals(StorageResultCode.OperationFailedInternalError,
    278                 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true));
    279     }
    280 
    281     public void test_Fat_Internal_CreateDuplicate_Failure() throws Exception {
    282         assertEquals(StorageResultCode.OperationSucceeded,
    283                 createContainer("testCreateDupContainer", 4, "none", FS_FAT, false));
    284 
    285         assertEquals(StorageResultCode.OperationFailedInternalError,
    286                 createContainer("testCreateDupContainer", 4, "none", FS_FAT, false));
    287     }
    288 
    289     public void test_Ext4_Internal_CreateDuplicate_Failure() throws Exception {
    290         assertEquals(StorageResultCode.OperationSucceeded,
    291                 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false));
    292 
    293         assertEquals(StorageResultCode.OperationFailedInternalError,
    294                 createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false));
    295     }
    296 
    297 
    298     /*
    299      * DESTROY
    300      */
    301 
    302     public void test_Fat_External_Destroy_Success() throws Exception {
    303         if (Environment.isExternalStorageEmulated()) {
    304             return;
    305         }
    306 
    307         assertEquals(StorageResultCode.OperationSucceeded,
    308                 createContainer("testDestroyContainer", 4, "none", FS_FAT, true));
    309         assertEquals(StorageResultCode.OperationSucceeded,
    310                 destroyContainer("testDestroyContainer", false));
    311     }
    312 
    313     public void test_Ext4_External_Destroy_Success() throws Exception {
    314         if (Environment.isExternalStorageEmulated()) {
    315             return;
    316         }
    317 
    318         assertEquals(StorageResultCode.OperationSucceeded,
    319                 createContainer("testDestroyContainer", 4, "none", FS_EXT4, true));
    320         assertEquals(StorageResultCode.OperationSucceeded,
    321                 destroyContainer("testDestroyContainer", false));
    322     }
    323 
    324     public void test_Fat_Internal_Destroy_Success() throws Exception {
    325         assertEquals(StorageResultCode.OperationSucceeded,
    326                 createContainer("testDestroyContainer", 4, "none", FS_FAT, false));
    327         assertEquals(StorageResultCode.OperationSucceeded,
    328                 destroyContainer("testDestroyContainer", false));
    329     }
    330 
    331     public void test_Ext4_Internal_Destroy_Success() throws Exception {
    332         assertEquals(StorageResultCode.OperationSucceeded,
    333                 createContainer("testDestroyContainer", 4, "none", FS_EXT4, false));
    334         assertEquals(StorageResultCode.OperationSucceeded,
    335                 destroyContainer("testDestroyContainer", false));
    336     }
    337 
    338 
    339     /*
    340      * MOUNT
    341      */
    342 
    343     public void test_Fat_External_Mount() throws Exception {
    344         if (Environment.isExternalStorageEmulated()) {
    345             return;
    346         }
    347 
    348         assertEquals(StorageResultCode.OperationSucceeded,
    349                 createContainer("testMountContainer", 4, "none", FS_FAT, true));
    350 
    351         assertEquals(StorageResultCode.OperationSucceeded,
    352                 unmountContainer("testMountContainer", false));
    353 
    354         assertEquals(StorageResultCode.OperationSucceeded,
    355                 mountContainer("testMountContainer", "none"));
    356     }
    357 
    358 
    359     /*
    360      * MOUNT BAD KEY - FAIL CASE
    361      */
    362 
    363     public void test_Fat_External_MountBadKey_Failure() throws Exception {
    364         if (Environment.isExternalStorageEmulated()) {
    365             return;
    366         }
    367 
    368         assertEquals(StorageResultCode.OperationSucceeded,
    369                 createContainer("testMountBadKey", 4, "00000000000000000000000000000000", FS_FAT,
    370                         true));
    371 
    372         assertEquals(StorageResultCode.OperationSucceeded,
    373                 unmountContainer("testMountBadKey", false));
    374 
    375         assertEquals(StorageResultCode.OperationFailedInternalError,
    376                 mountContainer("testMountContainer", "000000000000000000000000000000001"));
    377 
    378         assertEquals(StorageResultCode.OperationFailedInternalError,
    379                 mountContainer("testMountContainer", "none"));
    380     }
    381 
    382 
    383     public void test_Fat_External_UnmountBusy_Success() throws Exception {
    384         if (Environment.isExternalStorageEmulated()) {
    385             return;
    386         }
    387 
    388         IMountService ms = getMs();
    389         assertEquals(StorageResultCode.OperationSucceeded,
    390                 createContainer("testUnmountBusyContainer", 4, "none", FS_FAT, true));
    391 
    392         String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX
    393                 + "testUnmountBusyContainer");
    394 
    395         File f = new File(path, "reference");
    396         FileOutputStream fos = new FileOutputStream(f);
    397 
    398         assertEquals(StorageResultCode.OperationFailedStorageBusy,
    399                 unmountContainer("testUnmountBusyContainer", false));
    400 
    401         fos.close();
    402         assertEquals(StorageResultCode.OperationSucceeded,
    403                 unmountContainer("testUnmountBusyContainer", false));
    404     }
    405 
    406     public void test_Fat_External_DestroyBusy() throws Exception {
    407         if (Environment.isExternalStorageEmulated()) {
    408             return;
    409         }
    410 
    411         IMountService ms = getMs();
    412 
    413         assertEquals(StorageResultCode.OperationSucceeded,
    414                 createContainer("testDestroyBusyContainer", 4, "none", FS_FAT, true));
    415 
    416         String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX
    417                 + "testDestroyBusyContainer");
    418 
    419         File f = new File(path, "reference");
    420         FileOutputStream fos = new FileOutputStream(f);
    421 
    422         assertEquals(StorageResultCode.OperationFailedStorageBusy,
    423                 destroyContainer("testDestroyBusyContainer", false));
    424 
    425         fos.close();
    426         assertEquals(StorageResultCode.OperationSucceeded,
    427                 destroyContainer("testDestroyBusyContainer", false));
    428     }
    429 
    430     public void test_Fat_External_Rename_Success() throws Exception {
    431         if (Environment.isExternalStorageEmulated()) {
    432             return;
    433         }
    434 
    435         assertEquals(StorageResultCode.OperationSucceeded,
    436                 createContainer("testRenameContainer.1", 4, "none", FS_FAT, true));
    437 
    438         assertEquals(StorageResultCode.OperationSucceeded,
    439                 unmountContainer("testRenameContainer.1", false));
    440 
    441         assertEquals(StorageResultCode.OperationSucceeded,
    442                 renameContainer("testRenameContainer.1", "testRenameContainer.2"));
    443 
    444         assertFalse(containerExists("testRenameContainer.1"));
    445         assertTrue(containerExists("testRenameContainer.2"));
    446     }
    447 
    448     public void test_Fat_External_RenameSrcMounted_Failure() throws Exception {
    449         if (Environment.isExternalStorageEmulated()) {
    450             return;
    451         }
    452 
    453         assertEquals(StorageResultCode.OperationSucceeded,
    454                 createContainer("testRenameContainer.1", 4, "none", FS_FAT, true));
    455 
    456         assertEquals(StorageResultCode.OperationFailedStorageMounted,
    457                 renameContainer("testRenameContainer.1", "testRenameContainer.2"));
    458     }
    459 
    460     public void test_Fat_External_RenameDstMounted_Failure() throws Exception {
    461         if (Environment.isExternalStorageEmulated()) {
    462             return;
    463         }
    464 
    465         assertEquals(StorageResultCode.OperationSucceeded,
    466                 createContainer("testRenameContainer.1", 4, "none", FS_FAT, true));
    467 
    468         assertEquals(StorageResultCode.OperationSucceeded,
    469                 unmountContainer("testRenameContainer.1", false));
    470 
    471         assertEquals(StorageResultCode.OperationSucceeded,
    472                 createContainer("testRenameContainer.2", 4, "none", FS_FAT, true));
    473 
    474         assertEquals(StorageResultCode.OperationFailedStorageMounted,
    475                 renameContainer("testRenameContainer.1", "testRenameContainer.2"));
    476     }
    477 
    478     public void test_Fat_External_Size_Success() throws Exception {
    479         if (Environment.isExternalStorageEmulated()) {
    480             return;
    481         }
    482 
    483         IMountService ms = getMs();
    484         assertEquals(StorageResultCode.OperationSucceeded,
    485                 createContainer("testContainerSize", 1, "none", FS_FAT, true));
    486         String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX + "testContainerSize");
    487 
    488         byte[] buf = new byte[4096];
    489         File f = new File(path, "reference");
    490         FileOutputStream fos = new FileOutputStream(f);
    491         for (int i = 0; i < (1024 * 1024); i += buf.length) {
    492             fos.write(buf);
    493         }
    494         fos.close();
    495     }
    496 
    497     public void testGetSecureContainerPath_NonExistPath_Failure() throws Exception {
    498         IMountService ms = getMs();
    499         assertNull("Getting the path for an invalid container should return null",
    500                 ms.getSecureContainerPath("jparks.broke.it"));
    501     }
    502 
    503     /*------------ Tests for unmounting volume ---*/
    504     public final long MAX_WAIT_TIME=120*1000;
    505     public final long WAIT_TIME_INCR=20*1000;
    506 
    507     boolean getMediaState() throws Exception {
    508         String mPath = Environment.getExternalStorageDirectory().toString();
    509         String state = getMs().getVolumeState(mPath);
    510         return Environment.MEDIA_MOUNTED.equals(state);
    511     }
    512 
    513     boolean mountMedia() throws Exception {
    514         if (Environment.isExternalStorageEmulated()) {
    515             return true;
    516         }
    517 
    518         if (getMediaState()) {
    519             return true;
    520         }
    521 
    522         String mPath = Environment.getExternalStorageDirectory().toString();
    523         int ret = getMs().mountVolume(mPath);
    524         return ret == StorageResultCode.OperationSucceeded;
    525     }
    526 
    527     class StorageListener extends StorageEventListener {
    528         String oldState;
    529         String newState;
    530         String path;
    531         private boolean doneFlag = false;
    532 
    533         public void action() {
    534             synchronized (this) {
    535                 doneFlag = true;
    536                 notifyAll();
    537             }
    538         }
    539 
    540         public boolean isDone() {
    541             return doneFlag;
    542         }
    543 
    544         @Override
    545         public void onStorageStateChanged(String path, String oldState, String newState) {
    546             if (localLOGV) Log.i(TAG, "Storage state changed from " + oldState + " to " + newState);
    547             this.oldState = oldState;
    548             this.newState = newState;
    549             this.path = path;
    550             action();
    551         }
    552     }
    553 
    554     private void unmountMedia() throws Exception {
    555         if (Environment.isExternalStorageEmulated()) {
    556             return;
    557         }
    558 
    559         if (!getMediaState()) {
    560             return;
    561         }
    562 
    563         String path = Environment.getExternalStorageDirectory().toString();
    564         StorageListener observer = new StorageListener();
    565         StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
    566         sm.registerListener(observer);
    567         try {
    568             // Wait on observer
    569             synchronized(observer) {
    570                 getMs().unmountVolume(path, false, false);
    571                 long waitTime = 0;
    572                 while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
    573                     observer.wait(WAIT_TIME_INCR);
    574                     waitTime += WAIT_TIME_INCR;
    575                 }
    576                 if(!observer.isDone()) {
    577                     fail("Timed out waiting for packageInstalled callback");
    578                 }
    579             }
    580         } finally {
    581             sm.unregisterListener(observer);
    582         }
    583     }
    584 
    585     public void testUnmount() throws Exception {
    586         boolean oldStatus = getMediaState();
    587         Log.i(TAG, "oldStatus="+oldStatus);
    588         try {
    589             // Mount media firsts
    590             if (!getMediaState()) {
    591                 mountMedia();
    592             }
    593             unmountMedia();
    594         } finally {
    595             // Restore old status
    596             boolean currStatus = getMediaState();
    597             if (oldStatus != currStatus) {
    598                 if (oldStatus) {
    599                     // Mount media
    600                     mountMedia();
    601                 } else {
    602                     unmountMedia();
    603                 }
    604             }
    605         }
    606     }
    607 
    608     class MultipleStorageLis extends StorageListener {
    609         int count = 0;
    610         public void onStorageStateChanged(String path, String oldState, String newState) {
    611             count++;
    612             super.action();
    613         }
    614     }
    615     /*
    616      * This test invokes unmount multiple time and expects the call back
    617      * to be invoked just once.
    618      */
    619     public void testUnmountMultiple() throws Exception {
    620         if (Environment.isExternalStorageEmulated()) {
    621             return;
    622         }
    623 
    624         boolean oldStatus = getMediaState();
    625         StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
    626         MultipleStorageLis observer = new MultipleStorageLis();
    627         try {
    628             // Mount media firsts
    629             if (!getMediaState()) {
    630                 mountMedia();
    631             }
    632             String path = Environment.getExternalStorageDirectory().toString();
    633             sm.registerListener(observer);
    634             // Wait on observer
    635             synchronized(observer) {
    636                 for (int i = 0; i < 5; i++) {
    637                     getMs().unmountVolume(path, false, false);
    638                 }
    639                 long waitTime = 0;
    640                 while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
    641                     observer.wait(WAIT_TIME_INCR);
    642                     waitTime += WAIT_TIME_INCR;
    643                 }
    644                 if(!observer.isDone()) {
    645                     fail("Timed out waiting for packageInstalled callback");
    646                 }
    647             }
    648             assertEquals(observer.count, 1);
    649         } finally {
    650             sm.unregisterListener(observer);
    651             // Restore old status
    652             boolean currStatus = getMediaState();
    653             if (oldStatus != currStatus) {
    654                 if (oldStatus) {
    655                     // Mount media
    656                     mountMedia();
    657                 } else {
    658                     unmountMedia();
    659                 }
    660             }
    661         }
    662     }
    663 
    664     class ShutdownObserver extends  IMountShutdownObserver.Stub{
    665         private boolean doneFlag = false;
    666         int statusCode;
    667 
    668         public void action() {
    669             synchronized (this) {
    670                 doneFlag = true;
    671                 notifyAll();
    672             }
    673         }
    674 
    675         public boolean isDone() {
    676             return doneFlag;
    677         }
    678         public void onShutDownComplete(int statusCode) throws RemoteException {
    679             this.statusCode = statusCode;
    680             action();
    681         }
    682 
    683     }
    684 
    685     void invokeShutdown() throws Exception {
    686         IMountService ms = getMs();
    687         ShutdownObserver observer = new ShutdownObserver();
    688         synchronized (observer) {
    689             ms.shutdown(observer);
    690         }
    691     }
    692 
    693     public void testShutdown() throws Exception {
    694         if (Environment.isExternalStorageEmulated()) {
    695             return;
    696         }
    697 
    698         boolean oldStatus = getMediaState();
    699         try {
    700             // Mount media firsts
    701             if (!getMediaState()) {
    702                 mountMedia();
    703             }
    704             invokeShutdown();
    705         } finally {
    706             // Restore old status
    707             boolean currStatus = getMediaState();
    708             if (oldStatus != currStatus) {
    709                 if (oldStatus) {
    710                     // Mount media
    711                     mountMedia();
    712                 } else {
    713                     unmountMedia();
    714                 }
    715             }
    716         }
    717     }
    718 
    719     /*
    720      * This test invokes unmount multiple time and expects the call back
    721      * to be invoked just once.
    722      */
    723     public void testShutdownMultiple() throws Exception {
    724         if (Environment.isExternalStorageEmulated()) {
    725             return;
    726         }
    727 
    728         boolean oldStatus = getMediaState();
    729         try {
    730             // Mount media firsts
    731             if (!getMediaState()) {
    732                 mountMedia();
    733             }
    734             IMountService ms = getMs();
    735             ShutdownObserver observer = new ShutdownObserver();
    736             synchronized (observer) {
    737                 ms.shutdown(observer);
    738                 for (int i = 0; i < 4; i++) {
    739                     ms.shutdown(null);
    740                 }
    741             }
    742         } finally {
    743             // Restore old status
    744             boolean currStatus = getMediaState();
    745             if (oldStatus != currStatus) {
    746                 if (oldStatus) {
    747                     // Mount media
    748                     mountMedia();
    749                 } else {
    750                     unmountMedia();
    751                 }
    752             }
    753         }
    754     }
    755 
    756 }
    757