Move unsolicited vold events to Binder.

Create IVoldListener and move most unsolicited vold events over to
this new interface.  The remaining events will be routed through
method-specific listeners instead of a global one.

Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.DirectBootHostTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AdoptableHostTest
Test: cts-tradefed run commandAndExit cts-dev -m CtsOsTestCases -t android.os.storage.cts.StorageManagerTest
Bug: 13758960
Change-Id: I492dacfaf98eeb66868b2cf7dfa27d84f6710948
This commit is contained in:
Jeff Sharkey
2017-09-13 11:50:33 -06:00
parent 43e12114d4
commit 8058fe691c
4 changed files with 191 additions and 79 deletions

View File

@@ -567,6 +567,7 @@ LOCAL_SRC_FILES += \
LOCAL_SRC_FILES += \
../../system/netd/server/binder/android/net/INetd.aidl \
../../system/vold/binder/android/os/IVold.aidl \
../../system/vold/binder/android/os/IVoldListener.aidl \
../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += system/update_engine/binder_bindings
@@ -591,6 +592,7 @@ LOCAL_AIDL_INCLUDES += \
frameworks/av/media/libaudioclient/aidl \
frameworks/native/aidl/gui \
system/netd/server/binder \
system/vold/binder \
system/bt/binder
LOCAL_INTERMEDIATE_SOURCES := \

View File

