Merge "Remove DefaultContainerService usage in StorageManagerService."
This commit is contained in:
committed by
Android (Google) Code Review
commit
8e7cf05d27
@@ -80,6 +80,7 @@ public class ObbInfo implements Parcelable {
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel dest, int parcelableFlags) {
|
||||
// Keep this in sync with writeToParcel() in ObbInfo.cpp
|
||||
dest.writeString(filename);
|
||||
dest.writeString(packageName);
|
||||
dest.writeInt(version);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.os.storage;
|
||||
|
||||
import android.content.pm.IPackageMoveObserver;
|
||||
import android.content.res.ObbInfo;
|
||||
import android.os.IVoldTaskListener;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.storage.DiskInfo;
|
||||
@@ -57,7 +58,7 @@ interface IStorageManager {
|
||||
* it of the terminal state of the call.
|
||||
*/
|
||||
void mountObb(in String rawPath, in String canonicalPath, in String key,
|
||||
IObbActionListener token, int nonce) = 21;
|
||||
IObbActionListener token, int nonce, in ObbInfo obbInfo) = 21;
|
||||
/**
|
||||
* Unmounts an Opaque Binary Blob (OBB). When the force flag is specified,
|
||||
* any program using it will be forcibly killed to unmount the image.
|
||||
|
||||
@@ -34,6 +34,8 @@ import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageMoveObserver;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.ObbInfo;
|
||||
import android.content.res.ObbScanner;
|
||||
import android.os.Binder;
|
||||
import android.os.Environment;
|
||||
import android.os.FileUtils;
|
||||
@@ -580,7 +582,8 @@ public class StorageManager {
|
||||
try {
|
||||
final String canonicalPath = new File(rawPath).getCanonicalPath();
|
||||
final int nonce = mObbActionListener.addListener(listener);
|
||||
mStorageManager.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce);
|
||||
mStorageManager.mountObb(rawPath, canonicalPath, key, mObbActionListener, nonce,
|
||||
getObbInfo(canonicalPath));
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException("Failed to resolve path: " + rawPath, e);
|
||||
@@ -589,6 +592,15 @@ public class StorageManager {
|
||||
}
|
||||
}
|
||||
|
||||
private ObbInfo getObbInfo(String canonicalPath) {
|
||||
try {
|
||||
final ObbInfo obbInfo = ObbScanner.getObbInfo(canonicalPath);
|
||||
return obbInfo;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalArgumentException("Couldn't get OBB info for " + canonicalPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
|
||||
* <code>force</code> flag is true, it will kill any application needed to
|
||||
|
||||
@@ -65,95 +65,6 @@ public class StorageManagerBaseTest extends InstrumentationTestCase {
|
||||
+ "to ourselves and our posterity, do ordain and establish this Constitution\n"
|
||||
+ "for the United States of America.\n\n";
|
||||
|
||||
class MountingObbThread extends Thread {
|
||||
boolean mStop = false;
|
||||
volatile boolean mFileOpenOnObb = false;
|
||||
private String mObbFilePath = null;
|
||||
private String mPathToContentsFile = null;
|
||||
private String mOfficialObbFilePath = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param obbFilePath path to the OBB image file
|
||||
* @param pathToContentsFile path to a file on the mounted OBB volume to open after the OBB
|
||||
* has been mounted
|
||||
*/
|
||||
public MountingObbThread (String obbFilePath, String pathToContentsFile) {
|
||||
assertTrue("obbFilePath cannot be null!", obbFilePath != null);
|
||||
mObbFilePath = obbFilePath;
|
||||
assertTrue("path to contents file cannot be null!", pathToContentsFile != null);
|
||||
mPathToContentsFile = pathToContentsFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the thread
|
||||
*
|
||||
* Mounts OBB_FILE_1, and tries to open a file on the mounted OBB (specified in the
|
||||
* constructor). Once it's open, it waits until someone calls its doStop(), after which it
|
||||
* closes the opened file.
|
||||
*/
|
||||
public void run() {
|
||||
// the official OBB file path and the mount-request file path should be the same, but
|
||||
// let's distinguish the two as they may make for some interesting tests later
|
||||
mOfficialObbFilePath = mountObb(mObbFilePath);
|
||||
assertEquals("Expected and actual OBB file paths differ!", mObbFilePath,
|
||||
mOfficialObbFilePath);
|
||||
|
||||
// open a file on OBB 1...
|
||||
DataInputStream inputFile = openFileOnMountedObb(mOfficialObbFilePath,
|
||||
mPathToContentsFile);
|
||||
assertTrue("Failed to open file!", inputFile != null);
|
||||
|
||||
synchronized (this) {
|
||||
mFileOpenOnObb = true;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
while (!mStop) {
|
||||
try {
|
||||
Thread.sleep(WAIT_TIME_INCR);
|
||||
} catch (InterruptedException e) {
|
||||
// nothing special to be done for interruptions
|
||||
}
|
||||
}
|
||||
try {
|
||||
inputFile.close();
|
||||
} catch (IOException e) {
|
||||
fail("Failed to close file on OBB due to error: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether a file has yet been successfully opened on the OBB or not
|
||||
*
|
||||
* @return true if the specified file on the OBB was opened; false otherwise
|
||||
*/
|
||||
public boolean isFileOpenOnObb() {
|
||||
return mFileOpenOnObb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the official path of the OBB file that was mounted
|
||||
*
|
||||
* This is not the mount path, but the normalized path to the actual OBB file
|
||||
*
|
||||
* @return a {@link String} representation of the path to the OBB file that was mounted
|
||||
*/
|
||||
public String officialObbFilePath() {
|
||||
return mOfficialObbFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the thread to stop running
|
||||
*
|
||||
* Closes the opened file and returns
|
||||
*/
|
||||
public void doStop() {
|
||||
mStop = true;
|
||||
}
|
||||
}
|
||||
|
||||
public class ObbListener extends OnObbStateChangeListener {
|
||||
private String LOG_TAG = "StorageManagerBaseTest.ObbListener";
|
||||
|
||||
@@ -362,7 +273,8 @@ public class StorageManagerBaseTest extends InstrumentationTestCase {
|
||||
assertTrue("mountObb call failed", mSm.mountObb(obbFilePath, key, obbListener));
|
||||
assertTrue("Failed to get OBB mount status change for file: " + obbFilePath,
|
||||
doWaitForObbStateChange(obbListener));
|
||||
assertEquals("OBB mount state not what was expected!", expectedState, obbListener.state());
|
||||
assertEquals("OBB mount state not what was expected!", expectedState,
|
||||
obbListener.state());
|
||||
|
||||
if (OnObbStateChangeListener.MOUNTED == expectedState) {
|
||||
assertEquals(obbFilePath, obbListener.officialPath());
|
||||
@@ -373,7 +285,8 @@ public class StorageManagerBaseTest extends InstrumentationTestCase {
|
||||
mSm.isObbMounted(obbListener.officialPath()));
|
||||
}
|
||||
|
||||
assertEquals("Mount state is not what was expected!", expectedState, obbListener.state());
|
||||
assertEquals("Mount state is not what was expected!", expectedState,
|
||||
obbListener.state());
|
||||
return obbListener.officialPath();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.os.ParcelFileDescriptor;
|
||||
import android.os.ProxyFileDescriptorCallback;
|
||||
import android.system.ErrnoException;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.frameworks.coretests.R;
|
||||
|
||||
@@ -134,50 +133,6 @@ public class StorageManagerIntegrationTest extends StorageManagerBaseTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that we can not force unmount when a file is currently open on the OBB.
|
||||
*/
|
||||
@LargeTest
|
||||
public void testUnmount_DontForce() throws Exception {
|
||||
final File file = createObbFile(OBB_FILE_1, R.raw.obb_file1);
|
||||
String obbFilePath = file.getAbsolutePath();
|
||||
|
||||
MountingObbThread mountingThread = new MountingObbThread(obbFilePath,
|
||||
OBB_FILE_1_CONTENTS_1);
|
||||
|
||||
try {
|
||||
mountingThread.start();
|
||||
|
||||
long waitTime = 0;
|
||||
while (!mountingThread.isFileOpenOnObb()) {
|
||||
synchronized (mountingThread) {
|
||||
Log.i(LOG_TAG, "Waiting for file to be opened on OBB...");
|
||||
mountingThread.wait(WAIT_TIME_INCR);
|
||||
waitTime += WAIT_TIME_INCR;
|
||||
if (waitTime > MAX_WAIT_TIME) {
|
||||
fail("Timed out waiting for file file to be opened on OBB!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unmountObb(obbFilePath, DONT_FORCE);
|
||||
|
||||
// verify still mounted
|
||||
assertTrue("mounted path should not be null!", obbFilePath != null);
|
||||
assertTrue("mounted path should still be mounted!", mSm.isObbMounted(obbFilePath));
|
||||
|
||||
// close the opened file
|
||||
mountingThread.doStop();
|
||||
|
||||
// try unmounting again (should succeed this time)
|
||||
unmountObb(obbFilePath, DONT_FORCE);
|
||||
assertFalse("mounted path should no longer be mounted!",
|
||||
mSm.isObbMounted(obbFilePath));
|
||||
} catch (InterruptedException e) {
|
||||
fail("Timed out waiting for file on OBB to be opened...");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests mounting a single OBB that isn't signed.
|
||||
*/
|
||||
@@ -185,7 +140,12 @@ public class StorageManagerIntegrationTest extends StorageManagerBaseTest {
|
||||
public void testMountUnsignedObb() throws Exception {
|
||||
final File file = createObbFile(OBB_FILE_2_UNSIGNED, R.raw.obb_file2_nosign);
|
||||
String filePath = file.getAbsolutePath();
|
||||
mountObb(filePath, OBB_FILE_2_UNSIGNED, OnObbStateChangeListener.ERROR_INTERNAL);
|
||||
try {
|
||||
mountObb(filePath, OBB_FILE_2_UNSIGNED, OnObbStateChangeListener.ERROR_INTERNAL);
|
||||
fail("mountObb should've failed with an exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ cc_library_static {
|
||||
"IMountShutdownObserver.cpp",
|
||||
"IObbActionListener.cpp",
|
||||
"IMountService.cpp",
|
||||
"ObbInfo.cpp",
|
||||
],
|
||||
|
||||
export_include_dirs: ["include"],
|
||||
|
||||
@@ -443,7 +443,7 @@ public:
|
||||
}
|
||||
|
||||
void mountObb(const String16& rawPath, const String16& canonicalPath, const String16& key,
|
||||
const sp<IObbActionListener>& token, int32_t nonce)
|
||||
const sp<IObbActionListener>& token, int32_t nonce, const sp<ObbInfo>& obbInfo)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
|
||||
@@ -452,6 +452,7 @@ public:
|
||||
data.writeString16(key);
|
||||
data.writeStrongBinder(IInterface::asBinder(token));
|
||||
data.writeInt32(nonce);
|
||||
obbInfo->writeToParcel(&data);
|
||||
if (remote()->transact(TRANSACTION_mountObb, data, &reply) != NO_ERROR) {
|
||||
ALOGD("mountObb could not contact remote\n");
|
||||
return;
|
||||
|
||||
47
libs/storage/ObbInfo.cpp
Normal file
47
libs/storage/ObbInfo.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#include <storage/ObbInfo.h>
|
||||
|
||||
#include <binder/Parcel.h>
|
||||
#include <utils/String16.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
ObbInfo::ObbInfo(const String16 fileName, const String16 packageName, int32_t version,
|
||||
int32_t flags, size_t saltSize, const uint8_t* salt) : mFileName(fileName),
|
||||
mPackageName(packageName), mVersion(version), mFlags(flags), mSaltSize(saltSize),
|
||||
mSalt(salt) {}
|
||||
|
||||
ObbInfo::~ObbInfo() {}
|
||||
|
||||
status_t ObbInfo::readFromParcel(const Parcel*) {
|
||||
return INVALID_OPERATION;
|
||||
}
|
||||
|
||||
status_t ObbInfo::writeToParcel(Parcel* p) const {
|
||||
// Parcel write code must be kept in sync with
|
||||
// frameworks/base/core/java/android/content/res/ObbInfo.java
|
||||
p->writeString16(mFileName);
|
||||
p->writeString16(mPackageName);
|
||||
p->writeInt32(mVersion);
|
||||
p->writeInt32(mFlags);
|
||||
p->writeByteArray(mSaltSize, mSalt);
|
||||
return OK;
|
||||
}
|
||||
|
||||
}; // namespace android
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <storage/IMountServiceListener.h>
|
||||
#include <storage/IMountShutdownObserver.h>
|
||||
#include <storage/IObbActionListener.h>
|
||||
#include <storage/ObbInfo.h>
|
||||
|
||||
#include <utils/String8.h>
|
||||
|
||||
@@ -64,7 +65,7 @@ public:
|
||||
virtual void finishMediaUpdate() = 0;
|
||||
virtual void mountObb(const String16& rawPath, const String16& canonicalPath,
|
||||
const String16& key, const sp<IObbActionListener>& token,
|
||||
const int32_t nonce) = 0;
|
||||
const int32_t nonce, const sp<ObbInfo>& obbInfo) = 0;
|
||||
virtual void unmountObb(const String16& filename, const bool force,
|
||||
const sp<IObbActionListener>& token, const int32_t nonce) = 0;
|
||||
virtual bool isObbMounted(const String16& filename) = 0;
|
||||
|
||||
48
libs/storage/include/storage/ObbInfo.h
Normal file
48
libs/storage/include/storage/ObbInfo.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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_OBBINFO_H
|
||||
#define ANDROID_OBBINFO_H
|
||||
|
||||
#include <binder/Parcelable.h>
|
||||
#include <utils/RefBase.h>
|
||||
#include <utils/String16.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
class ObbInfo : public Parcelable, public virtual RefBase {
|
||||
|
||||
public:
|
||||
ObbInfo(const String16 fileName, const String16 packageName, int32_t version,
|
||||
int32_t flags, size_t saltSize, const uint8_t* salt);
|
||||
~ObbInfo();
|
||||
|
||||
status_t writeToParcel(Parcel* parcel) const override;
|
||||
status_t readFromParcel(const Parcel* parcel) override;
|
||||
|
||||
private:
|
||||
const String16 mFileName;
|
||||
const String16 mPackageName;
|
||||
int32_t mVersion;
|
||||
int32_t mFlags;
|
||||
size_t mSaltSize;
|
||||
const uint8_t* mSalt;
|
||||
};
|
||||
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_OBBINFO_H
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
#include <android/storage_manager.h>
|
||||
#include <storage/IMountService.h>
|
||||
#include <storage/ObbInfo.h>
|
||||
|
||||
#include <androidfw/ObbFile.h>
|
||||
#include <binder/Binder.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <cutils/atomic.h>
|
||||
@@ -29,7 +31,6 @@
|
||||
#include <utils/Vector.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
|
||||
using namespace android;
|
||||
|
||||
struct ObbActionListener : public BnObbActionListener {
|
||||
@@ -79,6 +80,20 @@ protected:
|
||||
return cb;
|
||||
}
|
||||
|
||||
ObbInfo* getObbInfo(char* canonicalPath) {
|
||||
sp<ObbFile> obbFile = new ObbFile();
|
||||
if (!obbFile->readFrom(canonicalPath)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
String16 fileName(obbFile->getFileName());
|
||||
String16 packageName(obbFile->getPackageName());
|
||||
size_t length;
|
||||
const unsigned char* salt = obbFile->getSalt(&length);
|
||||
return new ObbInfo(fileName, packageName,
|
||||
obbFile->getVersion(), obbFile->getFlags(), length, salt);
|
||||
}
|
||||
|
||||
public:
|
||||
AStorageManager()
|
||||
{
|
||||
@@ -134,11 +149,18 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
sp<ObbInfo> obbInfo = getObbInfo(canonicalPath);
|
||||
if (obbInfo == nullptr) {
|
||||
ALOGE("Couldn't get obb info for %s: %s", canonicalPath, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
ObbCallback* cb = registerObbCallback(func, data);
|
||||
String16 rawPath16(rawPath);
|
||||
String16 canonicalPath16(canonicalPath);
|
||||
String16 key16(key);
|
||||
mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener, cb->nonce);
|
||||
mMountService->mountObb(rawPath16, canonicalPath16, key16, mObbActionListener,
|
||||
cb->nonce, obbInfo);
|
||||
}
|
||||
|
||||
void unmountObb(const char* filename, const bool force, AStorageManager_obbCallbackFunc func, void* data) {
|
||||
|
||||
@@ -44,11 +44,9 @@ import android.app.KeyguardManager;
|
||||
import android.app.admin.SecurityLog;
|
||||
import android.app.usage.StorageStatsManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageMoveObserver;
|
||||
import android.content.pm.PackageManager;
|
||||
@@ -115,7 +113,6 @@ import android.util.Xml;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.IMediaContainerService;
|
||||
import com.android.internal.os.AppFuseMount;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.os.FuseUnavailableMountException;
|
||||
@@ -544,37 +541,7 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
|
||||
// OBB action handler messages
|
||||
private static final int OBB_RUN_ACTION = 1;
|
||||
private static final int OBB_MCS_BOUND = 2;
|
||||
private static final int OBB_MCS_UNBIND = 3;
|
||||
private static final int OBB_MCS_RECONNECT = 4;
|
||||
private static final int OBB_FLUSH_MOUNT_STATE = 5;
|
||||
|
||||
/*
|
||||
* Default Container Service information
|
||||
*/
|
||||
static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
|
||||
"com.android.defcontainer", "com.android.defcontainer.DefaultContainerService");
|
||||
|
||||
final private DefaultContainerConnection mDefContainerConn = new DefaultContainerConnection();
|
||||
|
||||
class DefaultContainerConnection implements ServiceConnection {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "onServiceConnected");
|
||||
IMediaContainerService imcs = IMediaContainerService.Stub.asInterface(service);
|
||||
mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_MCS_BOUND, imcs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "onServiceDisconnected");
|
||||
}
|
||||
}
|
||||
|
||||
// Used in the ObbActionHandler
|
||||
private IMediaContainerService mContainerService = null;
|
||||
private static final int OBB_FLUSH_MOUNT_STATE = 2;
|
||||
|
||||
// Last fstrim operation tracking
|
||||
private static final String LAST_FSTRIM_FILE = "last-fstrim";
|
||||
@@ -2305,16 +2272,17 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mountObb(
|
||||
String rawPath, String canonicalPath, String key, IObbActionListener token, int nonce) {
|
||||
public void mountObb(String rawPath, String canonicalPath, String key,
|
||||
IObbActionListener token, int nonce, ObbInfo obbInfo) {
|
||||
Preconditions.checkNotNull(rawPath, "rawPath cannot be null");
|
||||
Preconditions.checkNotNull(canonicalPath, "canonicalPath cannot be null");
|
||||
Preconditions.checkNotNull(token, "token cannot be null");
|
||||
Preconditions.checkNotNull(obbInfo, "obbIfno cannot be null");
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final ObbState obbState = new ObbState(rawPath, canonicalPath,
|
||||
callingUid, token, nonce, null);
|
||||
final ObbAction action = new MountObbAction(obbState, key, callingUid);
|
||||
final ObbAction action = new MountObbAction(obbState, key, callingUid, obbInfo);
|
||||
mObbActionHandler.sendMessage(mObbActionHandler.obtainMessage(OBB_RUN_ACTION, action));
|
||||
|
||||
if (DEBUG_OBB)
|
||||
@@ -3217,8 +3185,6 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
}
|
||||
|
||||
private class ObbActionHandler extends Handler {
|
||||
private boolean mBound = false;
|
||||
private final List<ObbAction> mActions = new LinkedList<ObbAction>();
|
||||
|
||||
ObbActionHandler(Looper l) {
|
||||
super(l);
|
||||
@@ -3233,83 +3199,7 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "OBB_RUN_ACTION: " + action.toString());
|
||||
|
||||
// If a bind was already initiated we don't really
|
||||
// need to do anything. The pending install
|
||||
// will be processed later on.
|
||||
if (!mBound) {
|
||||
// If this is the only one pending we might
|
||||
// have to bind to the service again.
|
||||
if (!connectToService()) {
|
||||
action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
|
||||
"Failed to bind to media container service"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mActions.add(action);
|
||||
break;
|
||||
}
|
||||
case OBB_MCS_BOUND: {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "OBB_MCS_BOUND");
|
||||
if (msg.obj != null) {
|
||||
mContainerService = (IMediaContainerService) msg.obj;
|
||||
}
|
||||
if (mContainerService == null) {
|
||||
// Something seriously wrong. Bail out
|
||||
for (ObbAction action : mActions) {
|
||||
// Indicate service bind error
|
||||
action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
|
||||
"Failed to bind to media container service"));
|
||||
}
|
||||
mActions.clear();
|
||||
} else if (mActions.size() > 0) {
|
||||
final ObbAction action = mActions.get(0);
|
||||
if (action != null) {
|
||||
action.execute(this);
|
||||
}
|
||||
} else {
|
||||
// Should never happen ideally.
|
||||
Slog.w(TAG, "Empty queue");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OBB_MCS_RECONNECT: {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "OBB_MCS_RECONNECT");
|
||||
if (mActions.size() > 0) {
|
||||
if (mBound) {
|
||||
disconnectService();
|
||||
}
|
||||
if (!connectToService()) {
|
||||
for (ObbAction action : mActions) {
|
||||
// Indicate service bind error
|
||||
action.notifyObbStateChange(new ObbException(ERROR_INTERNAL,
|
||||
"Failed to bind to media container service"));
|
||||
}
|
||||
mActions.clear();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OBB_MCS_UNBIND: {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "OBB_MCS_UNBIND");
|
||||
|
||||
// Delete pending install
|
||||
if (mActions.size() > 0) {
|
||||
mActions.remove(0);
|
||||
}
|
||||
if (mActions.size() == 0) {
|
||||
if (mBound) {
|
||||
disconnectService();
|
||||
}
|
||||
} else {
|
||||
// There are more pending requests in queue.
|
||||
// Just post MCS_BOUND message to trigger processing
|
||||
// of next pending install.
|
||||
mObbActionHandler.sendEmptyMessage(OBB_MCS_BOUND);
|
||||
}
|
||||
action.execute(this);
|
||||
break;
|
||||
}
|
||||
case OBB_FLUSH_MOUNT_STATE: {
|
||||
@@ -3354,25 +3244,6 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean connectToService() {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "Trying to bind to DefaultContainerService");
|
||||
|
||||
Intent service = new Intent().setComponent(DEFAULT_CONTAINER_COMPONENT);
|
||||
if (mContext.bindServiceAsUser(service, mDefContainerConn, Context.BIND_AUTO_CREATE,
|
||||
UserHandle.SYSTEM)) {
|
||||
mBound = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void disconnectService() {
|
||||
mContainerService = null;
|
||||
mBound = false;
|
||||
mContext.unbindService(mDefContainerConn);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ObbException extends Exception {
|
||||
@@ -3390,8 +3261,6 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
}
|
||||
|
||||
abstract class ObbAction {
|
||||
private static final int MAX_RETRIES = 3;
|
||||
private int mRetries;
|
||||
|
||||
ObbState mObbState;
|
||||
|
||||
@@ -3403,40 +3272,14 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
try {
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "Starting to execute action: " + toString());
|
||||
mRetries++;
|
||||
if (mRetries > MAX_RETRIES) {
|
||||
mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
|
||||
notifyObbStateChange(new ObbException(ERROR_INTERNAL,
|
||||
"Failed to bind to media container service"));
|
||||
} else {
|
||||
handleExecute();
|
||||
if (DEBUG_OBB)
|
||||
Slog.i(TAG, "Posting install MCS_UNBIND");
|
||||
mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
|
||||
}
|
||||
handleExecute();
|
||||
} catch (ObbException e) {
|
||||
notifyObbStateChange(e);
|
||||
mObbActionHandler.sendEmptyMessage(OBB_MCS_UNBIND);
|
||||
}
|
||||
}
|
||||
|
||||
abstract void handleExecute() throws ObbException;
|
||||
|
||||
protected ObbInfo getObbInfo() throws ObbException {
|
||||
final ObbInfo obbInfo;
|
||||
try {
|
||||
obbInfo = mContainerService.getObbInfo(mObbState.canonicalPath);
|
||||
} catch (Exception e) {
|
||||
throw new ObbException(ERROR_PERMISSION_DENIED, e);
|
||||
}
|
||||
if (obbInfo != null) {
|
||||
return obbInfo;
|
||||
} else {
|
||||
throw new ObbException(ERROR_INTERNAL,
|
||||
"Missing OBB info for: " + mObbState.canonicalPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected void notifyObbStateChange(ObbException e) {
|
||||
Slog.w(TAG, e);
|
||||
notifyObbStateChange(e.status);
|
||||
@@ -3458,22 +3301,22 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
class MountObbAction extends ObbAction {
|
||||
private final String mKey;
|
||||
private final int mCallingUid;
|
||||
private ObbInfo mObbInfo;
|
||||
|
||||
MountObbAction(ObbState obbState, String key, int callingUid) {
|
||||
MountObbAction(ObbState obbState, String key, int callingUid, ObbInfo obbInfo) {
|
||||
super(obbState);
|
||||
mKey = key;
|
||||
mCallingUid = callingUid;
|
||||
mObbInfo = obbInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleExecute() throws ObbException {
|
||||
warnOnNotMounted();
|
||||
|
||||
final ObbInfo obbInfo = getObbInfo();
|
||||
|
||||
if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mCallingUid)) {
|
||||
if (!isUidOwnerOfPackageOrSystem(mObbInfo.packageName, mCallingUid)) {
|
||||
throw new ObbException(ERROR_PERMISSION_DENIED, "Denied attempt to mount OBB "
|
||||
+ obbInfo.filename + " which is owned by " + obbInfo.packageName);
|
||||
+ mObbInfo.filename + " which is owned by " + mObbInfo.packageName);
|
||||
}
|
||||
|
||||
final boolean isMounted;
|
||||
@@ -3482,7 +3325,7 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
}
|
||||
if (isMounted) {
|
||||
throw new ObbException(ERROR_ALREADY_MOUNTED,
|
||||
"Attempt to mount OBB which is already mounted: " + obbInfo.filename);
|
||||
"Attempt to mount OBB which is already mounted: " + mObbInfo.filename);
|
||||
}
|
||||
|
||||
final String hashedKey;
|
||||
@@ -3494,7 +3337,7 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
try {
|
||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
|
||||
KeySpec ks = new PBEKeySpec(mKey.toCharArray(), obbInfo.salt,
|
||||
KeySpec ks = new PBEKeySpec(mKey.toCharArray(), mObbInfo.salt,
|
||||
PBKDF2_HASH_ROUNDS, CRYPTO_ALGORITHM_KEY_SIZE);
|
||||
SecretKey key = factory.generateSecret(ks);
|
||||
BigInteger bi = new BigInteger(key.getEncoded());
|
||||
|
||||
@@ -220,7 +220,12 @@ public class MountServiceTests extends AndroidTestCase {
|
||||
|
||||
final File outFile = getFilePath("test1_nosig.obb");
|
||||
|
||||
mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
|
||||
try {
|
||||
mountObb(sm, R.raw.test1_nosig, outFile, OnObbStateChangeListener.ERROR_INTERNAL);
|
||||
fail("mountObb should've failed with an exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expected
|
||||
}
|
||||
|
||||
assertFalse("OBB should not be mounted",
|
||||
sm.isObbMounted(outFile.getPath()));
|
||||
|
||||
Reference in New Issue
Block a user