Add API to IMountService to get encryption state
Bug: 18002358
Change-Id: If7d9c9a5ed38ac37849fcf638ec10c76d2f419a1
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index fc440d2..c21c65a 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -2286,7 +2286,12 @@
/**
* Determines the encryption state of the volume.
- * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible values.
+ * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
+ * values.
+ * Note that this has been replaced in most cases by the APIs in
+ * StorageManager (see isEncryptable and below)
+ * This is still useful to get the error state when encryption has failed
+ * and CryptKeeper needs to throw up a screen advising the user what to do
*/
public int getEncryptionState() throws RemoteException;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 17df708..61e6b95 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1025,21 +1025,119 @@
}
}
- /** {@hide} */
- public static boolean isFileBasedEncryptionEnabled() {
- return isNativeFileBasedEncryptionEnabled() || isEmulatedFileBasedEncryptionEnabled();
+ /** {@hide}
+ * Is this device encryptable or already encrypted?
+ * @return true for encryptable or encrypted
+ * false not encrypted and not encryptable
+ */
+ public static boolean isEncryptable() {
+ final String state = SystemProperties.get("ro.crypto.state", "unsupported");
+ return !"unsupported".equalsIgnoreCase(state);
+ }
+
+ /** {@hide}
+ * Is this device already encrypted?
+ * @return true for encrypted. (Implies isEncryptable() == true)
+ * false not encrypted
+ */
+ public static boolean isEncrypted() {
+ final String state = SystemProperties.get("ro.crypto.state", "");
+ return "encrypted".equalsIgnoreCase(state);
+ }
+
+ /** {@hide}
+ * Is this device file encrypted?
+ * @return true for file encrypted. (Implies isEncrypted() == true)
+ * false not encrypted or block encrypted
+ */
+ public static boolean isFileEncryptedNativeOnly() {
+ if (!isEncrypted()) {
+ return false;
+ }
+
+ final String status = SystemProperties.get("ro.crypto.type", "");
+ return "file".equalsIgnoreCase(status);
+ }
+
+ /** {@hide}
+ * Is this device block encrypted?
+ * @return true for block encrypted. (Implies isEncrypted() == true)
+ * false not encrypted or file encrypted
+ */
+ public static boolean isBlockEncrypted() {
+ if (!isEncrypted()) {
+ return false;
+ }
+ final String status = SystemProperties.get("ro.crypto.type", "");
+ return "block".equalsIgnoreCase(status);
+ }
+
+ /** {@hide}
+ * Is this device block encrypted with credentials?
+ * @return true for crediential block encrypted.
+ * (Implies isBlockEncrypted() == true)
+ * false not encrypted, file encrypted or default block encrypted
+ */
+ public static boolean isNonDefaultBlockEncrypted() {
+ if (!isBlockEncrypted()) {
+ return false;
+ }
+
+ try {
+ IMountService mountService = IMountService.Stub.asInterface(
+ ServiceManager.getService("mount"));
+ return mountService.getPasswordType() != CRYPT_TYPE_DEFAULT;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error getting encryption type");
+ return false;
+ }
+ }
+
+ /** {@hide}
+ * Is this device in the process of being block encrypted?
+ * @return true for encrypting.
+ * false otherwise
+ * Whether device isEncrypted at this point is undefined
+ * Note that only system services and CryptKeeper will ever see this return
+ * true - no app will ever be launched in this state.
+ * Also note that this state will not change without a teardown of the
+ * framework, so no service needs to check for changes during their lifespan
+ */
+ public static boolean isBlockEncrypting() {
+ final String state = SystemProperties.get("vold.encrypt_progress", "");
+ return !"".equalsIgnoreCase(state);
+ }
+
+ /** {@hide}
+ * Is this device non default block encrypted and in the process of
+ * prompting for credentials?
+ * @return true for prompting for credentials.
+ * (Implies isNonDefaultBlockEncrypted() == true)
+ * false otherwise
+ * Note that only system services and CryptKeeper will ever see this return
+ * true - no app will ever be launched in this state.
+ * Also note that this state will not change without a teardown of the
+ * framework, so no service needs to check for changes during their lifespan
+ */
+ public static boolean inCryptKeeperBounce() {
+ final String status = SystemProperties.get("vold.decrypt");
+ return "trigger_restart_min_framework".equals(status);
}
/** {@hide} */
- public static boolean isNativeFileBasedEncryptionEnabled() {
- return "file".equals(SystemProperties.get("ro.crypto.type", "none"));
- }
-
- /** {@hide} */
- public static boolean isEmulatedFileBasedEncryptionEnabled() {
+ public static boolean isFileEncryptedEmulatedOnly() {
return SystemProperties.getBoolean(StorageManager.PROP_EMULATE_FBE, false);
}
+ /** {@hide}
+ * Is this device running in a file encrypted mode, either native or emulated?
+ * @return true for file encrypted, false otherwise
+ */
+ public static boolean isFileEncryptedNativeOrEmulated() {
+ return isFileEncryptedNativeOnly()
+ || isFileEncryptedEmulatedOnly();
+ }
+
/** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
final IMountService mountService = IMountService.Stub.asInterface(
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 795012d..9d14478 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -887,8 +887,7 @@
* @return true if device encryption is enabled
*/
public static boolean isDeviceEncryptionEnabled() {
- final String status = SystemProperties.get("ro.crypto.state", "unsupported");
- return "encrypted".equalsIgnoreCase(status);
+ return StorageManager.isEncrypted();
}
/**
@@ -896,7 +895,7 @@
* @return true if device is file encrypted
*/
public static boolean isFileEncryptionEnabled() {
- return StorageManager.isFileBasedEncryptionEnabled();
+ return StorageManager.isFileEncryptedNativeOrEmulated();
}
/**
diff --git a/core/java/com/android/server/BootReceiver.java b/core/java/com/android/server/BootReceiver.java
index ab75b7c..6d6c162 100644
--- a/core/java/com/android/server/BootReceiver.java
+++ b/core/java/com/android/server/BootReceiver.java
@@ -29,6 +29,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
+import android.os.storage.StorageManager;
import android.provider.Downloads;
import android.util.AtomicFile;
import android.util.Slog;
@@ -143,8 +144,7 @@
HashMap<String, Long> timestamps = readTimestamps();
if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) {
- if ("encrypted".equals(SystemProperties.get("ro.crypto.state"))
- && "trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))) {
+ if (StorageManager.inCryptKeeperBounce()) {
// Encrypted, first boot to get PIN/pattern/password so data is tmpfs
// Don't set ro.runtime.firstboot so that we will do this again
// when data is properly mounted
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6029c23..312d3c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -684,7 +684,7 @@
doKeyguardLocked(null);
mUpdateMonitor.registerCallback(mUpdateCallback);
}
- mIsPerUserLock = StorageManager.isFileBasedEncryptionEnabled();
+ mIsPerUserLock = StorageManager.isFileEncryptedNativeOrEmulated();
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
maybeSendUserPresentBroadcast();
diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java
index 9313148..8ca675a 100644
--- a/services/core/java/com/android/server/DiskStatsService.java
+++ b/services/core/java/com/android/server/DiskStatsService.java
@@ -80,7 +80,7 @@
reportFreeSpace(Environment.getDownloadCacheDirectory(), "Cache", pw);
reportFreeSpace(new File("/system"), "System", pw);
- if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+ if (StorageManager.isFileEncryptedNativeOnly()) {
pw.println("File-based Encryption: true");
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index a3322fc..4536e04 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -839,11 +839,11 @@
Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady
+ ", mDaemonConnected=" + mDaemonConnected);
if (mSystemReady && mDaemonConnected
- && !StorageManager.isNativeFileBasedEncryptionEnabled()) {
+ && !StorageManager.isFileEncryptedNativeOnly()) {
// When booting a device without native support, make sure that our
// user directories are locked or unlocked based on the current
// emulation status.
- final boolean initLocked = StorageManager.isEmulatedFileBasedEncryptionEnabled();
+ final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
for (UserInfo user : users) {
@@ -1940,7 +1940,7 @@
waitForReady();
if ((mask & StorageManager.DEBUG_EMULATE_FBE) != 0) {
- if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+ if (StorageManager.isFileEncryptedNativeOnly()) {
throw new IllegalStateException(
"Emulation not available on device with native FBE");
}
@@ -2811,7 +2811,7 @@
@Override
public boolean isUserKeyUnlocked(int userId) {
- if (StorageManager.isFileBasedEncryptionEnabled()) {
+ if (StorageManager.isFileEncryptedNativeOrEmulated()) {
synchronized (mLock) {
return ArrayUtils.contains(mLocalUnlockedUsers, userId);
}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 73d8bdd..30e0ceb 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -446,7 +446,7 @@
// Some devices can be field-converted to FBE, so offer to splice in
// those features if not already defined by the static config
- if (StorageManager.isNativeFileBasedEncryptionEnabled()) {
+ if (StorageManager.isFileEncryptedNativeOnly()) {
addFeature(PackageManager.FEATURE_FILE_BASED_ENCRYPTION, 0);
addFeature(PackageManager.FEATURE_SECURELY_REMOVES_USERS, 0);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0317641..3105134 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -10884,7 +10884,7 @@
* belonging to any running apps.
*/
private void installEncryptionUnawareProviders(int userId) {
- if (!StorageManager.isFileBasedEncryptionEnabled()) {
+ if (!StorageManager.isFileEncryptedNativeOrEmulated()) {
// TODO: eventually pivot this back to look at current user state,
// similar to the comment in UserManager.isUserUnlocked(), but for
// now, if we started apps when "unlocked" then unaware providers
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index addffd3..5f231ed 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -620,7 +620,7 @@
}
} else {
Slog.w(TAG, "Mount service not published; guessing locked state based on property");
- return !StorageManager.isFileBasedEncryptionEnabled();
+ return !StorageManager.isFileEncryptedNativeOrEmulated();
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e180e050..debe072 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2449,7 +2449,7 @@
// since core system apps like SettingsProvider and SystemUI
// can't wait for user to start
final int storageFlags;
- if (StorageManager.isFileBasedEncryptionEnabled()) {
+ if (StorageManager.isFileEncryptedNativeOrEmulated()) {
storageFlags = StorageManager.FLAG_STORAGE_DE;
} else {
storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
@@ -3231,7 +3231,7 @@
* Return if the user key is currently unlocked.
*/
private boolean isUserKeyUnlocked(int userId) {
- if (StorageManager.isFileBasedEncryptionEnabled()) {
+ if (StorageManager.isFileEncryptedNativeOrEmulated()) {
final IMountService mount = IMountService.Stub
.asInterface(ServiceManager.getService("mount"));
if (mount == null) {
@@ -18313,7 +18313,7 @@
* the app.
*/
private boolean maybeMigrateAppData(String volumeUuid, int userId, PackageParser.Package pkg) {
- if (pkg.isSystemApp() && !StorageManager.isFileBasedEncryptionEnabled()
+ if (pkg.isSystemApp() && !StorageManager.isFileEncryptedNativeOrEmulated()
&& PackageManager.APPLY_FORCE_DEVICE_ENCRYPTED) {
final int storageTarget = pkg.applicationInfo.isForceDeviceEncrypted()
? StorageManager.FLAG_STORAGE_DE : StorageManager.FLAG_STORAGE_CE;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d979675..32343cc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1636,9 +1636,7 @@
}
// Still at the first stage of CryptKeeper double bounce, mOwners.hasDeviceOwner is
// always false at this point.
- if ("encrypted".equals(mInjector.systemPropertiesGet("ro.crypto.state"))
- && "trigger_restart_min_framework".equals(
- mInjector.systemPropertiesGet("vold.decrypt"))){
+ if (StorageManager.inCryptKeeperBounce()) {
return;
}
@@ -4854,17 +4852,11 @@
* {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
*/
private int getEncryptionStatus() {
- String status = mInjector.systemPropertiesGet("ro.crypto.state", "unsupported");
- if ("encrypted".equalsIgnoreCase(status)) {
- final long token = mInjector.binderClearCallingIdentity();
- try {
- return LockPatternUtils.isDeviceEncrypted()
- ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
- : DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
- } finally {
- mInjector.binderRestoreCallingIdentity(token);
- }
- } else if ("unencrypted".equalsIgnoreCase(status)) {
+ if (!StorageManager.isNonDefaultBlockEncrypted()) {
+ return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_DEFAULT_KEY;
+ } else if (StorageManager.isEncrypted()) {
+ return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
+ } else if (StorageManager.isEncryptable()) {
return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
} else {
return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;