summaryrefslogtreecommitdiffstats
path: root/services/tests/servicestests/src/com/android/server/MountServiceTests.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/tests/servicestests/src/com/android/server/MountServiceTests.java')
-rw-r--r--services/tests/servicestests/src/com/android/server/MountServiceTests.java317
1 files changed, 317 insertions, 0 deletions
diff --git a/services/tests/servicestests/src/com/android/server/MountServiceTests.java b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
new file mode 100644
index 0000000..9c88b40
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/MountServiceTests.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
+import android.os.FileUtils;
+import android.os.storage.OnObbStateChangeListener;
+import android.os.storage.StorageManager;
+import android.test.AndroidTestCase;
+import android.test.ComparisonFailure;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import static com.android.server.MountService.buildObbPath;
+
+import com.android.frameworks.servicestests.R;
+
+import java.io.File;
+import java.io.InputStream;
+
+public class MountServiceTests extends AndroidTestCase {
+ private static final String TAG = "MountServiceTests";
+
+ private static final long MAX_WAIT_TIME = 25*1000;
+ private static final long WAIT_TIME_INCR = 5*1000;
+
+ private static final String OBB_MOUNT_PREFIX = "/mnt/obb/";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ private static void assertStartsWith(String message, String prefix, String actual) {
+ if (!actual.startsWith(prefix)) {
+ throw new ComparisonFailure(message, prefix, actual);
+ }
+ }
+
+ private static class ObbObserver extends OnObbStateChangeListener {
+ private String path;
+
+ public int state = -1;
+ boolean done = false;
+
+ @Override
+ public void onObbStateChange(String path, int state) {
+ Log.d(TAG, "Received message. path=" + path + ", state=" + state);
+ synchronized (this) {
+ this.path = path;
+ this.state = state;
+ done = true;
+ notifyAll();
+ }
+ }
+
+ public String getPath() {
+ assertTrue("Expected ObbObserver to have received a state change.", done);
+ return path;
+ }
+
+ public int getState() {
+ assertTrue("Expected ObbObserver to have received a state change.", done);
+ return state;
+ }
+
+ public void reset() {
+ this.path = null;
+ this.state = -1;
+ done = false;
+ }
+
+ public boolean isDone() {
+ return done;
+ }
+
+ public boolean waitForCompletion() {
+ long waitTime = 0;
+ synchronized (this) {
+ while (!isDone() && waitTime < MAX_WAIT_TIME) {
+ try {
+ wait(WAIT_TIME_INCR);
+ waitTime += WAIT_TIME_INCR;
+ } catch (InterruptedException e) {
+ Log.i(TAG, "Interrupted during sleep", e);
+ }
+ }
+ }
+
+ return isDone();
+ }
+ }
+
+ private File getFilePath(String name) {
+ final File filesDir = mContext.getFilesDir();
+ final File outFile = new File(filesDir, name);
+ return outFile;
+ }
+
+ private void copyRawToFile(int rawResId, File outFile) {
+ Resources res = mContext.getResources();
+ InputStream is = null;
+ try {
+ is = res.openRawResource(rawResId);
+ } catch (NotFoundException e) {
+ fail("Failed to load resource with id: " + rawResId);
+ }
+ FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+ | FileUtils.S_IRWXO, -1, -1);
+ assertTrue(FileUtils.copyToFile(is, outFile));
+ FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG
+ | FileUtils.S_IRWXO, -1, -1);
+ }
+
+ private StorageManager getStorageManager() {
+ return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
+ }
+
+ private void mountObb(StorageManager sm, final int resource, final File file,
+ int expectedState) {
+ copyRawToFile(resource, file);
+
+ final ObbObserver observer = new ObbObserver();
+ assertTrue("mountObb call on " + file.getPath() + " should succeed",
+ sm.mountObb(file.getPath(), null, observer));
+
+ assertTrue("Mount should have completed",
+ observer.waitForCompletion());
+
+ if (expectedState == OnObbStateChangeListener.MOUNTED) {
+ assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
+ }
+
+ assertEquals("Actual file and resolved file should be the same",
+ file.getPath(), observer.getPath());
+
+ assertEquals(expectedState, observer.getState());
+ }
+
+ private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource,
+ final File file) {
+ copyRawToFile(resource, file);
+
+ final ObbObserver observer = new ObbObserver();
+ assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file
+ .getPath(), null, observer));
+
+ return observer;
+ }
+
+ private void waitForObbActionCompletion(final StorageManager sm, final File file,
+ final ObbObserver observer, int expectedState, boolean checkPath) {
+ assertTrue("Mount should have completed", observer.waitForCompletion());
+
+ assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath()));
+
+ if (checkPath) {
+ assertEquals("Actual file and resolved file should be the same", file.getPath(),
+ observer.getPath());
+ }
+
+ assertEquals(expectedState, observer.getState());
+ }
+
+ private String checkMountedPath(final StorageManager sm, final File file) {
+ final String mountPath = sm.getMountedObbPath(file.getPath());
+ assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX,
+ OBB_MOUNT_PREFIX,
+ mountPath);
+ return mountPath;
+ }
+
+ private void unmountObb(final StorageManager sm, final File file, int expectedState) {
+ final ObbObserver observer = new ObbObserver();
+
+ assertTrue("unmountObb call on test1.obb should succeed",
+ sm.unmountObb(file.getPath(),
+ false, observer));
+
+ assertTrue("Unmount should have completed",
+ observer.waitForCompletion());
+
+ assertEquals(expectedState, observer.getState());
+
+ if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
+ assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
+ }
+ }
+
+ @LargeTest
+ public void testMountAndUnmountObbNormal() {
+ StorageManager sm = getStorageManager();
+
+ final File outFile = getFilePath("test1.obb");
+
+ mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED);
+
+ mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED);
+
+ final String mountPath = checkMountedPath(sm, outFile);
+ final File mountDir = new File(mountPath);
+
+ assertTrue("OBB mounted path should be a directory",
+ mountDir.isDirectory());
+
+ unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
+ }
+
+ @LargeTest
+ public void testAttemptMountNonObb() {
+ StorageManager sm = getStorageManager();
+
+ final File outFile = getFilePath("test1_nosig.obb");
+
+ mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
+
+ assertFalse("OBB should not be mounted",
+ sm.isObbMounted(outFile.getPath()));
+
+ assertNull("OBB's mounted path should be null",
+ sm.getMountedObbPath(outFile.getPath()));
+ }
+
+ @LargeTest
+ public void testAttemptMountObbWrongPackage() {
+ StorageManager sm = getStorageManager();
+
+ final File outFile = getFilePath("test1_wrongpackage.obb");
+
+ mountObb(sm, R.raw.test1_wrongpackage, outFile,
+ OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
+
+ assertFalse("OBB should not be mounted",
+ sm.isObbMounted(outFile.getPath()));
+
+ assertNull("OBB's mounted path should be null",
+ sm.getMountedObbPath(outFile.getPath()));
+ }
+
+ @LargeTest
+ public void testMountAndUnmountTwoObbs() {
+ StorageManager sm = getStorageManager();
+
+ final File file1 = getFilePath("test1.obb");
+ final File file2 = getFilePath("test2.obb");
+
+ ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1);
+ ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2);
+
+ Log.d(TAG, "Waiting for OBB #1 to complete mount");
+ waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false);
+ Log.d(TAG, "Waiting for OBB #2 to complete mount");
+ waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false);
+
+ final String mountPath1 = checkMountedPath(sm, file1);
+ final File mountDir1 = new File(mountPath1);
+ assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory());
+
+ final String mountPath2 = checkMountedPath(sm, file2);
+ final File mountDir2 = new File(mountPath2);
+ assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory());
+
+ unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED);
+ unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED);
+ }
+
+ public void testBuildObbPath() {
+ final int userId = 10;
+
+ // Paths outside external storage should remain untouched
+ assertEquals("/storage/random/foo",
+ buildObbPath("/storage/random/foo", userId, true));
+ assertEquals("/storage/random/foo",
+ buildObbPath("/storage/random/foo", userId, false));
+
+ // Paths on user-specific emulated storage
+ assertEquals("/mnt/shell/emulated/10/foo",
+ buildObbPath("/storage/emulated_legacy/foo", userId, true));
+ assertEquals("/storage/emulated/10/foo",
+ buildObbPath("/storage/emulated_legacy/foo", userId, false));
+ assertEquals("/mnt/shell/emulated/10/foo",
+ buildObbPath("/storage/emulated/10/foo", userId, true));
+ assertEquals("/storage/emulated/10/foo",
+ buildObbPath("/storage/emulated/10/foo", userId, false));
+
+ // Paths on shared OBB emulated storage
+ assertEquals("/mnt/shell/emulated/obb/foo",
+ buildObbPath("/storage/emulated_legacy/Android/obb/foo", userId, true));
+ assertEquals("/storage/emulated/0/Android/obb/foo",
+ buildObbPath("/storage/emulated_legacy/Android/obb/foo", userId, false));
+ assertEquals("/mnt/shell/emulated/obb/foo",
+ buildObbPath("/storage/emulated/10/Android/obb/foo", userId, true));
+ assertEquals("/storage/emulated/0/Android/obb/foo",
+ buildObbPath("/storage/emulated/10/Android/obb/foo", userId, false));
+ }
+}