diff options
| -rw-r--r-- | api/current.txt | 1 | ||||
| -rw-r--r-- | api/system-current.txt | 1 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManager.java | 2 | ||||
| -rw-r--r-- | core/java/android/content/Intent.java | 8 | ||||
| -rw-r--r-- | core/java/android/content/pm/ApplicationInfo.java | 12 | ||||
| -rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 2 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/LockSettingsService.java | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/MountService.java | 18 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/UserController.java | 26 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 46 |
13 files changed, 124 insertions, 23 deletions
diff --git a/api/current.txt b/api/current.txt index 73962f8fdba7..fc95ca3dfd8a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -8344,6 +8344,7 @@ package android.content { field public static final java.lang.String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND"; field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE"; field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT"; + field public static final java.lang.String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED"; field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW"; field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; field public static final deprecated java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED"; diff --git a/api/system-current.txt b/api/system-current.txt index c4d99b8ef195..409a7d53b2cf 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8602,6 +8602,7 @@ package android.content { field public static final java.lang.String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND"; field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE"; field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT"; + field public static final java.lang.String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED"; field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW"; field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; field public static final deprecated java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED"; diff --git a/api/test-current.txt b/api/test-current.txt index 73962f8fdba7..fc95ca3dfd8a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -8344,6 +8344,7 @@ package android.content { field public static final java.lang.String ACTION_USER_FOREGROUND = "android.intent.action.USER_FOREGROUND"; field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE"; field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT"; + field public static final java.lang.String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED"; field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW"; field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND"; field public static final deprecated java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED"; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index f7aee759f3b9..f1a7de81d5ac 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -3084,7 +3084,7 @@ public class ActivityManager { /** {@hide} */ public static final int FLAG_OR_STOPPED = 1 << 0; /** {@hide} */ - public static final int FLAG_WITH_AMNESIA = 1 << 1; + public static final int FLAG_AND_LOCKED = 1 << 1; /** * Return whether the given user is actively running. This means that diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 4a7cbc7b0517..e25f1d7804ce 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2877,6 +2877,14 @@ public class Intent implements Parcelable, Cloneable { "android.intent.action.USER_SWITCHED"; /** + * Broadcast Action: Sent when the credential-encrypted private storage has + * become unlocked for the target user. This is only sent to registered + * receivers, not manifest receivers. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED"; + + /** * Broadcast sent to the system when a user's information changes. Carries an extra * {@link #EXTRA_USER_HANDLE} to indicate which user's information changed. * This is only sent to registered receivers, not manifest receivers. It is sent to all users. diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 1996e0feb401..65e5945a9421 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -487,6 +487,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public static final int PRIVATE_FLAG_AUTOPLAY = 1 << 7; /** + * When set, at least one component inside this application is encryption aware. + * + * @hide + */ + public static final int PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE = 1 << 8; + + /** * Private/hidden flags. See {@code PRIVATE_FLAG_...} constants. * {@hide} */ @@ -1054,6 +1061,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_ENCRYPTION_AWARE) != 0; } + /** @hide */ + public boolean isPartiallyEncryptionAware() { + return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE) != 0; + } + /** * @hide */ diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 6fe1efd72ba3..b9a42eb21eee 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -59,7 +59,7 @@ import android.content.IntentSender; * {@hide} */ interface IPackageManager { - boolean isPackageFrozen(String packageName); + void checkPackageStartable(String packageName, int userId); boolean isPackageAvailable(String packageName, int userId); PackageInfo getPackageInfo(String packageName, int flags, int userId); int getPackageUid(String packageName, int userId); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 838da37c365d..17af944545b8 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3262,6 +3262,11 @@ public class PackageParser { owner.applicationInfo.isEncryptionAware()); } + if (a.info.encryptionAware) { + owner.applicationInfo.privateFlags |= + ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE; + } + sa.recycle(); if (receiver && (owner.applicationInfo.privateFlags @@ -3663,6 +3668,10 @@ public class PackageParser { p.info.encryptionAware = sa.getBoolean( R.styleable.AndroidManifestProvider_encryptionAware, owner.applicationInfo.isEncryptionAware()); + if (p.info.encryptionAware) { + owner.applicationInfo.privateFlags |= + ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE; + } sa.recycle(); @@ -3947,6 +3956,10 @@ public class PackageParser { s.info.encryptionAware = sa.getBoolean( R.styleable.AndroidManifestService_encryptionAware, owner.applicationInfo.isEncryptionAware()); + if (s.info.encryptionAware) { + owner.applicationInfo.privateFlags |= + ApplicationInfo.PRIVATE_FLAG_PARTIALLY_ENCRYPTION_AWARE; + } sa.recycle(); diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index da8152861edf..d6c6f13b606a 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -16,6 +16,8 @@ package com.android.server; +import android.app.ActivityManagerNative; +import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; import android.app.backup.BackupManager; import android.app.trust.IStrongAuthTracker; @@ -388,6 +390,13 @@ public class LockSettingsService extends ILockSettings.Stub { } } + private void unlockUser(int userId, byte[] token) { + try { + ActivityManagerNative.getDefault().unlockUser(userId, token); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } private byte[] getCurrentHandle(int userId) { CredentialHash credential; @@ -612,6 +621,7 @@ public class LockSettingsService extends ILockSettings.Stub { byte[] hash = credentialUtil.toHash(credential, userId); if (Arrays.equals(hash, storedHash.hash)) { unlockKeystore(credentialUtil.adjustForKeystore(credential), userId); + unlockUser(userId, null); // migrate credential to GateKeeper credentialUtil.setCredential(credential, null, userId); if (!hasChallenge) { @@ -664,6 +674,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) { // credential has matched unlockKeystore(credential, userId); + unlockUser(userId, null); if (shouldReEnroll) { credentialUtil.setCredential(credential, credential, userId); } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index a32bb2f213bd..bd43a71173d7 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -781,6 +781,7 @@ class MountService extends IMountService.Stub } private void handleSystemReady() { + initIfReadyAndConnected(); resetIfReadyAndConnected(); // Start scheduling nominally-daily fstrim operations @@ -828,6 +829,22 @@ class MountService extends IMountService.Stub mVolumes.put(internal.id, internal); } + private void initIfReadyAndConnected() { + Slog.d(TAG, "Thinking about init, mSystemReady=" + mSystemReady + + ", mDaemonConnected=" + mDaemonConnected); + if (mSystemReady && mDaemonConnected && StorageManager.isFileBasedEncryptionEnabled()) { + final List<UserInfo> users = mContext.getSystemService(UserManager.class) + .getUsers(); + for (UserInfo user : users) { + try { + mCryptConnector.execute("cryptfs", "lock_user_key", user.id); + } catch (NativeDaemonConnectorException e) { + Slog.w(TAG, "Failed to init vold", e); + } + } + } + } + private void resetIfReadyAndConnected() { Slog.d(TAG, "Thinking about reset, mSystemReady=" + mSystemReady + ", mDaemonConnected=" + mDaemonConnected); @@ -928,6 +945,7 @@ class MountService extends IMountService.Stub } private void handleDaemonConnected() { + initIfReadyAndConnected(); resetIfReadyAndConnected(); /* diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 557b3869a886..99470c808b8f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3356,10 +3356,8 @@ public final class ActivityManagerService extends ActivityManagerNative try { try { - if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) { - // This is caught below as if we had failed to fork zygote - throw new RuntimeException("Package " + app.info.packageName + " is frozen!"); - } + final int userId = UserHandle.getUserId(app.uid); + AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index b30905e4d590..9c2914976bac 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -624,6 +624,23 @@ final class UserController { throw new SecurityException(msg); } + final long binderToken = Binder.clearCallingIdentity(); + try { + return unlockUserCleared(userId, token); + } finally { + Binder.restoreCallingIdentity(binderToken); + } + } + + boolean unlockUserCleared(final int userId, byte[] token) { + synchronized (mService) { + final UserState uss = mStartedUsers.get(userId); + if (uss.unlocked) { + // Bail early when already unlocked + return true; + } + } + final UserInfo userInfo = getUserInfo(userId); final IMountService mountService = IMountService.Stub .asInterface(ServiceManager.getService("mount")); @@ -631,7 +648,7 @@ final class UserController { mountService.unlockUserKey(userId, userInfo.serialNumber, token); } catch (RemoteException e) { Slog.w(TAG, "Failed to unlock: " + e.getMessage()); - throw e.rethrowAsRuntimeException(); + return false; } synchronized (mService) { @@ -639,6 +656,11 @@ final class UserController { updateUserUnlockedState(uss); } + final Intent intent = new Intent(Intent.ACTION_USER_UNLOCKED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); + mService.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null, + AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, userId); + return true; } @@ -1011,7 +1033,7 @@ final class UserController { if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) { return true; } - if ((flags & ActivityManager.FLAG_WITH_AMNESIA) != 0) { + if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) { // If user is currently locked, we fall through to default "running" // behavior below if (state.unlocked) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4bc79cb13fce..c7d1171cd4c2 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2800,15 +2800,24 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public boolean isPackageFrozen(String packageName) { + public void checkPackageStartable(String packageName, int userId) { + final boolean userKeyUnlocked = isUserKeyUnlocked(userId); + synchronized (mPackages) { final PackageSetting ps = mSettings.mPackages.get(packageName); - if (ps != null) { - return ps.frozen; + if (ps == null) { + throw new SecurityException("Package " + packageName + " was not found!"); + } + + if (ps.frozen) { + throw new SecurityException("Package " + packageName + " is currently frozen!"); + } + + if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isEncryptionAware() + || ps.pkg.applicationInfo.isPartiallyEncryptionAware())) { + throw new SecurityException("Package " + packageName + " is not encryption aware!"); } } - Slog.w(TAG, "Package " + packageName + " is missing; assuming frozen"); - return true; } @Override @@ -3143,29 +3152,36 @@ public class PackageManagerService extends IPackageManager.Stub { } /** - * Augment the given flags depending on current user running state. This is - * purposefully done before acquiring {@link #mPackages} lock. + * Return if the user key is currently unlocked. */ - private int augmentFlagsForUser(int flags, int userId) { + private boolean isUserKeyUnlocked(int userId) { if (StorageManager.isFileBasedEncryptionEnabled()) { final IMountService mount = IMountService.Stub .asInterface(ServiceManager.getService("mount")); if (mount == null) { - // We must be early in boot, so the best we can do is assume the - // user is fully running. - Slog.w(TAG, "Early during boot, assuming not encrypted"); - return flags; + Slog.w(TAG, "Early during boot, assuming locked"); + return false; } final long token = Binder.clearCallingIdentity(); try { - if (!mount.isUserKeyUnlocked(userId)) { - flags |= PackageManager.MATCH_ENCRYPTION_AWARE_ONLY; - } + return mount.isUserKeyUnlocked(userId); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } finally { Binder.restoreCallingIdentity(token); } + } else { + return true; + } + } + + /** + * Augment the given flags depending on current user running state. This is + * purposefully done before acquiring {@link #mPackages} lock. + */ + private int augmentFlagsForUser(int flags, int userId) { + if (!isUserKeyUnlocked(userId)) { + flags |= PackageManager.MATCH_ENCRYPTION_AWARE_ONLY; } return flags; } |