am b4de3dca: Merge "OBB: rearrange to be entirely asynchronous" into gingerbread

Merge commit 'b4de3dca96b9ff18562062e181dcd8b83e641e45' into gingerbread-plus-aosp

* commit 'b4de3dca96b9ff18562062e181dcd8b83e641e45':
  OBB: rearrange to be entirely asynchronous
This commit is contained in:
Kenny Root
2010-10-11 17:31:06 -07:00
committed by Android Git Automerger
13 changed files with 734 additions and 439 deletions

View File

@@ -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;
/*

View File

@@ -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;
}

View File

@@ -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) {
}
}

View File

@@ -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);
}
}
if (delegate != null) {
delegate.sendObbStateChanged(filename, status);
}
}
public void addListener(OnObbStateChangeListener listener) {
if (listener == null) {
return;
}
public int addListener(OnObbStateChangeListener listener) {
final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
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;
}
}
final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
mListeners.add(new WeakReference<ObbListenerDelegate>(delegate));
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;