Merge "OBB: rearrange to be entirely asynchronous" into gingerbread
This commit is contained in:
@@ -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;
|
||||
|
||||
/*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user