summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2010-10-11 17:24:54 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-10-11 17:24:54 -0700
commitb4de3dca96b9ff18562062e181dcd8b83e641e45 (patch)
treeb2e8b6060e1dbea173de867e5258add9b08ef8f3 /core
parent1169f420f6df5cf5254fed883efa7e6780473c08 (diff)
parentaf9d667ccf3e24058214cf4cc0a8aa8bc5100e3c (diff)
downloadframeworks_base-b4de3dca96b9ff18562062e181dcd8b83e641e45.zip
frameworks_base-b4de3dca96b9ff18562062e181dcd8b83e641e45.tar.gz
frameworks_base-b4de3dca96b9ff18562062e181dcd8b83e641e45.tar.bz2
Merge "OBB: rearrange to be entirely asynchronous" into gingerbread
Diffstat (limited to 'core')
-rw-r--r--core/java/android/os/storage/IMountService.java20
-rw-r--r--core/java/android/os/storage/IObbActionListener.java19
-rw-r--r--core/java/android/os/storage/OnObbStateChangeListener.java58
-rw-r--r--core/java/android/os/storage/StorageManager.java129
-rw-r--r--core/tests/coretests/src/com/android/server/MountServiceTests.java145
5 files changed, 261 insertions, 110 deletions
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 60ea95c..467a0ac 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -484,7 +484,7 @@ public interface IMountService extends IInterface {
* IObbActionListener to inform it of the terminal state of the
* call.
*/
- public void mountObb(String filename, String key, IObbActionListener token)
+ public void mountObb(String filename, String key, IObbActionListener token, int nonce)
throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -493,6 +493,7 @@ public interface IMountService extends IInterface {
_data.writeString(filename);
_data.writeString(key);
_data.writeStrongBinder((token != null ? token.asBinder() : null));
+ _data.writeInt(nonce);
mRemote.transact(Stub.TRANSACTION_mountObb, _data, _reply, 0);
_reply.readException();
} finally {
@@ -508,8 +509,8 @@ public interface IMountService extends IInterface {
* IObbActionListener to inform it of the terminal state of the
* call.
*/
- public void unmountObb(String filename, boolean force, IObbActionListener token)
- throws RemoteException {
+ public void unmountObb(String filename, boolean force, IObbActionListener token,
+ int nonce) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
try {
@@ -517,6 +518,7 @@ public interface IMountService extends IInterface {
_data.writeString(filename);
_data.writeInt((force ? 1 : 0));
_data.writeStrongBinder((token != null ? token.asBinder() : null));
+ _data.writeInt(nonce);
mRemote.transact(Stub.TRANSACTION_unmountObb, _data, _reply, 0);
_reply.readException();
} finally {
@@ -855,7 +857,9 @@ public interface IMountService extends IInterface {
key = data.readString();
IObbActionListener observer;
observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
- mountObb(filename, key, observer);
+ int nonce;
+ nonce = data.readInt();
+ mountObb(filename, key, observer, nonce);
reply.writeNoException();
return true;
}
@@ -867,7 +871,9 @@ public interface IMountService extends IInterface {
force = 0 != data.readInt();
IObbActionListener observer;
observer = IObbActionListener.Stub.asInterface(data.readStrongBinder());
- unmountObb(filename, force, observer);
+ int nonce;
+ nonce = data.readInt();
+ unmountObb(filename, force, observer, nonce);
reply.writeNoException();
return true;
}
@@ -979,7 +985,7 @@ public interface IMountService extends IInterface {
* MountService will call back to the supplied IObbActionListener to inform
* it of the terminal state of the call.
*/
- public void mountObb(String filename, String key, IObbActionListener token)
+ public void mountObb(String filename, String key, IObbActionListener token, int nonce)
throws RemoteException;
/*
@@ -1023,7 +1029,7 @@ public interface IMountService extends IInterface {
* MountService will call back to the supplied IObbActionListener to inform
* it of the terminal state of the call.
*/
- public void unmountObb(String filename, boolean force, IObbActionListener token)
+ public void unmountObb(String filename, boolean force, IObbActionListener token, int nonce)
throws RemoteException;
/*
diff --git a/core/java/android/os/storage/IObbActionListener.java b/core/java/android/os/storage/IObbActionListener.java
index 2c098ac..d6fa58a 100644
--- a/core/java/android/os/storage/IObbActionListener.java
+++ b/core/java/android/os/storage/IObbActionListener.java
@@ -69,9 +69,11 @@ public interface IObbActionListener extends IInterface {
data.enforceInterface(DESCRIPTOR);
String filename;
filename = data.readString();
- String status;
- status = data.readString();
- this.onObbResult(filename, status);
+ int nonce;
+ nonce = data.readInt();
+ int status;
+ status = data.readInt();
+ this.onObbResult(filename, nonce, status);
reply.writeNoException();
return true;
}
@@ -101,13 +103,15 @@ public interface IObbActionListener extends IInterface {
* on
* @param returnCode status of the operation
*/
- public void onObbResult(String filename, String status) throws RemoteException {
+ public void onObbResult(String filename, int nonce, int status)
+ throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(filename);
- _data.writeString(status);
+ _data.writeInt(nonce);
+ _data.writeInt(status);
mRemote.transact(Stub.TRANSACTION_onObbResult, _data, _reply, 0);
_reply.readException();
} finally {
@@ -124,7 +128,8 @@ public interface IObbActionListener extends IInterface {
* Return from an OBB action result.
*
* @param filename the path to the OBB the operation was performed on
- * @param returnCode status of the operation
+ * @param nonce identifier that is meaningful to the receiver
+ * @param status status code as defined in {@link OnObbStateChangeListener}
*/
- public void onObbResult(String filename, String status) throws RemoteException;
+ public void onObbResult(String filename, int nonce, int status) throws RemoteException;
}
diff --git a/core/java/android/os/storage/OnObbStateChangeListener.java b/core/java/android/os/storage/OnObbStateChangeListener.java
index a2d0a56..950195b 100644
--- a/core/java/android/os/storage/OnObbStateChangeListener.java
+++ b/core/java/android/os/storage/OnObbStateChangeListener.java
@@ -17,15 +17,69 @@
package android.os.storage;
/**
- * Used for receiving notifications from {@link StorageManager}.
+ * Used for receiving notifications from {@link StorageManager} about OBB file
+ * states.
*/
public abstract class OnObbStateChangeListener {
+
+ /**
+ * The OBB container is now mounted and ready for use. Returned in status
+ * messages from calls made via {@link StorageManager}
+ */
+ public static final int MOUNTED = 1;
+
+ /**
+ * The OBB container is now unmounted and not usable. Returned in status
+ * messages from calls made via {@link StorageManager}
+ */
+ public static final int UNMOUNTED = 2;
+
+ /**
+ * There was an internal system error encountered while trying to mount the
+ * OBB. Returned in status messages from calls made via
+ * {@link StorageManager}
+ */
+ public static final int ERROR_INTERNAL = 20;
+
+ /**
+ * The OBB could not be mounted by the system. Returned in status messages
+ * from calls made via {@link StorageManager}
+ */
+ public static final int ERROR_COULD_NOT_MOUNT = 21;
+
+ /**
+ * The OBB could not be unmounted. This most likely indicates that a file is
+ * in use on the OBB. Returned in status messages from calls made via
+ * {@link StorageManager}
+ */
+ public static final int ERROR_COULD_NOT_UNMOUNT = 22;
+
+ /**
+ * A call was made to unmount the OBB when it was not mounted. Returned in
+ * status messages from calls made via {@link StorageManager}
+ */
+ public static final int ERROR_NOT_MOUNTED = 23;
+
+ /**
+ * The OBB has already been mounted. Returned in status messages from calls
+ * made via {@link StorageManager}
+ */
+ public static final int ERROR_ALREADY_MOUNTED = 24;
+
+ /**
+ * The current application does not have permission to use this OBB because
+ * the OBB indicates it's owned by a different package or the key used to
+ * open it is incorrect. Returned in status messages from calls made via
+ * {@link StorageManager}
+ */
+ public static final int ERROR_PERMISSION_DENIED = 25;
+
/**
* Called when an OBB has changed states.
*
* @param path path to the OBB file the state change has happened on
* @param state the current state of the OBB
*/
- public void onObbStateChange(String path, String state) {
+ public void onObbStateChange(String path, int state) {
}
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 2ebd049..73ac79f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -22,12 +22,13 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* StorageManager is the interface to the systems storage service. The storage
@@ -69,7 +70,12 @@ public class StorageManager
/*
* List of our listeners
*/
- private ArrayList<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
+ private List<ListenerDelegate> mListeners = new ArrayList<ListenerDelegate>();
+
+ /*
+ * Next available nonce
+ */
+ final private AtomicInteger mNextNonce = new AtomicInteger(0);
private class MountServiceBinderListener extends IMountServiceListener.Stub {
public void onUsbMassStorageConnectionChanged(boolean available) {
@@ -93,57 +99,38 @@ public class StorageManager
private final ObbActionListener mObbActionListener = new ObbActionListener();
private class ObbActionListener extends IObbActionListener.Stub {
- private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>();
+ private SparseArray<ObbListenerDelegate> mListeners = new SparseArray<ObbListenerDelegate>();
@Override
- public void onObbResult(String filename, String status) throws RemoteException {
+ public void onObbResult(String filename, int nonce, int status) throws RemoteException {
+ final ObbListenerDelegate delegate;
synchronized (mListeners) {
- final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
- while (iter.hasNext()) {
- final WeakReference<ObbListenerDelegate> ref = iter.next();
-
- final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
- if (delegate == null) {
- iter.remove();
- continue;
- }
-
- delegate.sendObbStateChanged(filename, status);
+ delegate = mListeners.get(nonce);
+ if (delegate != null) {
+ mListeners.remove(nonce);
}
}
- }
- public void addListener(OnObbStateChangeListener listener) {
- if (listener == null) {
- return;
+ if (delegate != null) {
+ delegate.sendObbStateChanged(filename, status);
}
+ }
- synchronized (mListeners) {
- final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
- while (iter.hasNext()) {
- final WeakReference<ObbListenerDelegate> ref = iter.next();
-
- final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
- if (delegate == null) {
- iter.remove();
- continue;
- }
-
- /*
- * If we're already in the listeners, we don't need to be in
- * there again.
- */
- if (listener.equals(delegate.getListener())) {
- return;
- }
- }
+ public int addListener(OnObbStateChangeListener listener) {
+ final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
- final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
- mListeners.add(new WeakReference<ObbListenerDelegate>(delegate));
+ synchronized (mListeners) {
+ mListeners.put(delegate.nonce, delegate);
}
+
+ return delegate.nonce;
}
}
+ private int getNextNonce() {
+ return mNextNonce.getAndIncrement();
+ }
+
/**
* Private class containing sender and receiver code for StorageEvents.
*/
@@ -151,7 +138,10 @@ public class StorageManager
private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
private final Handler mHandler;
+ private final int nonce;
+
ObbListenerDelegate(OnObbStateChangeListener listener) {
+ nonce = getNextNonce();
mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
mHandler = new Handler(mTgtLooper) {
@Override
@@ -180,7 +170,7 @@ public class StorageManager
return mObbEventListenerRef.get();
}
- void sendObbStateChanged(String path, String state) {
+ void sendObbStateChanged(String path, int state) {
ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
mHandler.sendMessage(e.getMessage());
}
@@ -191,9 +181,10 @@ public class StorageManager
*/
private class ObbStateChangedStorageEvent extends StorageEvent {
public final String path;
- public final String state;
- public ObbStateChangedStorageEvent(String path, String state) {
+ public final int state;
+
+ public ObbStateChangedStorageEvent(String path, int state) {
super(EVENT_OBB_STATE_CHANGED);
this.path = path;
this.state = state;
@@ -420,10 +411,8 @@ public class StorageManager
* <p>
* The OBB will remain mounted for as long as the StorageManager reference
* is held by the application. As soon as this reference is lost, the OBBs
- * in use will be unmounted. The {@link OnObbStateChangeListener} registered with
- * this call will receive all further OBB-related events until it goes out
- * of scope. If the caller is not interested in whether the call succeeds,
- * the <code>listener</code> may be specified as <code>null</code>.
+ * in use will be unmounted. The {@link OnObbStateChangeListener} registered
+ * with this call will receive the success or failure of this operation.
* <p>
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
* file matches a package ID that is owned by the calling program's UID.
@@ -433,12 +422,21 @@ public class StorageManager
* @param filename the path to the OBB file
* @param key secret used to encrypt the OBB; may be <code>null</code> if no
* encryption was used on the OBB.
+ * @param listener will receive the success or failure of the operation
* @return whether the mount call was successfully queued or not
*/
public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
+ if (filename == null) {
+ throw new IllegalArgumentException("filename cannot be null");
+ }
+
+ if (listener == null) {
+ throw new IllegalArgumentException("listener cannot be null");
+ }
+
try {
- mObbActionListener.addListener(listener);
- mMountService.mountObb(filename, key, mObbActionListener);
+ final int nonce = mObbActionListener.addListener(listener);
+ mMountService.mountObb(filename, key, mObbActionListener, nonce);
return true;
} catch (RemoteException e) {
Log.e(TAG, "Failed to mount OBB", e);
@@ -452,10 +450,8 @@ public class StorageManager
* <code>force</code> flag is true, it will kill any application needed to
* unmount the given OBB (even the calling application).
* <p>
- * The {@link OnObbStateChangeListener} registered with this call will receive all
- * further OBB-related events until it goes out of scope. If the caller is
- * not interested in whether the call succeeded, the listener may be
- * specified as <code>null</code>.
+ * The {@link OnObbStateChangeListener} registered with this call will
+ * receive the success or failure of this operation.
* <p>
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
* file matches a package ID that is owned by the calling program's UID.
@@ -466,12 +462,21 @@ public class StorageManager
* @param filename path to the OBB file
* @param force whether to kill any programs using this in order to unmount
* it
+ * @param listener will receive the success or failure of the operation
* @return whether the unmount call was successfully queued or not
*/
public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener) {
+ if (filename == null) {
+ throw new IllegalArgumentException("filename cannot be null");
+ }
+
+ if (listener == null) {
+ throw new IllegalArgumentException("listener cannot be null");
+ }
+
try {
- mObbActionListener.addListener(listener);
- mMountService.unmountObb(filename, force, mObbActionListener);
+ final int nonce = mObbActionListener.addListener(listener);
+ mMountService.unmountObb(filename, force, mObbActionListener, nonce);
return true;
} catch (RemoteException e) {
Log.e(TAG, "Failed to mount OBB", e);
@@ -486,7 +491,11 @@ public class StorageManager
* @param filename path to OBB image
* @return true if OBB is mounted; false if not mounted or on error
*/
- public boolean isObbMounted(String filename) throws IllegalArgumentException {
+ public boolean isObbMounted(String filename) {
+ if (filename == null) {
+ throw new IllegalArgumentException("filename cannot be null");
+ }
+
try {
return mMountService.isObbMounted(filename);
} catch (RemoteException e) {
@@ -506,12 +515,14 @@ public class StorageManager
* not mounted or exception encountered trying to read status
*/
public String getMountedObbPath(String filename) {
+ if (filename == null) {
+ throw new IllegalArgumentException("filename cannot be null");
+ }
+
try {
return mMountService.getMountedObbPath(filename);
} catch (RemoteException e) {
Log.e(TAG, "Failed to find mounted path for OBB", e);
- } catch (IllegalArgumentException e) {
- Log.d(TAG, "Couldn't read OBB file", e);
}
return null;
diff --git a/core/tests/coretests/src/com/android/server/MountServiceTests.java b/core/tests/coretests/src/com/android/server/MountServiceTests.java
index 83e9d18..1f8c92e 100644
--- a/core/tests/coretests/src/com/android/server/MountServiceTests.java
+++ b/core/tests/coretests/src/com/android/server/MountServiceTests.java
@@ -21,7 +21,6 @@ import com.android.frameworks.coretests.R;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
-import android.os.Environment;
import android.os.FileUtils;
import android.os.storage.OnObbStateChangeListener;
import android.os.storage.StorageManager;
@@ -57,17 +56,15 @@ public class MountServiceTests extends AndroidTestCase {
}
}
- private interface CompletableTask {
- public boolean isDone();
- }
+ private static class ObbObserver extends OnObbStateChangeListener {
+ private String path;
- private static class ObbObserver extends OnObbStateChangeListener implements CompletableTask {
- public String path;
- public String state;
+ public int state = -1;
boolean done = false;
@Override
- public void onObbStateChange(String path, String state) {
+ public void onObbStateChange(String path, int state) {
+ Log.d(TAG, "Received message. path=" + path + ", state=" + state);
synchronized (this) {
this.path = path;
this.state = state;
@@ -76,32 +73,43 @@ public class MountServiceTests extends AndroidTestCase {
}
}
+ 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 = null;
+ this.state = -1;
done = false;
}
public boolean isDone() {
return done;
}
- }
- private boolean waitForCompletion(CompletableTask task) {
- long waitTime = 0;
- synchronized (task) {
- while (!task.isDone() && waitTime < MAX_WAIT_TIME) {
- try {
- task.wait(WAIT_TIME_INCR);
- waitTime += WAIT_TIME_INCR;
- } catch (InterruptedException e) {
- Log.i(TAG, "Interrupted during sleep", e);
+ 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 task.isDone();
+ return isDone();
+ }
}
+
private File getFilePath(String name) {
final File filesDir = mContext.getFilesDir();
final File outFile = new File(filesDir, name);
@@ -128,23 +136,52 @@ public class MountServiceTests extends AndroidTestCase {
}
private void mountObb(StorageManager sm, final int resource, final File file,
- String expectedState) {
+ int expectedState) {
copyRawToFile(resource, file);
- ObbObserver observer = new ObbObserver();
+ final ObbObserver observer = new ObbObserver();
assertTrue("mountObb call on " + file.getPath() + " should succeed",
sm.mountObb(file.getPath(), null, observer));
assertTrue("Mount should have completed",
- waitForCompletion(observer));
+ 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.path);
+ 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;
+ }
- assertEquals(expectedState, observer.state);
+ 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(StorageManager sm, File file) {
+ 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,
@@ -152,13 +189,21 @@ public class MountServiceTests extends AndroidTestCase {
return mountPath;
}
- private void unmountObb(StorageManager sm, final File outFile) {
- ObbObserver observer = new ObbObserver();
+ 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(outFile.getPath(), false, observer));
+ sm.unmountObb(file.getPath(),
+ false, observer));
assertTrue("Unmount should have completed",
- waitForCompletion(observer));
+ observer.waitForCompletion());
+
+ assertEquals(expectedState, observer.getState());
+
+ if (expectedState == OnObbStateChangeListener.UNMOUNTED) {
+ assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath()));
+ }
}
@LargeTest
@@ -167,7 +212,9 @@ public class MountServiceTests extends AndroidTestCase {
final File outFile = getFilePath("test1.obb");
- mountObb(sm, R.raw.test1, outFile, Environment.MEDIA_MOUNTED);
+ 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);
@@ -175,7 +222,7 @@ public class MountServiceTests extends AndroidTestCase {
assertTrue("OBB mounted path should be a directory",
mountDir.isDirectory());
- unmountObb(sm, outFile);
+ unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED);
}
@LargeTest
@@ -184,7 +231,7 @@ public class MountServiceTests extends AndroidTestCase {
final File outFile = getFilePath("test1_nosig.obb");
- mountObb(sm, R.raw.test1_nosig, outFile, Environment.MEDIA_BAD_REMOVAL);
+ mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
assertFalse("OBB should not be mounted",
sm.isObbMounted(outFile.getPath()));
@@ -199,7 +246,8 @@ public class MountServiceTests extends AndroidTestCase {
final File outFile = getFilePath("test1_wrongpackage.obb");
- mountObb(sm, R.raw.test1_wrongpackage, outFile, Environment.MEDIA_BAD_REMOVAL);
+ mountObb(sm, R.raw.test1_wrongpackage, outFile,
+ OnObbStateChangeListener.ERROR_PERMISSION_DENIED);
assertFalse("OBB should not be mounted",
sm.isObbMounted(outFile.getPath()));
@@ -207,4 +255,31 @@ public class MountServiceTests extends AndroidTestCase {
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);
+ }
}