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:
@@ -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 := \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 += \
|
||||
|
||||
@@ -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...");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user