@@ -76,21 +76,21 @@ public class VolumeInfo implements Parcelable {
/** Real volume representing internal emulated storage */
public static final String ID_EMULATED_INTERNAL = "emulated";
public static final int TYPE_PUBLIC = IVold.TYPE_PUBLIC;
public static final int TYPE_PRIVATE = IVold.TYPE_PRIVATE;
public static final int TYPE_EMULATED = IVold.TYPE_EMULATED;
public static final int TYPE_ASEC = IVold.TYPE_ASEC;
public static final int TYPE_OBB = IVold.TYPE_OBB;
public static final int TYPE_PUBLIC = IVold.VOLUME_TYPE_PUBLIC;
public static final int TYPE_PRIVATE = IVold.VOLUME_TYPE_PRIVATE;
public static final int TYPE_EMULATED = IVold.VOLUME_TYPE_EMULATED;
public static final int TYPE_ASEC = IVold.VOLUME_TYPE_ASEC;
public static final int TYPE_OBB = IVold.VOLUME_TYPE_OBB;
public static final int STATE_UNMOUNTED = IVold.STATE_UNMOUNTED;
public static final int STATE_CHECKING = IVold.STATE_CHECKING;
public static final int STATE_MOUNTED = IVold.STATE_MOUNTED;
public static final int STATE_MOUNTED_READ_ONLY = IVold.STATE_MOUNTED_READ_ONLY;
public static final int STATE_FORMATTING = IVold.STATE_FORMATTING;
public static final int STATE_EJECTING = IVold.STATE_EJECTING;
public static final int STATE_UNMOUNTABLE = IVold.STATE_UNMOUNTABLE;
public static final int STATE_REMOVED = IVold.STATE_REMOVED;
public static final int STATE_BAD_REMOVAL = IVold.STATE_BAD_REMOVAL;
public static final int STATE_UNMOUNTED = IVold.VOLUME_STATE_UNMOUNTED;
public static final int STATE_CHECKING = IVold.VOLUME_STATE_CHECKING;
public static final int STATE_MOUNTED = IVold.VOLUME_STATE_MOUNTED;
public static final int STATE_MOUNTED_READ_ONLY = IVold.VOLUME_STATE_MOUNTED_READ_ONLY;
public static final int STATE_FORMATTING = IVold.VOLUME_STATE_FORMATTING;
public static final int STATE_EJECTING = IVold.VOLUME_STATE_EJECTING;
public static final int STATE_UNMOUNTABLE = IVold.VOLUME_STATE_UNMOUNTABLE;
public static final int STATE_REMOVED = IVold.VOLUME_STATE_REMOVED;
public static final int STATE_BAD_REMOVAL = IVold.VOLUME_STATE_BAD_REMOVAL;
public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY;
public static final int MOUNT_FLAG_VISIBLE = IVold.MOUNT_FLAG_VISIBLE;

View File

@@ -6,8 +6,8 @@ LOCAL_MODULE := services.core
LOCAL_AIDL_INCLUDES := \
frameworks/native/aidl/binder \
system/netd/server/binder
system/netd/server/binder \
system/vold/binder
LOCAL_SRC_FILES += \
$(call all-java-files-under,java) \
@@ -16,6 +16,7 @@ LOCAL_SRC_FILES += \
../../../../system/netd/server/binder/android/net/INetd.aidl \
../../../../system/netd/server/binder/android/net/metrics/INetdEventListener.aidl \
../../../../system/vold/binder/android/os/IVold.aidl \
../../../../system/vold/binder/android/os/IVoldListener.aidl \
../../../native/cmds/installd/binder/android/os/IInstalld.aidl \
LOCAL_AIDL_INCLUDES += \

View File

@@ -57,6 +57,7 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IVold;
import android.os.IVoldListener;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -1128,26 +1129,21 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public boolean onEvent(int code, String raw, String[] cooked) {
synchronized (mLock) {
return onEventLocked(code, raw, cooked);
try {
return onEventLocked(code, raw, cooked);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
}
private boolean onEventLocked(int code, String raw, String[] cooked) {
private boolean onEventLocked(int code, String raw, String[] cooked) throws RemoteException {
switch (code) {
case VoldResponseCode.DISK_CREATED: {
if (cooked.length != 3) break;
final String id = cooked[1];
int flags = Integer.parseInt(cooked[2]);
if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
|| mForceAdoptable) {
flags |= DiskInfo.FLAG_ADOPTABLE;
}
// Adoptable storage isn't currently supported on FBE devices
if (StorageManager.isFileEncryptedNativeOnly()
&& !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
flags &= ~DiskInfo.FLAG_ADOPTABLE;
}
mDisks.put(id, new DiskInfo(id, flags));
final String diskId = cooked[1];
final int flags = Integer.parseInt(cooked[2]);
mListener.onDiskCreated(diskId, flags);
break;
}
case VoldResponseCode.DISK_SIZE_CHANGED: {
@@ -1171,10 +1167,8 @@ class StorageManagerService extends IStorageManager.Stub
}
case VoldResponseCode.DISK_SCANNED: {
if (cooked.length != 2) break;
final DiskInfo disk = mDisks.get(cooked[1]);
if (disk != null) {
onDiskScannedLocked(disk);
}
final String diskId = cooked[1];
mListener.onDiskScanned(diskId);
break;
}
case VoldResponseCode.DISK_SYS_PATH_CHANGED: {
@@ -1187,34 +1181,24 @@ class StorageManagerService extends IStorageManager.Stub
}
case VoldResponseCode.DISK_DESTROYED: {
if (cooked.length != 2) break;
final DiskInfo disk = mDisks.remove(cooked[1]);
if (disk != null) {
mCallbacks.notifyDiskDestroyed(disk);
}
final String diskId = cooked[1];
mListener.onDiskDestroyed(diskId);
break;
}
case VoldResponseCode.VOLUME_CREATED: {
final String id = cooked[1];
final String volId = cooked[1];
final int type = Integer.parseInt(cooked[2]);
final String diskId = TextUtils.nullIfEmpty(cooked[3]);
final String partGuid = TextUtils.nullIfEmpty(cooked[4]);
final DiskInfo disk = mDisks.get(diskId);
final VolumeInfo vol = new VolumeInfo(id, type, disk, partGuid);
mVolumes.put(id, vol);
onVolumeCreatedLocked(vol);
mListener.onVolumeCreated(volId, type, diskId, partGuid);
break;
}
case VoldResponseCode.VOLUME_STATE_CHANGED: {
if (cooked.length != 3) break;
final VolumeInfo vol = mVolumes.get(cooked[1]);
if (vol != null) {
final int oldState = vol.state;
final int newState = Integer.parseInt(cooked[2]);
vol.state = newState;
onVolumeStateChangedLocked(vol, oldState, newState);
}
final String volId = cooked[1];
final int state = Integer.parseInt(cooked[2]);
mListener.onVolumeStateChanged(volId, state);
break;
}
case VoldResponseCode.VOLUME_FS_TYPE_CHANGED: {
@@ -1247,23 +1231,22 @@ class StorageManagerService extends IStorageManager.Stub
}
case VoldResponseCode.VOLUME_PATH_CHANGED: {
if (cooked.length != 3) break;
final VolumeInfo vol = mVolumes.get(cooked[1]);
if (vol != null) {
vol.path = cooked[2];
}
final String volId = cooked[1];
final String path = cooked[2];
mListener.onVolumePathChanged(volId, path);
break;
}
case VoldResponseCode.VOLUME_INTERNAL_PATH_CHANGED: {
if (cooked.length != 3) break;
final VolumeInfo vol = mVolumes.get(cooked[1]);
if (vol != null) {
vol.internalPath = cooked[2];
}
final String volId = cooked[1];
final String internalPath = cooked[2];
mListener.onVolumeInternalPathChanged(volId, internalPath);
break;
}
case VoldResponseCode.VOLUME_DESTROYED: {
if (cooked.length != 2) break;
mVolumes.remove(cooked[1]);
final String volId = cooked[1];
mListener.onVolumeDestroyed(volId);
break;
}
@@ -1320,6 +1303,120 @@ class StorageManagerService extends IStorageManager.Stub
return true;
}
private final IVoldListener mListener = new IVoldListener.Stub() {
@Override
public void onDiskCreated(String diskId, int flags) {
synchronized (mLock) {
if (SystemProperties.getBoolean(StorageManager.PROP_FORCE_ADOPTABLE, false)
|| mForceAdoptable) {
flags |= DiskInfo.FLAG_ADOPTABLE;
}
// Adoptable storage isn't currently supported on FBE devices
if (StorageManager.isFileEncryptedNativeOnly()
&& !SystemProperties.getBoolean(StorageManager.PROP_ADOPTABLE_FBE, false)) {
flags &= ~DiskInfo.FLAG_ADOPTABLE;
}
mDisks.put(diskId, new DiskInfo(diskId, flags));
}
}
@Override
public void onDiskScanned(String diskId) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
if (disk != null) {
onDiskScannedLocked(disk);
}
}
}
@Override
public void onDiskMetadataChanged(String diskId, long sizeBytes, String label,
String sysPath) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
if (disk != null) {
disk.size = sizeBytes;
disk.label = label;
disk.sysPath = sysPath;
}
}
}
@Override
public void onDiskDestroyed(String diskId) {
synchronized (mLock) {
final DiskInfo disk = mDisks.remove(diskId);
if (disk != null) {
mCallbacks.notifyDiskDestroyed(disk);
}
}
}
@Override
public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
synchronized (mLock) {
final DiskInfo disk = mDisks.get(diskId);
final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
mVolumes.put(volId, vol);
onVolumeCreatedLocked(vol);
}
}
@Override
public void onVolumeStateChanged(String volId, int state) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
final int oldState = vol.state;
final int newState = state;
vol.state = newState;
onVolumeStateChangedLocked(vol, oldState, newState);
}
}
}
@Override
public void onVolumeMetadataChanged(String volId, String fsType, String fsUuid,
String fsLabel) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
vol.fsType = fsType;
vol.fsUuid = fsUuid;
vol.fsLabel = fsLabel;
}
}
}
@Override
public void onVolumePathChanged(String volId, String path) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
vol.path = path;
}
}
}
@Override
public void onVolumeInternalPathChanged(String volId, String internalPath) {
synchronized (mLock) {
final VolumeInfo vol = mVolumes.get(volId);
if (vol != null) {
vol.internalPath = internalPath;
}
}
}
@Override
public void onVolumeDestroyed(String volId) {
synchronized (mLock) {
mVolumes.remove(volId);
}
}
};
private void onDiskScannedLocked(DiskInfo disk) {
int volumeCount = 0;
for (int i = 0; i < mVolumes.size(); i++) {
@@ -1661,12 +1758,19 @@ class StorageManagerService extends IStorageManager.Stub
if (binder != null) {
mVold = IVold.Stub.asInterface(binder);
try {
mVold.setListener(mListener);
return;
} catch (RemoteException e) {
Slog.w(TAG, "vold listener rejected; trying again", e);
}
} else {
Slog.w(TAG, "vold not found; trying again");
BackgroundThread.getHandler().postDelayed(() -> {
connect();
}, DateUtils.SECOND_IN_MILLIS);
}
BackgroundThread.getHandler().postDelayed(() -> {
connect();
}, DateUtils.SECOND_IN_MILLIS);
}
private void systemReady() {
@@ -2769,15 +2873,15 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public int decryptStorage(String password) {
if (TextUtils.isEmpty(password)) {
throw new IllegalArgumentException("password cannot be empty");
}
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
waitForReady();
if (TextUtils.isEmpty(password)) {
throw new IllegalArgumentException("password cannot be empty");
}
if (DEBUG_EVENTS) {
Slog.i(TAG, "decrypting storage...");
}
@@ -2792,6 +2896,7 @@ class StorageManagerService extends IStorageManager.Stub
Slog.wtf(TAG, e);
}
}, DateUtils.SECOND_IN_MILLIS);
return 0;
} catch (Exception e) {
Slog.wtf(TAG, e);
return StorageManager.ENCRYPTION_STATE_ERROR_UNKNOWN;
@@ -2825,30 +2930,28 @@ class StorageManagerService extends IStorageManager.Stub
}
public int encryptStorage(int type, String password) {
if (TextUtils.isEmpty(password) && type != StorageManager.CRYPT_TYPE_DEFAULT) {
throw new IllegalArgumentException("password cannot be empty");
}
mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
"no permission to access the crypt keeper");
waitForReady();
if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
password = "";
} else if (TextUtils.isEmpty(password)) {
throw new IllegalArgumentException("password cannot be empty");
}
if (DEBUG_EVENTS) {
Slog.i(TAG, "encrypting storage...");
}
try {
if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
if (ENABLE_BINDER) {
mVold.fdeEnable(type, null, IVold.ENCRYPTION_FLAG_IN_PLACE);
} else {
if (ENABLE_BINDER) {
mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
} else {
if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
mCryptConnector.execute("cryptfs", "enablecrypto", "inplace",
CRYPTO_TYPES[type]);
}
} else {
if (ENABLE_BINDER) {
mVold.fdeEnable(type, password, IVold.ENCRYPTION_FLAG_IN_PLACE);
} else {
mCryptConnector.execute("cryptfs", "enablecrypto", "inplace",
CRYPTO_TYPES[type], new SensitiveArg(password));
@@ -2872,6 +2975,12 @@ class StorageManagerService extends IStorageManager.Stub
waitForReady();
if (type == StorageManager.CRYPT_TYPE_DEFAULT) {
password = "";
} else if (TextUtils.isEmpty(password)) {
throw new IllegalArgumentException("password cannot be empty");
}
if (DEBUG_EVENTS) {
Slog.i(TAG, "changing encryption password...");
}