am 05105f7a: Update OBB API to include callbacks
Merge commit '05105f7abe02b2dff91d6260b3628c8b97816bab' into gingerbread-plus-aosp * commit '05105f7abe02b2dff91d6260b3628c8b97816bab': Update OBB API to include callbacks
This commit is contained in:
148
api/current.xml
148
api/current.xml
@@ -52631,6 +52631,118 @@
|
|||||||
>
|
>
|
||||||
</field>
|
</field>
|
||||||
</class>
|
</class>
|
||||||
|
<class name="ObbInfo"
|
||||||
|
extends="java.lang.Object"
|
||||||
|
abstract="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
<implements name="android.os.Parcelable">
|
||||||
|
</implements>
|
||||||
|
<method name="describeContents"
|
||||||
|
return="int"
|
||||||
|
abstract="false"
|
||||||
|
native="false"
|
||||||
|
synchronized="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</method>
|
||||||
|
<method name="writeToParcel"
|
||||||
|
return="void"
|
||||||
|
abstract="false"
|
||||||
|
native="false"
|
||||||
|
synchronized="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
<parameter name="dest" type="android.os.Parcel">
|
||||||
|
</parameter>
|
||||||
|
<parameter name="parcelableFlags" type="int">
|
||||||
|
</parameter>
|
||||||
|
</method>
|
||||||
|
<field name="CREATOR"
|
||||||
|
type="android.os.Parcelable.Creator"
|
||||||
|
transient="false"
|
||||||
|
volatile="false"
|
||||||
|
static="true"
|
||||||
|
final="true"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</field>
|
||||||
|
<field name="OBB_OVERLAY"
|
||||||
|
type="int"
|
||||||
|
transient="false"
|
||||||
|
volatile="false"
|
||||||
|
value="1"
|
||||||
|
static="true"
|
||||||
|
final="true"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</field>
|
||||||
|
<field name="flags"
|
||||||
|
type="int"
|
||||||
|
transient="false"
|
||||||
|
volatile="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</field>
|
||||||
|
<field name="packageName"
|
||||||
|
type="java.lang.String"
|
||||||
|
transient="false"
|
||||||
|
volatile="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</field>
|
||||||
|
<field name="version"
|
||||||
|
type="int"
|
||||||
|
transient="false"
|
||||||
|
volatile="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</field>
|
||||||
|
</class>
|
||||||
|
<class name="ObbScanner"
|
||||||
|
extends="java.lang.Object"
|
||||||
|
abstract="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
<method name="getObbInfo"
|
||||||
|
return="android.content.res.ObbInfo"
|
||||||
|
abstract="false"
|
||||||
|
native="false"
|
||||||
|
synchronized="false"
|
||||||
|
static="true"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
<parameter name="filePath" type="java.lang.String">
|
||||||
|
</parameter>
|
||||||
|
<exception name="IOException" type="java.io.IOException">
|
||||||
|
</exception>
|
||||||
|
</method>
|
||||||
|
</class>
|
||||||
<class name="Resources"
|
<class name="Resources"
|
||||||
extends="java.lang.Object"
|
extends="java.lang.Object"
|
||||||
abstract="false"
|
abstract="false"
|
||||||
@@ -130689,6 +130801,38 @@
|
|||||||
</package>
|
</package>
|
||||||
<package name="android.os.storage"
|
<package name="android.os.storage"
|
||||||
>
|
>
|
||||||
|
<class name="OnObbStateChangeListener"
|
||||||
|
extends="java.lang.Object"
|
||||||
|
abstract="true"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
<constructor name="OnObbStateChangeListener"
|
||||||
|
type="android.os.storage.OnObbStateChangeListener"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
</constructor>
|
||||||
|
<method name="onObbStateChange"
|
||||||
|
return="void"
|
||||||
|
abstract="false"
|
||||||
|
native="false"
|
||||||
|
synchronized="false"
|
||||||
|
static="false"
|
||||||
|
final="false"
|
||||||
|
deprecated="not deprecated"
|
||||||
|
visibility="public"
|
||||||
|
>
|
||||||
|
<parameter name="path" type="java.lang.String">
|
||||||
|
</parameter>
|
||||||
|
<parameter name="state" type="java.lang.String">
|
||||||
|
</parameter>
|
||||||
|
</method>
|
||||||
|
</class>
|
||||||
<class name="StorageManager"
|
<class name="StorageManager"
|
||||||
extends="java.lang.Object"
|
extends="java.lang.Object"
|
||||||
abstract="false"
|
abstract="false"
|
||||||
@@ -130739,6 +130883,8 @@
|
|||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="key" type="java.lang.String">
|
<parameter name="key" type="java.lang.String">
|
||||||
</parameter>
|
</parameter>
|
||||||
|
<parameter name="listener" type="android.os.storage.OnObbStateChangeListener">
|
||||||
|
</parameter>
|
||||||
</method>
|
</method>
|
||||||
<method name="unmountObb"
|
<method name="unmountObb"
|
||||||
return="boolean"
|
return="boolean"
|
||||||
@@ -130754,6 +130900,8 @@
|
|||||||
</parameter>
|
</parameter>
|
||||||
<parameter name="force" type="boolean">
|
<parameter name="force" type="boolean">
|
||||||
</parameter>
|
</parameter>
|
||||||
|
<parameter name="listener" type="android.os.storage.OnObbStateChangeListener">
|
||||||
|
</parameter>
|
||||||
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
|
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
|
||||||
</exception>
|
</exception>
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import android.os.Parcel;
|
|||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic information about a Opaque Binary Blob (OBB) that reflects
|
* Basic information about a Opaque Binary Blob (OBB) that reflects the info
|
||||||
* the info from the footer on the OBB file.
|
* from the footer on the OBB file. This information may be manipulated by a
|
||||||
* @hide
|
* developer with the <code>obbtool</code> program in the Android SDK.
|
||||||
*/
|
*/
|
||||||
public class ObbInfo implements Parcelable {
|
public class ObbInfo implements Parcelable {
|
||||||
/** Flag noting that this OBB is an overlay patch for a base OBB. */
|
/** Flag noting that this OBB is an overlay patch for a base OBB. */
|
||||||
@@ -43,7 +43,8 @@ public class ObbInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public int flags;
|
public int flags;
|
||||||
|
|
||||||
public ObbInfo() {
|
// Only allow things in this package to instantiate.
|
||||||
|
/* package */ ObbInfo() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|||||||
@@ -16,25 +16,43 @@
|
|||||||
|
|
||||||
package android.content.res;
|
package android.content.res;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to scan Opaque Binary Blob (OBB) files.
|
* Class to scan Opaque Binary Blob (OBB) files. Use this to get information
|
||||||
* @hide
|
* about an OBB file for use in a program via {@link ObbInfo}.
|
||||||
*/
|
*/
|
||||||
public class ObbScanner {
|
public class ObbScanner {
|
||||||
// Don't allow others to instantiate this class
|
// Don't allow others to instantiate this class
|
||||||
private ObbScanner() {}
|
private ObbScanner() {}
|
||||||
|
|
||||||
public static ObbInfo getObbInfo(String filePath) {
|
/**
|
||||||
|
* Scan a file for OBB information.
|
||||||
|
*
|
||||||
|
* @param filePath path to the OBB file to be scanned.
|
||||||
|
* @return ObbInfo object information corresponding to the file path
|
||||||
|
* @throws IllegalArgumentException if the OBB file couldn't be found
|
||||||
|
* @throws IOException if the OBB file couldn't be read
|
||||||
|
*/
|
||||||
|
public static ObbInfo getObbInfo(String filePath) throws IOException {
|
||||||
if (filePath == null) {
|
if (filePath == null) {
|
||||||
return null;
|
throw new IllegalArgumentException("file path cannot be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
ObbInfo obbInfo = new ObbInfo();
|
final File obbFile = new File(filePath);
|
||||||
if (!getObbInfo_native(filePath, obbInfo)) {
|
if (!obbFile.exists()) {
|
||||||
throw new IllegalArgumentException("Could not read OBB file: " + filePath);
|
throw new IllegalArgumentException("OBB file does nto exist: " + filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final String canonicalFilePath = obbFile.getCanonicalPath();
|
||||||
|
|
||||||
|
ObbInfo obbInfo = new ObbInfo();
|
||||||
|
getObbInfo_native(canonicalFilePath, obbInfo);
|
||||||
|
|
||||||
return obbInfo;
|
return obbInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private native static boolean getObbInfo_native(String filePath, ObbInfo obbInfo);
|
private native static void getObbInfo_native(String filePath, ObbInfo obbInfo)
|
||||||
|
throws IOException;
|
||||||
}
|
}
|
||||||
|
|||||||
31
core/java/android/os/storage/OnObbStateChangeListener.java
Normal file
31
core/java/android/os/storage/OnObbStateChangeListener.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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 android.os.storage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for receiving notifications from {@link StorageManager}.
|
||||||
|
*/
|
||||||
|
public abstract class OnObbStateChangeListener {
|
||||||
|
/**
|
||||||
|
* 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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,13 +23,28 @@ import android.os.RemoteException;
|
|||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* StorageManager is the interface to the systems storage service.
|
* StorageManager is the interface to the systems storage service. The storage
|
||||||
|
* manager handles storage-related items such as Opaque Binary Blobs (OBBs).
|
||||||
|
* <p>
|
||||||
|
* OBBs contain a filesystem that maybe be encrypted on disk and mounted
|
||||||
|
* on-demand from an application. OBBs are a good way of providing large amounts
|
||||||
|
* of binary assets without packaging them into APKs as they may be multiple
|
||||||
|
* gigabytes in size. However, due to their size, they're most likely stored in
|
||||||
|
* a shared storage pool accessible from all programs. The system does not
|
||||||
|
* guarantee the security of the OBB file itself: if any program modifies the
|
||||||
|
* OBB, there is no guarantee that a read from that OBB will produce the
|
||||||
|
* expected output.
|
||||||
|
* <p>
|
||||||
* Get an instance of this class by calling
|
* Get an instance of this class by calling
|
||||||
* {@link android.content.Context#getSystemService(java.lang.String)} with an argument
|
* {@link android.content.Context#getSystemService(java.lang.String)} with an
|
||||||
* of {@link android.content.Context#STORAGE_SERVICE}.
|
* argument of {@link android.content.Context#STORAGE_SERVICE}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class StorageManager
|
public class StorageManager
|
||||||
@@ -75,11 +90,113 @@ public class StorageManager
|
|||||||
/**
|
/**
|
||||||
* Binder listener for OBB action results.
|
* Binder listener for OBB action results.
|
||||||
*/
|
*/
|
||||||
private final ObbActionBinderListener mObbActionListener = new ObbActionBinderListener();
|
private final ObbActionListener mObbActionListener = new ObbActionListener();
|
||||||
private class ObbActionBinderListener extends IObbActionListener.Stub {
|
|
||||||
|
private class ObbActionListener extends IObbActionListener.Stub {
|
||||||
|
private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onObbResult(String filename, String status) throws RemoteException {
|
public void onObbResult(String filename, String status) throws RemoteException {
|
||||||
Log.i(TAG, "filename = " + filename + ", result = " + 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate.sendObbStateChanged(filename, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListener(OnObbStateChangeListener listener) {
|
||||||
|
if (listener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private class containing sender and receiver code for StorageEvents.
|
||||||
|
*/
|
||||||
|
private class ObbListenerDelegate {
|
||||||
|
private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
|
||||||
|
private final Handler mHandler;
|
||||||
|
|
||||||
|
ObbListenerDelegate(OnObbStateChangeListener listener) {
|
||||||
|
mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
|
||||||
|
mHandler = new Handler(mTgtLooper) {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
final OnObbStateChangeListener listener = getListener();
|
||||||
|
if (listener == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StorageEvent e = (StorageEvent) msg.obj;
|
||||||
|
|
||||||
|
if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
|
||||||
|
ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
|
||||||
|
listener.onObbStateChange(ev.path, ev.state);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Unsupported event " + msg.what);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
OnObbStateChangeListener getListener() {
|
||||||
|
if (mObbEventListenerRef == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mObbEventListenerRef.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendObbStateChanged(String path, String state) {
|
||||||
|
ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
|
||||||
|
mHandler.sendMessage(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message sent during an OBB status change event.
|
||||||
|
*/
|
||||||
|
private class ObbStateChangedStorageEvent extends StorageEvent {
|
||||||
|
public final String path;
|
||||||
|
public final String state;
|
||||||
|
|
||||||
|
public ObbStateChangedStorageEvent(String path, String state) {
|
||||||
|
super(EVENT_OBB_STATE_CHANGED);
|
||||||
|
this.path = path;
|
||||||
|
this.state = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +205,9 @@ public class StorageManager
|
|||||||
* and the target looper handler.
|
* and the target looper handler.
|
||||||
*/
|
*/
|
||||||
private class StorageEvent {
|
private class StorageEvent {
|
||||||
public static final int EVENT_UMS_CONNECTION_CHANGED = 1;
|
static final int EVENT_UMS_CONNECTION_CHANGED = 1;
|
||||||
public static final int EVENT_STORAGE_STATE_CHANGED = 2;
|
static final int EVENT_STORAGE_STATE_CHANGED = 2;
|
||||||
|
static final int EVENT_OBB_STATE_CHANGED = 3;
|
||||||
|
|
||||||
private Message mMessage;
|
private Message mMessage;
|
||||||
|
|
||||||
@@ -300,19 +418,27 @@ public class StorageManager
|
|||||||
* specified, it is supplied to the mounting process to be used in any
|
* specified, it is supplied to the mounting process to be used in any
|
||||||
* encryption used in the OBB.
|
* encryption used in the OBB.
|
||||||
* <p>
|
* <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>.
|
||||||
|
* <p>
|
||||||
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
|
* <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.
|
* file matches a package ID that is owned by the calling program's UID.
|
||||||
* That is, shared UID applications can obtain access to any other
|
* That is, shared UID applications can attempt to mount any other
|
||||||
* application's OBB that shares its UID.
|
* application's OBB that shares its UID.
|
||||||
* <p>
|
|
||||||
* STOPSHIP document more; discuss lack of guarantees of security
|
|
||||||
*
|
*
|
||||||
* @param filename the path to the OBB file
|
* @param filename the path to the OBB file
|
||||||
* @param key decryption key
|
* @param key secret used to encrypt the OBB; may be <code>null</code> if no
|
||||||
|
* encryption was used on the OBB.
|
||||||
* @return whether the mount call was successfully queued or not
|
* @return whether the mount call was successfully queued or not
|
||||||
|
* @throws IllegalArgumentException when the OBB is already mounted
|
||||||
*/
|
*/
|
||||||
public boolean mountObb(String filename, String key) {
|
public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
|
||||||
try {
|
try {
|
||||||
|
mObbActionListener.addListener(listener);
|
||||||
mMountService.mountObb(filename, key, mObbActionListener);
|
mMountService.mountObb(filename, key, mObbActionListener);
|
||||||
return true;
|
return true;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -323,15 +449,20 @@ public class StorageManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unmount an Opaque Binary Blob (OBB) file. If the <code>force</code> flag
|
* Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
|
||||||
* is true, it will kill any application needed to unmount the given OBB.
|
* <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>.
|
||||||
* <p>
|
* <p>
|
||||||
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
|
* <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.
|
* file matches a package ID that is owned by the calling program's UID.
|
||||||
* That is, shared UID applications can obtain access to any other
|
* That is, shared UID applications can obtain access to any other
|
||||||
* application's OBB that shares its UID.
|
* application's OBB that shares its UID.
|
||||||
* <p>
|
* <p>
|
||||||
* STOPSHIP document more; discuss lack of guarantees of security
|
|
||||||
*
|
*
|
||||||
* @param filename path to the OBB file
|
* @param filename path to the OBB file
|
||||||
* @param force whether to kill any programs using this in order to unmount
|
* @param force whether to kill any programs using this in order to unmount
|
||||||
@@ -339,8 +470,10 @@ public class StorageManager
|
|||||||
* @return whether the unmount call was successfully queued or not
|
* @return whether the unmount call was successfully queued or not
|
||||||
* @throws IllegalArgumentException when OBB is not already mounted
|
* @throws IllegalArgumentException when OBB is not already mounted
|
||||||
*/
|
*/
|
||||||
public boolean unmountObb(String filename, boolean force) throws IllegalArgumentException {
|
public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener)
|
||||||
|
throws IllegalArgumentException {
|
||||||
try {
|
try {
|
||||||
|
mObbActionListener.addListener(listener);
|
||||||
mMountService.unmountObb(filename, force, mObbActionListener);
|
mMountService.unmountObb(filename, force, mObbActionListener);
|
||||||
return true;
|
return true;
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
|
|||||||
@@ -34,7 +34,17 @@ static struct {
|
|||||||
jfieldID flags;
|
jfieldID flags;
|
||||||
} gObbInfoClassInfo;
|
} gObbInfoClassInfo;
|
||||||
|
|
||||||
static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz, jstring file,
|
static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
|
||||||
|
{
|
||||||
|
jclass npeClazz;
|
||||||
|
|
||||||
|
npeClazz = env->FindClass(exc);
|
||||||
|
LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
|
||||||
|
|
||||||
|
env->ThrowNew(npeClazz, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz, jstring file,
|
||||||
jobject obbInfo)
|
jobject obbInfo)
|
||||||
{
|
{
|
||||||
const char* filePath = env->GetStringUTFChars(file, JNI_FALSE);
|
const char* filePath = env->GetStringUTFChars(file, JNI_FALSE);
|
||||||
@@ -42,7 +52,8 @@ static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject c
|
|||||||
sp<ObbFile> obb = new ObbFile();
|
sp<ObbFile> obb = new ObbFile();
|
||||||
if (!obb->readFrom(filePath)) {
|
if (!obb->readFrom(filePath)) {
|
||||||
env->ReleaseStringUTFChars(file, filePath);
|
env->ReleaseStringUTFChars(file, filePath);
|
||||||
return JNI_FALSE;
|
doThrow(env, "java/io/IOException", "Could not read OBB file");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
env->ReleaseStringUTFChars(file, filePath);
|
env->ReleaseStringUTFChars(file, filePath);
|
||||||
@@ -51,13 +62,13 @@ static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject c
|
|||||||
|
|
||||||
jstring packageName = env->NewStringUTF(packageNameStr);
|
jstring packageName = env->NewStringUTF(packageNameStr);
|
||||||
if (packageName == NULL) {
|
if (packageName == NULL) {
|
||||||
return JNI_FALSE;
|
doThrow(env, "java/io/IOException", "Could not read OBB file");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
env->SetObjectField(obbInfo, gObbInfoClassInfo.packageName, packageName);
|
env->SetObjectField(obbInfo, gObbInfoClassInfo.packageName, packageName);
|
||||||
env->SetIntField(obbInfo, gObbInfoClassInfo.version, obb->getVersion());
|
env->SetIntField(obbInfo, gObbInfoClassInfo.version, obb->getVersion());
|
||||||
|
env->SetIntField(obbInfo, gObbInfoClassInfo.flags, obb->getFlags());
|
||||||
return JNI_TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -65,7 +76,7 @@ static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject c
|
|||||||
*/
|
*/
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
/* name, signature, funcPtr */
|
/* name, signature, funcPtr */
|
||||||
{ "getObbInfo_native", "(Ljava/lang/String;Landroid/content/res/ObbInfo;)Z",
|
{ "getObbInfo_native", "(Ljava/lang/String;Landroid/content/res/ObbInfo;)V",
|
||||||
(void*) android_content_res_ObbScanner_getObbInfo },
|
(void*) android_content_res_ObbScanner_getObbInfo },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ public:
|
|||||||
virtual void finishMediaUpdate() = 0;
|
virtual void finishMediaUpdate() = 0;
|
||||||
virtual void mountObb(const String16& filename, const String16& key,
|
virtual void mountObb(const String16& filename, const String16& key,
|
||||||
const sp<IObbActionListener>& token) = 0;
|
const sp<IObbActionListener>& token) = 0;
|
||||||
virtual void unmountObb(const String16& filename, const bool force) = 0;
|
virtual void unmountObb(const String16& filename, const bool force,
|
||||||
|
const sp<IObbActionListener>& token) = 0;
|
||||||
virtual bool isObbMounted(const String16& filename) = 0;
|
virtual bool isObbMounted(const String16& filename) = 0;
|
||||||
virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
|
virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -429,8 +429,8 @@ public:
|
|||||||
reply.readExceptionCode();
|
reply.readExceptionCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mountObb(const String16& filename, const String16& key, const sp<
|
void mountObb(const String16& filename, const String16& key,
|
||||||
IObbActionListener>& token)
|
const sp<IObbActionListener>& token)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
|
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
|
||||||
@@ -448,7 +448,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmountObb(const String16& filename, const bool force)
|
void unmountObb(const String16& filename, const bool force, const sp<IObbActionListener>& token)
|
||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
|
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ LOCAL_SRC_FILES:= \
|
|||||||
looper.cpp \
|
looper.cpp \
|
||||||
native_activity.cpp \
|
native_activity.cpp \
|
||||||
native_window.cpp \
|
native_window.cpp \
|
||||||
|
obb.cpp \
|
||||||
sensor.cpp \
|
sensor.cpp \
|
||||||
storage_manager.cpp
|
storage_manager.cpp
|
||||||
|
|
||||||
|
|||||||
54
native/android/obb.cpp
Normal file
54
native/android/obb.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "NObb"
|
||||||
|
|
||||||
|
#include <android/obb.h>
|
||||||
|
|
||||||
|
#include <utils/Log.h>
|
||||||
|
#include <utils/ObbFile.h>
|
||||||
|
|
||||||
|
using namespace android;
|
||||||
|
|
||||||
|
struct AObbInfo : public ObbFile {};
|
||||||
|
|
||||||
|
AObbInfo* AObbScanner_getObbInfo(const char* filename) {
|
||||||
|
AObbInfo* obbFile = new AObbInfo();
|
||||||
|
if (obbFile == NULL || !obbFile->readFrom(filename)) {
|
||||||
|
delete obbFile;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
obbFile->incStrong((void*)AObbScanner_getObbInfo);
|
||||||
|
return static_cast<AObbInfo*>(obbFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AObbInfo_delete(AObbInfo* obbInfo) {
|
||||||
|
if (obbInfo != NULL) {
|
||||||
|
obbInfo->decStrong((void*)AObbScanner_getObbInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* AObbInfo_getPackageName(AObbInfo* obbInfo) {
|
||||||
|
return obbInfo->getPackageName();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t AObbInfo_getVersion(AObbInfo* obbInfo) {
|
||||||
|
return obbInfo->getVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t AObbInfo_getFlags(AObbInfo* obbInfo) {
|
||||||
|
return obbInfo->getFlags();
|
||||||
|
}
|
||||||
@@ -38,20 +38,20 @@ public:
|
|||||||
mStorageManager(mgr)
|
mStorageManager(mgr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void onObbResult(const android::String16& filename, const android::String16& state) {
|
virtual void onObbResult(const android::String16& filename, const android::String16& state);
|
||||||
LOGD("Got obb result (%s, %s)\n", String8(filename).string(), String8(state).string());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AStorageManager : public RefBase {
|
struct AStorageManager : public RefBase {
|
||||||
protected:
|
protected:
|
||||||
void* mObbCallback;
|
AStorageManager_obbCallbackFunc mObbCallback;
|
||||||
|
void* mObbCallbackData;
|
||||||
sp<ObbActionListener> mObbActionListener;
|
sp<ObbActionListener> mObbActionListener;
|
||||||
sp<IMountService> mMountService;
|
sp<IMountService> mMountService;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AStorageManager() :
|
AStorageManager()
|
||||||
mObbCallback(NULL)
|
: mObbCallback(NULL)
|
||||||
|
, mObbCallbackData(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +73,15 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setObbCallback(void* cb) {
|
void setObbCallback(AStorageManager_obbCallbackFunc cb, void* data) {
|
||||||
mObbCallback = cb;
|
mObbCallback = cb;
|
||||||
|
mObbCallbackData = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fireCallback(const char* filename, const char* state) {
|
||||||
|
if (mObbCallback != NULL) {
|
||||||
|
mObbCallback(filename, state, mObbCallbackData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mountObb(const char* filename, const char* key) {
|
void mountObb(const char* filename, const char* key) {
|
||||||
@@ -85,7 +92,7 @@ public:
|
|||||||
|
|
||||||
void unmountObb(const char* filename, const bool force) {
|
void unmountObb(const char* filename, const bool force) {
|
||||||
String16 filename16(filename);
|
String16 filename16(filename);
|
||||||
mMountService->unmountObb(filename16, force);
|
mMountService->unmountObb(filename16, force, mObbActionListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
int isObbMounted(const char* filename) {
|
int isObbMounted(const char* filename) {
|
||||||
@@ -104,6 +111,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void ObbActionListener::onObbResult(const android::String16& filename, const android::String16& state) {
|
||||||
|
mStorageManager->fireCallback(String8(filename).string(), String8(state).string());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AStorageManager* AStorageManager_new() {
|
AStorageManager* AStorageManager_new() {
|
||||||
sp<AStorageManager> mgr = new AStorageManager();
|
sp<AStorageManager> mgr = new AStorageManager();
|
||||||
@@ -120,8 +131,8 @@ void AStorageManager_delete(AStorageManager* mgr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStorageManager_setObbCallback(AStorageManager* mgr, void* cb) {
|
void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data) {
|
||||||
mgr->setObbCallback(cb);
|
mgr->setObbCallback(cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key) {
|
void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key) {
|
||||||
|
|||||||
63
native/include/android/obb.h
Normal file
63
native/include/android/obb.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ANDROID_OBB_H
|
||||||
|
#define ANDROID_OBB_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct AObbInfo;
|
||||||
|
typedef struct AObbInfo AObbInfo;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AOBBINFO_OVERLAY = 0x0001,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan an OBB and get information about it.
|
||||||
|
*/
|
||||||
|
AObbInfo* AObbScanner_getObbInfo(const char* filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the AObbInfo object. You must call this when finished with the object.
|
||||||
|
*/
|
||||||
|
void AObbInfo_delete(AObbInfo* obbInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the package name for the OBB.
|
||||||
|
*/
|
||||||
|
const char* AObbInfo_getPackageName(AObbInfo* obbInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the version of an OBB file.
|
||||||
|
*/
|
||||||
|
int32_t AObbInfo_getVersion(AObbInfo* obbInfo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the flags of an OBB file.
|
||||||
|
*/
|
||||||
|
int32_t AObbInfo_getFlags(AObbInfo* obbInfo);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // ANDROID_OBB_H
|
||||||
@@ -37,17 +37,22 @@ AStorageManager* AStorageManager_new();
|
|||||||
void AStorageManager_delete(AStorageManager* mgr);
|
void AStorageManager_delete(AStorageManager* mgr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback to call when requested OBB is complete.
|
* Callback function for asynchronous calls made on OBB files.
|
||||||
*/
|
*/
|
||||||
void AStorageManager_setObbCallback(AStorageManager* mgr, void* cb);
|
typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const char* state, void* data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to mount an OBB file.
|
* Callback to call when requested asynchronous OBB operation is complete.
|
||||||
|
*/
|
||||||
|
void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to mount an OBB file. This is an asynchronous operation.
|
||||||
*/
|
*/
|
||||||
void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key);
|
void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to unmount an OBB file.
|
* Attempts to unmount an OBB file. This is an asynchronous operation.
|
||||||
*/
|
*/
|
||||||
void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force);
|
void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force);
|
||||||
|
|
||||||
@@ -66,4 +71,4 @@ const char* AStorageManager_getMountedObbPath(AStorageManager* mgr, const char*
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // ANDROID_PACKAGE_MANAGER_H
|
#endif // ANDROID_STORAGE_MANAGER_H
|
||||||
|
|||||||
@@ -156,7 +156,12 @@ public class DefaultContainerService extends IntentService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ObbInfo getObbInfo(String filename) {
|
public ObbInfo getObbInfo(String filename) {
|
||||||
|
try {
|
||||||
return ObbScanner.getObbInfo(filename);
|
return ObbScanner.getObbInfo(filename);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(TAG, "Couldn't get OBB info", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import android.os.storage.IObbActionListener;
|
|||||||
import android.os.storage.StorageResultCode;
|
import android.os.storage.StorageResultCode;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -148,7 +149,7 @@ class MountService extends IMountService.Stub
|
|||||||
* Mounted OBB tracking information. Used to track the current state of all
|
* Mounted OBB tracking information. Used to track the current state of all
|
||||||
* OBBs.
|
* OBBs.
|
||||||
*/
|
*/
|
||||||
final private Map<IObbActionListener, ObbState> mObbMounts = new HashMap<IObbActionListener, ObbState>();
|
final private Map<IObbActionListener, List<ObbState>> mObbMounts = new HashMap<IObbActionListener, List<ObbState>>();
|
||||||
final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
|
final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
|
||||||
|
|
||||||
class ObbState implements IBinder.DeathRecipient {
|
class ObbState implements IBinder.DeathRecipient {
|
||||||
@@ -160,13 +161,13 @@ class MountService extends IMountService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
// OBB source filename
|
// OBB source filename
|
||||||
String filename;
|
final String filename;
|
||||||
|
|
||||||
// Token of remote Binder caller
|
// Token of remote Binder caller
|
||||||
IObbActionListener token;
|
final IObbActionListener token;
|
||||||
|
|
||||||
// Binder.callingUid()
|
// Binder.callingUid()
|
||||||
public int callerUid;
|
final public int callerUid;
|
||||||
|
|
||||||
// Whether this is mounted currently.
|
// Whether this is mounted currently.
|
||||||
boolean mounted;
|
boolean mounted;
|
||||||
@@ -225,9 +226,9 @@ class MountService extends IMountService.Stub
|
|||||||
private static final int MAX_UNMOUNT_RETRIES = 4;
|
private static final int MAX_UNMOUNT_RETRIES = 4;
|
||||||
|
|
||||||
class UnmountCallBack {
|
class UnmountCallBack {
|
||||||
String path;
|
final String path;
|
||||||
|
final boolean force;
|
||||||
int retries;
|
int retries;
|
||||||
boolean force;
|
|
||||||
|
|
||||||
UnmountCallBack(String path, boolean force) {
|
UnmountCallBack(String path, boolean force) {
|
||||||
retries = 0;
|
retries = 0;
|
||||||
@@ -242,7 +243,7 @@ class MountService extends IMountService.Stub
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UmsEnableCallBack extends UnmountCallBack {
|
class UmsEnableCallBack extends UnmountCallBack {
|
||||||
String method;
|
final String method;
|
||||||
|
|
||||||
UmsEnableCallBack(String path, String method, boolean force) {
|
UmsEnableCallBack(String path, String method, boolean force) {
|
||||||
super(path, force);
|
super(path, force);
|
||||||
@@ -1513,10 +1514,6 @@ class MountService extends IMountService.Stub
|
|||||||
throw new IllegalArgumentException("OBB file is already mounted");
|
throw new IllegalArgumentException("OBB file is already mounted");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mObbMounts.containsKey(token)) {
|
|
||||||
throw new IllegalArgumentException("You may only have one OBB mounted at a time");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int callerUid = Binder.getCallingUid();
|
final int callerUid = Binder.getCallingUid();
|
||||||
obbState = new ObbState(filename, token, callerUid);
|
obbState = new ObbState(filename, token, callerUid);
|
||||||
addObbState(obbState);
|
addObbState(obbState);
|
||||||
@@ -1554,14 +1551,25 @@ class MountService extends IMountService.Stub
|
|||||||
|
|
||||||
private void addObbState(ObbState obbState) {
|
private void addObbState(ObbState obbState) {
|
||||||
synchronized (mObbMounts) {
|
synchronized (mObbMounts) {
|
||||||
mObbMounts.put(obbState.token, obbState);
|
List<ObbState> obbStates = mObbMounts.get(obbState.token);
|
||||||
|
if (obbStates == null) {
|
||||||
|
obbStates = new ArrayList<ObbState>();
|
||||||
|
mObbMounts.put(obbState.token, obbStates);
|
||||||
|
}
|
||||||
|
obbStates.add(obbState);
|
||||||
mObbPathToStateMap.put(obbState.filename, obbState);
|
mObbPathToStateMap.put(obbState.filename, obbState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeObbState(ObbState obbState) {
|
private void removeObbState(ObbState obbState) {
|
||||||
synchronized (mObbMounts) {
|
synchronized (mObbMounts) {
|
||||||
|
final List<ObbState> obbStates = mObbMounts.get(obbState.token);
|
||||||
|
if (obbStates != null) {
|
||||||
|
obbStates.remove(obbState);
|
||||||
|
}
|
||||||
|
if (obbStates == null || obbStates.isEmpty()) {
|
||||||
mObbMounts.remove(obbState.token);
|
mObbMounts.remove(obbState.token);
|
||||||
|
}
|
||||||
mObbPathToStateMap.remove(obbState.filename);
|
mObbPathToStateMap.remove(obbState.filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1737,7 +1745,7 @@ class MountService extends IMountService.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void handleExecute() throws RemoteException;
|
abstract void handleExecute() throws RemoteException, IOException;
|
||||||
abstract void handleError();
|
abstract void handleError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1749,8 +1757,12 @@ class MountService extends IMountService.Stub
|
|||||||
mKey = key;
|
mKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleExecute() throws RemoteException {
|
public void handleExecute() throws RemoteException, IOException {
|
||||||
ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename);
|
ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename);
|
||||||
|
if (obbInfo == null) {
|
||||||
|
throw new IOException("Couldn't read OBB file");
|
||||||
|
}
|
||||||
|
|
||||||
if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) {
|
if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) {
|
||||||
throw new IllegalArgumentException("Caller package does not match OBB file");
|
throw new IllegalArgumentException("Caller package does not match OBB file");
|
||||||
}
|
}
|
||||||
@@ -1773,15 +1785,17 @@ class MountService extends IMountService.Stub
|
|||||||
|
|
||||||
if (rc == StorageResultCode.OperationSucceeded) {
|
if (rc == StorageResultCode.OperationSucceeded) {
|
||||||
try {
|
try {
|
||||||
mObbState.token.onObbResult(mObbState.filename, "mounted");
|
mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_MOUNTED);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
|
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "Couldn't mount OBB file");
|
Slog.e(TAG, "Couldn't mount OBB file: " + rc);
|
||||||
|
|
||||||
// We didn't succeed, so remove this from the mount-set.
|
// We didn't succeed, so remove this from the mount-set.
|
||||||
removeObbState(mObbState);
|
removeObbState(mObbState);
|
||||||
|
|
||||||
|
mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1789,7 +1803,7 @@ class MountService extends IMountService.Stub
|
|||||||
removeObbState(mObbState);
|
removeObbState(mObbState);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mObbState.token.onObbResult(mObbState.filename, "error");
|
mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.e(TAG, "Couldn't send back OBB mount error for " + mObbState.filename);
|
Slog.e(TAG, "Couldn't send back OBB mount error for " + mObbState.filename);
|
||||||
}
|
}
|
||||||
@@ -1818,8 +1832,11 @@ class MountService extends IMountService.Stub
|
|||||||
mForceUnmount = force;
|
mForceUnmount = force;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handleExecute() throws RemoteException {
|
public void handleExecute() throws RemoteException, IOException {
|
||||||
ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename);
|
ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename);
|
||||||
|
if (obbInfo == null) {
|
||||||
|
throw new IOException("Couldn't read OBB file");
|
||||||
|
}
|
||||||
|
|
||||||
if (!isCallerOwnerOfPackageOrSystem(obbInfo.packageName)) {
|
if (!isCallerOwnerOfPackageOrSystem(obbInfo.packageName)) {
|
||||||
throw new IllegalArgumentException("Caller package does not match OBB file");
|
throw new IllegalArgumentException("Caller package does not match OBB file");
|
||||||
@@ -1843,13 +1860,13 @@ class MountService extends IMountService.Stub
|
|||||||
removeObbState(mObbState);
|
removeObbState(mObbState);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mObbState.token.onObbResult(mObbState.filename, "unmounted");
|
mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_UNMOUNTED);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
|
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
mObbState.token.onObbResult(mObbState.filename, "error");
|
mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
|
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
|
||||||
}
|
}
|
||||||
@@ -1860,7 +1877,7 @@ class MountService extends IMountService.Stub
|
|||||||
removeObbState(mObbState);
|
removeObbState(mObbState);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mObbState.token.onObbResult(mObbState.filename, "error");
|
mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.e(TAG, "Couldn't send back OBB unmount error for " + mObbState.filename);
|
Slog.e(TAG, "Couldn't send back OBB unmount error for " + mObbState.filename);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user