Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2010 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.server;
     18 
     19 import android.content.Context;
     20 import android.content.res.Resources;
     21 import android.content.res.Resources.NotFoundException;
     22 import android.os.FileUtils;
     23 import android.os.storage.OnObbStateChangeListener;
     24 import android.os.storage.StorageManager;
     25 import android.test.AndroidTestCase;
     26 import android.test.ComparisonFailure;
     27 import android.test.suitebuilder.annotation.LargeTest;
     28 import android.util.Log;
     29 
     30 import com.android.frameworks.servicestests.R;
     31 
     32 import java.io.File;
     33 import java.io.InputStream;
     34 
     35 public class MountServiceTests extends AndroidTestCase {
     36     private static final String TAG = "MountServiceTests";
     37 
     38     private static final long MAX_WAIT_TIME = 25*1000;
     39     private static final long WAIT_TIME_INCR = 5*1000;
     40 
     41     private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
     42 
     43     private static void assertStartsWith(String message, String prefix, String actual) {
     44         if (!actual.startsWith(prefix)) {
     45             throw new ComparisonFailure(message, prefix, actual);
     46         }
     47     }
     48 
     49     private static class ObbObserver extends OnObbStateChangeListener {
     50         private String path;
     51 
     52         public int state = -1;
     53         boolean done = false;
     54 
     55         @Override
     56         public void onObbStateChange(String path, int state) {
     57             Log.d(TAG, "Received message.  path=" + path + ", state=" + state);
     58             synchronized (this) {
     59                 this.path = path;
     60                 this.state = state;
     61                 done = true;
     62                 notifyAll();
     63             }
     64         }
     65 
     66         public String getPath() {
     67             assertTrue("Expected ObbObserver to have received a state change.", done);
     68             return path;
     69         }
     70 
     71         public int getState() {
     72             assertTrue("Expected ObbObserver to have received a state change.", done);
     73             return state;
     74         }
     75 
     76         public void reset() {
     77             this.path = null;
     78             this.state = -1;
     79             done = false;
     80         }
     81 
     82         public boolean isDone() {
     83             return done;
     84         }
     85 
     86         public boolean waitForCompletion() {
     87             long waitTime = 0;
     88             synchronized (this) {
     89                 while (!isDone() && waitTime < MAX_WAIT_TIME) {
     90                     try {
     91                         wait(WAIT_TIME_INCR);
     92                         waitTime += WAIT_TIME_INCR;
     93                     } catch (InterruptedException e) {
     94                         Log.i(TAG, "Interrupted during sleep", e);
     95                     }
     96                 }
     97             }
     98 
     99             return isDone();
    100         }
    101     }
    102 
    103     private File getFilePath(String name) {
    104         final File filesDir = mContext.getFilesDir();
    105         final File outFile = new File(filesDir, name);
    106         return outFile;
    107     }
    108 
    109     private void copyRawToFile(int rawResId, File outFile) {
    110         Resources res = mContext.getResources();
    111         InputStream is = null;
    112         try {
    113             is = res.openRawResource(rawResId);
    114         } catch (NotFoundException e) {
    115             fail("Failed to load resource with id: " + rawResId);
    116         }
    117         FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
    118                 | FileUtils.S_IRWXO, -1, -1);
    119         assertTrue(FileUtils.copyToFile(is, outFile));
    120         FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
    121                 | FileUtils.S_IRWXO, -1, -1);
    122     }
    123 
    124     private StorageManager getStorageManager() {
    125         return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
    126     }
    127 
    128     private void mountObb(StorageManager sm, final int resource, final File file,
    129             int expectedState) {
    130         copyRawToFile(resource, file);
    131 
    132         final ObbObserver observer = new ObbObserver();
    133         assertTrue("mountObb call on " + file.getPath() + " should succeed",
    134                 sm.mountObb(file.getPath(), null, observer));
    135 
    136         assertTrue("Mount should have completed",
    137                 observer.waitForCompletion());
    138 
    139         if (expectedState == OnObbStateChangeListener.MOUNTED) {
    140             assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
    141         }
    142 
    143         assertEquals("Actual file and resolved file should be the same",
    144                 file.getPath(), observer.getPath());
    145 
    146         assertEquals(expectedState, observer.getState());
    147     }
    148 
    149     private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource,
    150             final File file) {
    151         copyRawToFile(resource, file);
    152 
    153         final ObbObserver observer = new ObbObserver();
    154         assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file
    155                 .getPath(), null, observer));
    156 
    157         return observer;
    158     }
    159 
    160     private void waitForObbActionCompletion(final StorageManager sm, final File file,
    161             final ObbObserver observer, int expectedState, boolean checkPath) {
    162         assertTrue("Mount should have completed", observer.waitForCompletion());
    163 
    164         assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
    165 
    166         if (checkPath) {
    167             assertEquals("Actual file and resolved file should be the same", file.getPath(),
    168                     observer.getPath());
    169         }
    170 
    171         assertEquals(expectedState, observer.getState());
    172     }
    173 
    174     private String checkMountedPath(final StorageManager sm, final File file) {
    175         final String mountPath = sm.getMountedObbPath(file.getPath());
    176         assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX,
    177                 OBB_MOUNT_PREFIX,
    178                 mountPath);
    179         return mountPath;
    180     }
    181 
    182     private void unmountObb(final StorageManager sm, final File file, int expectedState) {
    183         final ObbObserver observer = new ObbObserver();
    184 
    185         assertTrue("unmountObb call on test1.obb should succeed",
    186                 sm.unmountObb(file.getPath(), false, observer));
    187 
    188         assertTrue("Unmount should have completed",
    189                 observer.waitForCompletion());
    190 
    191         assertEquals(expectedState, observer.getState());
    192 
    193         if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
    194             assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
    195         }
    196     }
    197 
    198     @LargeTest
    199     public void testMountAndUnmountObbNormal() {
    200         StorageManager sm = getStorageManager();
    201 
    202         final File outFile = getFilePath("test1.obb");
    203 
    204         mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
    205 
    206         mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
    207 
    208         final String mountPath = checkMountedPath(sm, outFile);
    209         final File mountDir = new File(mountPath);
    210 
    211         assertTrue("OBB mounted path should be a directory",
    212                 mountDir.isDirectory());
    213 
    214         unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
    215     }
    216 
    217     @LargeTest
    218     public void testAttemptMountNonObb() {
    219         StorageManager sm = getStorageManager();
    220 
    221         final File outFile = getFilePath("test1_nosig.obb");
    222 
    223         mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
    224 
    225         assertFalse("OBB should not be mounted",
    226                 sm.isObbMounted(outFile.getPath()));
    227 
    228         assertNull("OBB's mounted path should be null",
    229                 sm.getMountedObbPath(outFile.getPath()));
    230     }
    231 
    232     @LargeTest
    233     public void testAttemptMountObbWrongPackage() {
    234         StorageManager sm = getStorageManager();
    235 
    236         final File outFile = getFilePath("test1_wrongpackage.obb");
    237 
    238         mountObb(sm, R.raw.test1_wrongpackage, outFile,
    239                 OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
    240 
    241         assertFalse("OBB should not be mounted",
    242                 sm.isObbMounted(outFile.getPath()));
    243 
    244         assertNull("OBB's mounted path should be null",
    245                 sm.getMountedObbPath(outFile.getPath()));
    246     }
    247 
    248     @LargeTest
    249     public void testMountAndUnmountTwoObbs() {
    250         StorageManager sm = getStorageManager();
    251 
    252         final File file1 = getFilePath("test1.obb");
    253         final File file2 = getFilePath("test2.obb");
    254 
    255         ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1);
    256         ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2);
    257 
    258         Log.d(TAG, "Waiting for OBB #1 to complete mount");
    259         waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false);
    260         Log.d(TAG, "Waiting for OBB #2 to complete mount");
    261         waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false);
    262 
    263         final String mountPath1 = checkMountedPath(sm, file1);
    264         final File mountDir1 = new File(mountPath1);
    265         assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
    266 
    267         final String mountPath2 = checkMountedPath(sm, file2);
    268         final File mountDir2 = new File(mountPath2);
    269         assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
    270 
    271         unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
    272         unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
    273     }
    274 }
    275