diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/os/Environment.java | 22 | ||||
-rw-r--r-- | core/java/android/os/storage/IMountService.java | 41 | ||||
-rw-r--r-- | core/java/android/os/storage/StorageManager.java | 57 | ||||
-rw-r--r-- | core/tests/coretests/res/raw/test1.obb | bin | 37440 -> 0 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/test1_nosig.obb | bin | 37376 -> 0 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/test1_wrongpackage.obb | bin | 37431 -> 0 bytes | |||
-rw-r--r-- | core/tests/coretests/src/com/android/server/MountServiceTests.java | 285 |
7 files changed, 68 insertions, 337 deletions
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 5c4c036..3315566 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -31,6 +31,7 @@ public class Environment { private static final String TAG = "Environment"; private static final String ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE"; + private static final String ENV_EMULATED_STORAGE_SOURCE = "EMULATED_STORAGE_SOURCE"; private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"; private static final String ENV_MEDIA_STORAGE = "MEDIA_STORAGE"; @@ -134,6 +135,10 @@ public class Environment { return mExternalStorage; } + public File getExternalStorageObbDirectory() { + return mExternalStorageAndroidObb; + } + public File getExternalStoragePublicDirectory(String type) { return new File(mExternalStorage, type); } @@ -302,6 +307,23 @@ public class Environment { return new File(System.getenv(ENV_EXTERNAL_STORAGE)); } + /** {@hide} */ + public static File getLegacyExternalStorageObbDirectory() { + return buildPath(getLegacyExternalStorageDirectory(), DIRECTORY_ANDROID, "obb"); + } + + /** {@hide} */ + public static File getEmulatedStorageSource(int userId) { + // /mnt/shell/emulated/0 + return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), String.valueOf(userId)); + } + + /** {@hide} */ + public static File getEmulatedStorageObbSource() { + // /mnt/shell/emulated/obb + return new File(System.getenv(ENV_EMULATED_STORAGE_SOURCE), "obb"); + } + /** * Standard directory in which to place any audio files that should be * in the regular list of music for the user. diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java index 0b16316..fc18617 100644 --- a/core/java/android/os/storage/IMountService.java +++ b/core/java/android/os/storage/IMountService.java @@ -489,13 +489,14 @@ 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, int nonce) - throws RemoteException { + public void mountObb(String rawPath, String canonicalPath, String key, + IObbActionListener token, int nonce) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(filename); + _data.writeString(rawPath); + _data.writeString(canonicalPath); _data.writeString(key); _data.writeStrongBinder((token != null ? token.asBinder() : null)); _data.writeInt(nonce); @@ -514,13 +515,14 @@ 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, - int nonce) throws RemoteException { + public void unmountObb( + String rawPath, boolean force, IObbActionListener token, int nonce) + throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(filename); + _data.writeString(rawPath); _data.writeInt((force ? 1 : 0)); _data.writeStrongBinder((token != null ? token.asBinder() : null)); _data.writeInt(nonce); @@ -536,13 +538,13 @@ public interface IMountService extends IInterface { * Checks whether the specified Opaque Binary Blob (OBB) is mounted * somewhere. */ - public boolean isObbMounted(String filename) throws RemoteException { + public boolean isObbMounted(String rawPath) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); boolean _result; try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(filename); + _data.writeString(rawPath); mRemote.transact(Stub.TRANSACTION_isObbMounted, _data, _reply, 0); _reply.readException(); _result = 0 != _reply.readInt(); @@ -556,13 +558,13 @@ public interface IMountService extends IInterface { /** * Gets the path to the mounted Opaque Binary Blob (OBB). */ - public String getMountedObbPath(String filename) throws RemoteException { + public String getMountedObbPath(String rawPath) throws RemoteException { Parcel _data = Parcel.obtain(); Parcel _reply = Parcel.obtain(); String _result; try { _data.writeInterfaceToken(DESCRIPTOR); - _data.writeString(filename); + _data.writeString(rawPath); mRemote.transact(Stub.TRANSACTION_getMountedObbPath, _data, _reply, 0); _reply.readException(); _result = _reply.readString(); @@ -1042,15 +1044,14 @@ public interface IMountService extends IInterface { } case TRANSACTION_mountObb: { data.enforceInterface(DESCRIPTOR); - String filename; - filename = data.readString(); - String key; - key = data.readString(); + final String rawPath = data.readString(); + final String canonicalPath = data.readString(); + final String key = data.readString(); IObbActionListener observer; observer = IObbActionListener.Stub.asInterface(data.readStrongBinder()); int nonce; nonce = data.readInt(); - mountObb(filename, key, observer, nonce); + mountObb(rawPath, canonicalPath, key, observer, nonce); reply.writeNoException(); return true; } @@ -1194,7 +1195,7 @@ public interface IMountService extends IInterface { /** * Gets the path to the mounted Opaque Binary Blob (OBB). */ - public String getMountedObbPath(String filename) throws RemoteException; + public String getMountedObbPath(String rawPath) throws RemoteException; /** * Gets an Array of currently known secure container IDs @@ -1220,7 +1221,7 @@ public interface IMountService extends IInterface { * Checks whether the specified Opaque Binary Blob (OBB) is mounted * somewhere. */ - public boolean isObbMounted(String filename) throws RemoteException; + public boolean isObbMounted(String rawPath) throws RemoteException; /* * Returns true if the specified container is mounted @@ -1243,8 +1244,8 @@ 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, int nonce) - throws RemoteException; + public void mountObb(String rawPath, String canonicalPath, String key, + IObbActionListener token, int nonce) throws RemoteException; /* * Mount a secure container with the specified key and owner UID. Returns an @@ -1287,7 +1288,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, int nonce) + public void unmountObb(String rawPath, boolean force, IObbActionListener token, int nonce) throws RemoteException; /* diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java index 54c8709..862a95c 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -28,6 +28,10 @@ import android.os.ServiceManager; import android.util.Log; import android.util.SparseArray; +import com.android.internal.util.Preconditions; + +import java.io.File; +import java.io.IOException; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -443,25 +447,23 @@ public class StorageManager * That is, shared UID applications can attempt to mount any other * application's OBB that shares its UID. * - * @param filename the path to the OBB file + * @param rawPath 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"); - } + public boolean mountObb(String rawPath, String key, OnObbStateChangeListener listener) { + Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Preconditions.checkNotNull(listener, "listener cannot be null"); try { + final String canonicalPath = new File(rawPath).getCanonicalPath(); final int nonce = mObbActionListener.addListener(listener); - mMountService.mountObb(filename, key, mObbActionListener, nonce); + mMountService.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce); return true; + } catch (IOException e) { + throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e); } catch (RemoteException e) { Log.e(TAG, "Failed to mount OBB", e); } @@ -483,24 +485,19 @@ public class StorageManager * application's OBB that shares its UID. * <p> * - * @param filename path to the OBB file + * @param rawPath 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"); - } + public boolean unmountObb(String rawPath, boolean force, OnObbStateChangeListener listener) { + Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); + Preconditions.checkNotNull(listener, "listener cannot be null"); try { final int nonce = mObbActionListener.addListener(listener); - mMountService.unmountObb(filename, force, mObbActionListener, nonce); + mMountService.unmountObb(rawPath, force, mObbActionListener, nonce); return true; } catch (RemoteException e) { Log.e(TAG, "Failed to mount OBB", e); @@ -512,16 +509,14 @@ public class StorageManager /** * Check whether an Opaque Binary Blob (OBB) is mounted or not. * - * @param filename path to OBB image + * @param rawPath path to OBB image * @return true if OBB is mounted; false if not mounted or on error */ - public boolean isObbMounted(String filename) { - if (filename == null) { - throw new IllegalArgumentException("filename cannot be null"); - } + public boolean isObbMounted(String rawPath) { + Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); try { - return mMountService.isObbMounted(filename); + return mMountService.isObbMounted(rawPath); } catch (RemoteException e) { Log.e(TAG, "Failed to check if OBB is mounted", e); } @@ -534,17 +529,15 @@ public class StorageManager * give you the path to where you can obtain access to the internals of the * OBB. * - * @param filename path to OBB image + * @param rawPath path to OBB image * @return absolute path to mounted OBB image data or <code>null</code> if * not mounted or exception encountered trying to read status */ - public String getMountedObbPath(String filename) { - if (filename == null) { - throw new IllegalArgumentException("filename cannot be null"); - } + public String getMountedObbPath(String rawPath) { + Preconditions.checkNotNull(rawPath, "rawPath cannot be null"); try { - return mMountService.getMountedObbPath(filename); + return mMountService.getMountedObbPath(rawPath); } catch (RemoteException e) { Log.e(TAG, "Failed to find mounted path for OBB", e); } diff --git a/core/tests/coretests/res/raw/test1.obb b/core/tests/coretests/res/raw/test1.obb Binary files differdeleted file mode 100644 index 8466588..0000000 --- a/core/tests/coretests/res/raw/test1.obb +++ /dev/null diff --git a/core/tests/coretests/res/raw/test1_nosig.obb b/core/tests/coretests/res/raw/test1_nosig.obb Binary files differdeleted file mode 100644 index 5c3573f7..0000000 --- a/core/tests/coretests/res/raw/test1_nosig.obb +++ /dev/null diff --git a/core/tests/coretests/res/raw/test1_wrongpackage.obb b/core/tests/coretests/res/raw/test1_wrongpackage.obb Binary files differdeleted file mode 100644 index d0aafe1..0000000 --- a/core/tests/coretests/res/raw/test1_wrongpackage.obb +++ /dev/null diff --git a/core/tests/coretests/src/com/android/server/MountServiceTests.java b/core/tests/coretests/src/com/android/server/MountServiceTests.java deleted file mode 100644 index 1f8c92e..0000000 --- a/core/tests/coretests/src/com/android/server/MountServiceTests.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import com.android.frameworks.coretests.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.Resources.NotFoundException; -import android.os.FileUtils; -import android.os.storage.OnObbStateChangeListener; -import android.os.storage.StorageManager; -import android.test.AndroidTestCase; -import android.test.ComparisonFailure; -import android.test.suitebuilder.annotation.LargeTest; -import android.util.Log; - -import java.io.File; -import java.io.InputStream; - -public class MountServiceTests extends AndroidTestCase { - private static final String TAG = "MountServiceTests"; - - private static final long MAX_WAIT_TIME = 25*1000; - private static final long WAIT_TIME_INCR = 5*1000; - - private static final String OBB_MOUNT_PREFIX = "/mnt/obb/"; - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - private static void assertStartsWith(String message, String prefix, String actual) { - if (!actual.startsWith(prefix)) { - throw new ComparisonFailure(message, prefix, actual); - } - } - - private static class ObbObserver extends OnObbStateChangeListener { - private String path; - - public int state = -1; - boolean done = false; - - @Override - public void onObbStateChange(String path, int state) { - Log.d(TAG, "Received message. path=" + path + ", state=" + state); - synchronized (this) { - this.path = path; - this.state = state; - done = true; - notifyAll(); - } - } - - public String getPath() { - assertTrue("Expected ObbObserver to have received a state change.", done); - return path; - } - - public int getState() { - assertTrue("Expected ObbObserver to have received a state change.", done); - return state; - } - - public void reset() { - this.path = null; - this.state = -1; - done = false; - } - - public boolean isDone() { - return done; - } - - public boolean waitForCompletion() { - long waitTime = 0; - synchronized (this) { - while (!isDone() && waitTime < MAX_WAIT_TIME) { - try { - wait(WAIT_TIME_INCR); - waitTime += WAIT_TIME_INCR; - } catch (InterruptedException e) { - Log.i(TAG, "Interrupted during sleep", e); - } - } - } - - return isDone(); - } - } - - private File getFilePath(String name) { - final File filesDir = mContext.getFilesDir(); - final File outFile = new File(filesDir, name); - return outFile; - } - - private void copyRawToFile(int rawResId, File outFile) { - Resources res = mContext.getResources(); - InputStream is = null; - try { - is = res.openRawResource(rawResId); - } catch (NotFoundException e) { - fail("Failed to load resource with id: " + rawResId); - } - FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG - | FileUtils.S_IRWXO, -1, -1); - assertTrue(FileUtils.copyToFile(is, outFile)); - FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG - | FileUtils.S_IRWXO, -1, -1); - } - - private StorageManager getStorageManager() { - return (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE); - } - - private void mountObb(StorageManager sm, final int resource, final File file, - int expectedState) { - copyRawToFile(resource, file); - - final ObbObserver observer = new ObbObserver(); - assertTrue("mountObb call on " + file.getPath() + " should succeed", - sm.mountObb(file.getPath(), null, observer)); - - assertTrue("Mount should have completed", - observer.waitForCompletion()); - - if (expectedState == OnObbStateChangeListener.MOUNTED) { - assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath())); - } - - assertEquals("Actual file and resolved file should be the same", - file.getPath(), observer.getPath()); - - assertEquals(expectedState, observer.getState()); - } - - private ObbObserver mountObbWithoutWait(final StorageManager sm, final int resource, - final File file) { - copyRawToFile(resource, file); - - final ObbObserver observer = new ObbObserver(); - assertTrue("mountObb call on " + file.getPath() + " should succeed", sm.mountObb(file - .getPath(), null, observer)); - - return observer; - } - - private void waitForObbActionCompletion(final StorageManager sm, final File file, - final ObbObserver observer, int expectedState, boolean checkPath) { - assertTrue("Mount should have completed", observer.waitForCompletion()); - - assertTrue("OBB should be mounted", sm.isObbMounted(file.getPath())); - - if (checkPath) { - assertEquals("Actual file and resolved file should be the same", file.getPath(), - observer.getPath()); - } - - assertEquals(expectedState, observer.getState()); - } - - private String checkMountedPath(final StorageManager sm, final File file) { - final String mountPath = sm.getMountedObbPath(file.getPath()); - assertStartsWith("Path should be in " + OBB_MOUNT_PREFIX, - OBB_MOUNT_PREFIX, - mountPath); - return mountPath; - } - - private void unmountObb(final StorageManager sm, final File file, int expectedState) { - final ObbObserver observer = new ObbObserver(); - - assertTrue("unmountObb call on test1.obb should succeed", - sm.unmountObb(file.getPath(), - false, observer)); - - assertTrue("Unmount should have completed", - observer.waitForCompletion()); - - assertEquals(expectedState, observer.getState()); - - if (expectedState == OnObbStateChangeListener.UNMOUNTED) { - assertFalse("OBB should not be mounted", sm.isObbMounted(file.getPath())); - } - } - - @LargeTest - public void testMountAndUnmountObbNormal() { - StorageManager sm = getStorageManager(); - - final File outFile = getFilePath("test1.obb"); - - mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.MOUNTED); - - mountObb(sm, R.raw.test1, outFile, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED); - - final String mountPath = checkMountedPath(sm, outFile); - final File mountDir = new File(mountPath); - - assertTrue("OBB mounted path should be a directory", - mountDir.isDirectory()); - - unmountObb(sm, outFile, OnObbStateChangeListener.UNMOUNTED); - } - - @LargeTest - public void testAttemptMountNonObb() { - StorageManager sm = getStorageManager(); - - final File outFile = getFilePath("test1_nosig.obb"); - - mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL); - - assertFalse("OBB should not be mounted", - sm.isObbMounted(outFile.getPath())); - - assertNull("OBB's mounted path should be null", - sm.getMountedObbPath(outFile.getPath())); - } - - @LargeTest - public void testAttemptMountObbWrongPackage() { - StorageManager sm = getStorageManager(); - - final File outFile = getFilePath("test1_wrongpackage.obb"); - - mountObb(sm, R.raw.test1_wrongpackage, outFile, - OnObbStateChangeListener.ERROR_PERMISSION_DENIED); - - assertFalse("OBB should not be mounted", - sm.isObbMounted(outFile.getPath())); - - assertNull("OBB's mounted path should be null", - sm.getMountedObbPath(outFile.getPath())); - } - - @LargeTest - public void testMountAndUnmountTwoObbs() { - StorageManager sm = getStorageManager(); - - final File file1 = getFilePath("test1.obb"); - final File file2 = getFilePath("test2.obb"); - - ObbObserver oo1 = mountObbWithoutWait(sm, R.raw.test1, file1); - ObbObserver oo2 = mountObbWithoutWait(sm, R.raw.test1, file2); - - Log.d(TAG, "Waiting for OBB #1 to complete mount"); - waitForObbActionCompletion(sm, file1, oo1, OnObbStateChangeListener.MOUNTED, false); - Log.d(TAG, "Waiting for OBB #2 to complete mount"); - waitForObbActionCompletion(sm, file2, oo2, OnObbStateChangeListener.MOUNTED, false); - - final String mountPath1 = checkMountedPath(sm, file1); - final File mountDir1 = new File(mountPath1); - assertTrue("OBB mounted path should be a directory", mountDir1.isDirectory()); - - final String mountPath2 = checkMountedPath(sm, file2); - final File mountDir2 = new File(mountPath2); - assertTrue("OBB mounted path should be a directory", mountDir2.isDirectory()); - - unmountObb(sm, file1, OnObbStateChangeListener.UNMOUNTED); - unmountObb(sm, file2, OnObbStateChangeListener.UNMOUNTED); - } -} |