OSDN Git Service

Introduce "unlocking" vs "unlocked" nuance.
authorJeff Sharkey <jsharkey@android.com>
Wed, 27 Apr 2016 22:00:41 +0000 (16:00 -0600)
committerJeff Sharkey <jsharkey@android.com>
Thu, 28 Apr 2016 16:51:39 +0000 (10:51 -0600)
There is a narrow window of time during user unlock where we're
reconciling user storage and dispatching the "unlock" status to
various internal system services.  While in this "unlocking" state,
apps need to be told that the user still isn't actually "unlocked"
so they don't try making calls to AccountManager, etc.

The majority of internal services are interested in merging together
both the "unlocking" and "unlocked" state, so update them.

Clarify naming in AccountManagerService to make it clear that a local
list is being used, which mirrors the naming in MountService.

To match UX/PM requested behavior, move PRE_BOOT_COMPLETED dispatch
after the user is unlocked, but block BOOT_COMPLETED dispatch until
after all PRE_BOOT receivers are finished to avoid ANRs.

Bug: 2804094728164677
Change-Id: I57af2351633d9159f4483f19657ce0b62118d1ce

20 files changed:
core/java/android/app/ActivityManager.java
core/java/android/os/UserManager.java
core/java/android/os/storage/StorageManager.java
core/java/android/provider/CallLog.java
core/res/res/values/symbols.xml
services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
services/core/java/com/android/server/InputMethodManagerService.java
services/core/java/com/android/server/LockSettingsService.java
services/core/java/com/android/server/MountService.java
services/core/java/com/android/server/TextServicesManagerService.java
services/core/java/com/android/server/accounts/AccountManagerService.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityStarter.java
services/core/java/com/android/server/am/UserController.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/pm/UserManagerService.java
services/core/java/com/android/server/search/SearchManagerService.java
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
services/print/java/com/android/server/print/PrintManagerService.java

index d440017..ff8cf66 100644 (file)
@@ -3430,6 +3430,8 @@ public class ActivityManager {
     public static final int FLAG_AND_LOCKED = 1 << 1;
     /** {@hide} */
     public static final int FLAG_AND_UNLOCKED = 1 << 2;
+    /** {@hide} */
+    public static final int FLAG_AND_UNLOCKING_OR_UNLOCKED = 1 << 3;
 
     /**
      * Return whether the given user is actively running.  This means that
@@ -3449,26 +3451,6 @@ public class ActivityManager {
     }
 
     /** {@hide} */
-    public boolean isUserRunningAndLocked(int userId) {
-        try {
-            return ActivityManagerNative.getDefault().isUserRunning(userId,
-                    ActivityManager.FLAG_AND_LOCKED);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
-    public boolean isUserRunningAndUnlocked(int userId) {
-        try {
-            return ActivityManagerNative.getDefault().isUserRunning(userId,
-                    ActivityManager.FLAG_AND_UNLOCKED);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /** {@hide} */
     public boolean isVrModePackageEnabled(ComponentName component) {
         try {
             return ActivityManagerNative.getDefault().isVrModePackageEnabled(component);
index dd53cbb..d55201f 100644 (file)
@@ -36,7 +36,6 @@ import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.view.WindowManager.LayoutParams;
@@ -984,10 +983,27 @@ public class UserManager {
 
     /** {@hide} */
     public boolean isUserUnlocked(@UserIdInt int userId) {
-        // TODO: eventually pivot this back to look at ActivityManager state,
-        // but there is race where we can start a non-encryption-aware launcher
-        // before that lifecycle has entered the running unlocked state.
-        return mContext.getSystemService(StorageManager.class).isUserKeyUnlocked(userId);
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(userId,
+                    ActivityManager.FLAG_AND_UNLOCKED);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
+    public boolean isUserUnlockingOrUnlocked(UserHandle user) {
+        return isUserUnlockingOrUnlocked(user.getIdentifier());
+    }
+
+    /** {@hide} */
+    public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) {
+        try {
+            return ActivityManagerNative.getDefault().isUserRunning(userId,
+                    ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
     }
 
     /**
index f68e227..fbf7b26 100644 (file)
@@ -25,6 +25,7 @@ import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.PackageManager;
+import android.os.Binder;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.Handler;
@@ -1062,11 +1063,20 @@ public class StorageManager {
     }
 
     /** {@hide} */
-    public boolean isUserKeyUnlocked(int userId) {
+    public static boolean isUserKeyUnlocked(int userId) {
+        final IMountService mount = IMountService.Stub
+                .asInterface(ServiceManager.getService("mount"));
+        if (mount == null) {
+            Slog.w(TAG, "Early during boot, assuming locked");
+            return false;
+        }
+        final long token = Binder.clearCallingIdentity();
         try {
-            return mMountService.isUserKeyUnlocked(userId);
+            return mount.isUserKeyUnlocked(userId);
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            throw e.rethrowAsRuntimeException();
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
index 8a0759f..893eb37 100644 (file)
@@ -824,6 +824,8 @@ public class CallLog {
                 UserHandle user, ContentValues values) {
             final ContentResolver resolver = context.getContentResolver();
 
+            // Since we're doing this operation on behalf of an app, we only
+            // want to use the actual "unlocked" state.
             final Uri uri = ContentProvider.maybeAddUserId(
                     userManager.isUserUnlocked(user) ? CONTENT_URI : SHADOW_CONTENT_URI,
                     user.getIdentifier());
index 4d86a92..14c17f3 100644 (file)
   <java-symbol type="string" name="profile_encrypted_message" />
   <java-symbol type="drawable" name="ic_user_secure" />
 
+  <java-symbol type="string" name="android_upgrading_notification_title" />
+  <java-symbol type="string" name="android_upgrading_notification_body" />
+
   <java-symbol type="string" name="usb_mtp_launch_notification_title" />
   <java-symbol type="string" name="usb_mtp_launch_notification_description" />
 
index fc2e95d..ae31438 100644 (file)
@@ -1245,8 +1245,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
     private void updateServicesLocked(UserState userState) {
         Map<ComponentName, Service> componentNameToServiceMap =
                 userState.mComponentNameToServiceMap;
-        boolean isUnlocked = mContext.getSystemService(UserManager.class)
-                .isUserUnlocked(userState.mUserId);
+        boolean isUnlockingOrUnlocked = mContext.getSystemService(UserManager.class)
+                .isUserUnlockingOrUnlocked(userState.mUserId);
 
         for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
             AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
@@ -1256,7 +1256,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
             Service service = componentNameToServiceMap.get(componentName);
 
             // Ignore non-encryption-aware services until user is unlocked
-            if (!isUnlocked && !installedService.isDirectBootAware()) {
+            if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) {
                 Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
                 continue;
             }
index 0428ecf..7b9d445 100644 (file)
@@ -335,7 +335,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                     Provider provider = installedProviders.get(i);
 
                     final int userId = provider.getUserId();
-                    if (!mUserManager.isUserUnlocked(userId) ||
+                    if (!mUserManager.isUserUnlockingOrUnlocked(userId) ||
                             isProfileWithLockedParent(userId)) {
                         continue;
                     }
@@ -369,7 +369,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
     }
 
     private void onPackageBroadcastReceived(Intent intent, int userId) {
-        if (!mUserManager.isUserUnlocked(userId) ||
+        if (!mUserManager.isUserUnlockingOrUnlocked(userId) ||
                 isProfileWithLockedParent(userId)) {
             return;
         }
@@ -455,7 +455,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
      * userId must be the group parent.
      */
     private void reloadWidgetsMaskedStateForGroup(int userId) {
-        if (!mUserManager.isUserUnlocked(userId)) {
+        if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
             return;
         }
         synchronized (mLock) {
@@ -472,7 +472,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
         try {
             UserInfo user  = mUserManager.getUserInfo(userId);
 
-            boolean lockedProfile = !mUserManager.isUserUnlocked(userId);
+            boolean lockedProfile = !mUserManager.isUserUnlockingOrUnlocked(userId);
             boolean quietProfile = user.isQuietModeEnabled();
             final int N = mProviders.size();
             for (int i = 0; i < N; i++) {
@@ -656,7 +656,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
     }
 
     private void ensureGroupStateLoadedLocked(int userId) {
-        if (!mUserManager.isUserUnlocked(userId)) {
+        if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
             throw new IllegalStateException(
                     "User " + userId + " must be unlocked for widgets to be available");
         }
@@ -3363,7 +3363,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
             if (userInfo != null && userInfo.isManagedProfile()) {
                 UserInfo parentInfo = mUserManager.getProfileParent(userId);
                 if (parentInfo != null
-                        && !mUserManager.isUserUnlocked(parentInfo.getUserHandle())) {
+                        && !mUserManager.isUserUnlockingOrUnlocked(parentInfo.getUserHandle())) {
                     return true;
                 }
             }
@@ -3378,7 +3378,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
         if (userInfo != null && userInfo.isManagedProfile()) {
             UserInfo parentInfo = mUserManager.getProfileParent(userId);
             if (parentInfo != null
-                    && mUserManager.isUserUnlocked(parentInfo.getUserHandle())) {
+                    && mUserManager.isUserUnlockingOrUnlocked(parentInfo.getUserHandle())) {
                 return true;
             }
         }
index 79d16da..a584f70 100644 (file)
@@ -1020,7 +1020,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
         // If the system is not ready or the device is not yed unlocked by the user, then we use
         // copy-on-write settings.
         final boolean useCopyOnWriteSettings =
-                !mSystemReady || !mUserManager.isUserUnlocked(newUserId);
+                !mSystemReady || !mUserManager.isUserUnlockingOrUnlocked(newUserId);
         mSettings.switchCurrentUser(newUserId, useCopyOnWriteSettings);
         updateCurrentProfileIds();
         // InputMethodFileManager should be reset when the user is changed
@@ -1077,7 +1077,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
                 mSystemReady = true;
                 final int currentUserId = mSettings.getCurrentUserId();
                 mSettings.switchCurrentUser(currentUserId,
-                        !mUserManager.isUserUnlocked(currentUserId));
+                        !mUserManager.isUserUnlockingOrUnlocked(currentUserId));
                 mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
                 mNotificationManager = mContext.getSystemService(NotificationManager.class);
                 mStatusBar = statusBar;
index a3ef6b6..c912b11 100644 (file)
@@ -256,13 +256,13 @@ public class LockSettingsService extends ILockSettings.Stub {
         for (int i = 0; i < users.size(); i++) {
             UserInfo user = users.get(i);
             UserHandle userHandle = user.getUserHandle();
-            if (!mUserManager.isUserUnlocked(userHandle)) {
+            if (!mUserManager.isUserUnlockingOrUnlocked(userHandle)) {
                 if (!user.isManagedProfile()) {
                     showEncryptionNotification(userHandle);
                 } else {
                     UserInfo parent = mUserManager.getProfileParent(user.id);
                     if (parent != null &&
-                            mUserManager.isUserUnlocked(parent.getUserHandle()) &&
+                            mUserManager.isUserUnlockingOrUnlocked(parent.getUserHandle()) &&
                             !mUserManager.isQuietModeEnabled(userHandle)) {
                         // Only show notifications for managed profiles once their parent
                         // user is unlocked.
@@ -350,7 +350,7 @@ public class LockSettingsService extends ILockSettings.Stub {
             UserInfo profile = profiles.get(i);
             if (profile.isManagedProfile()) {
                 UserHandle userHandle = profile.getUserHandle();
-                if (!mUserManager.isUserUnlocked(userHandle) &&
+                if (!mUserManager.isUserUnlockingOrUnlocked(userHandle) &&
                         !mUserManager.isQuietModeEnabled(userHandle)) {
                     showEncryptionNotificationForProfile(userHandle);
                 }
index ec05dae..b0581aa 100644 (file)
@@ -2816,17 +2816,19 @@ class MountService extends IMountService.Stub
         enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
         waitForReady();
 
-        // When a user has secure lock screen, require a challenge token to
-        // actually unlock. This check is mostly in place for emulation mode.
-        if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(token)) {
-            throw new IllegalStateException("Token required to unlock secure user " + userId);
-        }
+        if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+            // When a user has secure lock screen, require a challenge token to
+            // actually unlock. This check is mostly in place for emulation mode.
+            if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(token)) {
+                throw new IllegalStateException("Token required to unlock secure user " + userId);
+            }
 
-        try {
-            mCryptConnector.execute("cryptfs", "unlock_user_key", userId, serialNumber,
-                    encodeBytes(token), encodeBytes(secret));
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            try {
+                mCryptConnector.execute("cryptfs", "unlock_user_key", userId, serialNumber,
+                        encodeBytes(token), encodeBytes(secret));
+            } catch (NativeDaemonConnectorException e) {
+                throw e.rethrowAsParcelableException();
+            }
         }
 
         synchronized (mLock) {
@@ -2852,12 +2854,8 @@ class MountService extends IMountService.Stub
 
     @Override
     public boolean isUserKeyUnlocked(int userId) {
-        if (StorageManager.isFileEncryptedNativeOrEmulated()) {
-            synchronized (mLock) {
-                return ArrayUtils.contains(mLocalUnlockedUsers, userId);
-            }
-        } else {
-            return true;
+        synchronized (mLock) {
+            return ArrayUtils.contains(mLocalUnlockedUsers, userId);
         }
     }
 
index a628747..4b0d4be 100644 (file)
@@ -166,7 +166,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
         mMonitor = new TextServicesMonitor();
         mMonitor.register(context, null, true);
         final boolean useCopyOnWriteSettings =
-                !mSystemReady || !mUserManager.isUserUnlocked(userId);
+                !mSystemReady || !mUserManager.isUserUnlockingOrUnlocked(userId);
         mSettings = new TextServicesSettings(context.getContentResolver(), userId,
                 useCopyOnWriteSettings);
 
@@ -176,7 +176,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
 
     private void resetInternalState(@UserIdInt int userId) {
         final boolean useCopyOnWriteSettings =
-                !mSystemReady || !mUserManager.isUserUnlocked(userId);
+                !mSystemReady || !mUserManager.isUserUnlockingOrUnlocked(userId);
         mSettings.switchCurrentUser(userId, useCopyOnWriteSettings);
         updateCurrentProfileIds();
         unbindServiceLocked();
index 480da72..96214d6 100644 (file)
@@ -304,7 +304,7 @@ public class AccountManagerService
     }
 
     private final SparseArray<UserAccounts> mUsers = new SparseArray<>();
-    private final SparseBooleanArray mUnlockedUsers = new SparseBooleanArray();
+    private final SparseBooleanArray mLocalUnlockedUsers = new SparseBooleanArray();
 
     private static AtomicReference<AccountManagerService> sThis = new AtomicReference<>();
     private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
@@ -424,7 +424,7 @@ public class AccountManagerService
         if (Log.isLoggable(TAG, Log.DEBUG)) {
             Log.d(TAG, "validateAccountsInternal " + accounts.userId
                     + " isCeDatabaseAttached=" + accounts.openHelper.isCeDatabaseAttached()
-                    + " userLocked=" + mUnlockedUsers.get(accounts.userId));
+                    + " userLocked=" + mLocalUnlockedUsers.get(accounts.userId));
         }
         if (invalidateAuthenticatorCache) {
             mAuthenticatorCache.invalidateCache(accounts.userId);
@@ -575,7 +575,7 @@ public class AccountManagerService
                 validateAccounts = true;
             }
             // open CE database if necessary
-            if (!accounts.openHelper.isCeDatabaseAttached() && mUnlockedUsers.get(userId)) {
+            if (!accounts.openHelper.isCeDatabaseAttached() && mLocalUnlockedUsers.get(userId)) {
                 Log.i(TAG, "User " + userId + " is unlocked - opening CE database");
                 synchronized (accounts.cacheLock) {
                     File preNDatabaseFile = new File(getPreNDatabaseName(userId));
@@ -648,8 +648,8 @@ public class AccountManagerService
         synchronized (mUsers) {
             accounts = mUsers.get(userId);
             mUsers.remove(userId);
-            userUnlocked = mUnlockedUsers.get(userId);
-            mUnlockedUsers.delete(userId);
+            userUnlocked = mLocalUnlockedUsers.get(userId);
+            mLocalUnlockedUsers.delete(userId);
         }
         if (accounts != null) {
             synchronized (accounts.cacheLock) {
@@ -686,7 +686,7 @@ public class AccountManagerService
             Log.v(TAG, "onUserUnlocked " + userId);
         }
         synchronized (mUsers) {
-            mUnlockedUsers.put(userId, true);
+            mLocalUnlockedUsers.put(userId, true);
         }
         if (userId < 1) return;
         syncSharedAccounts(userId);
@@ -746,7 +746,7 @@ public class AccountManagerService
         if (account == null) {
             return null;
         }
-        if (!isUserUnlocked(accounts.userId)) {
+        if (!isLocalUnlockedUser(accounts.userId)) {
             Log.w(TAG, "Password is not available - user " + accounts.userId + " data is locked");
             return null;
         }
@@ -828,7 +828,7 @@ public class AccountManagerService
                     account.type);
             throw new SecurityException(msg);
         }
-        if (!isUserUnlocked(userId)) {
+        if (!isLocalUnlockedUser(userId)) {
             Log.w(TAG, "User " + userId + " data is locked. callingUid " + callingUid);
             return null;
         }
@@ -1109,7 +1109,7 @@ public class AccountManagerService
         if (account == null) {
             return false;
         }
-        if (!isUserUnlocked(accounts.userId)) {
+        if (!isLocalUnlockedUser(accounts.userId)) {
             Log.w(TAG, "Account " + account + " cannot be added - user " + accounts.userId
                     + " is locked. callingUid=" + callingUid);
             return false;
@@ -1176,9 +1176,9 @@ public class AccountManagerService
         return true;
     }
 
-    private boolean isUserUnlocked(int userId) {
+    private boolean isLocalUnlockedUser(int userId) {
         synchronized (mUsers) {
-            return mUnlockedUsers.get(userId);
+            return mLocalUnlockedUsers.get(userId);
         }
     }
 
@@ -1193,7 +1193,7 @@ public class AccountManagerService
         for (UserInfo user : users) {
             if (user.isRestricted() && (parentUserId == user.restrictedProfileParentId)) {
                 addSharedAccountAsUser(account, user.id);
-                if (getUserManager().isUserUnlocked(user.id)) {
+                if (isLocalUnlockedUser(user.id)) {
                     mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
                             MESSAGE_COPY_SHARED_ACCOUNT, parentUserId, user.id, account));
                 }
@@ -1597,7 +1597,7 @@ public class AccountManagerService
 
     private boolean removeAccountInternal(UserAccounts accounts, Account account, int callingUid) {
         int deleted;
-        boolean userUnlocked = isUserUnlocked(accounts.userId);
+        boolean userUnlocked = isLocalUnlockedUser(accounts.userId);
         if (!userUnlocked) {
             Slog.i(TAG, "Removing account " + account + " while user "+ accounts.userId
                     + " is still locked. CE data will be removed later");
@@ -1792,7 +1792,7 @@ public class AccountManagerService
                     account.type);
             throw new SecurityException(msg);
         }
-        if (!isUserUnlocked(userId)) {
+        if (!isLocalUnlockedUser(userId)) {
             Log.w(TAG, "Authtoken not available - user " + userId + " data is locked. callingUid "
                     + callingUid);
             return null;
@@ -4037,8 +4037,7 @@ public class AccountManagerService
                 return false;
             }
 
-            final ActivityManager am = mContext.getSystemService(ActivityManager.class);
-            if (am.isUserRunningAndLocked(mAccounts.userId)
+            if (!isLocalUnlockedUser(mAccounts.userId)
                     && !authenticatorInfo.componentInfo.directBootAware) {
                 Slog.w(TAG, "Blocking binding to authenticator " + authenticatorInfo.componentName
                         + " which isn't encryption aware");
index 9d7ddc7..21a9f2c 100644 (file)
@@ -1946,9 +1946,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                     startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
                 }
                 installEncryptionUnawareProviders(userId);
-                if (msg.obj instanceof ProgressReporter) {
-                    ((ProgressReporter) msg.obj).finish();
-                }
+                mUserController.finishUserUnlocked((UserState) msg.obj);
                 break;
             }
             case SYSTEM_USER_CURRENT_MSG: {
@@ -6304,7 +6302,11 @@ public final class ActivityManagerService extends ActivityManagerNative
         app.debugging = false;
         app.cached = false;
         app.killedByAm = false;
-        app.unlocked = mContext.getSystemService(UserManager.class).isUserUnlocked(app.userId);
+
+        // We carefully use the same state that PackageManager uses for
+        // filtering, since we use this flag to decide if we need to install
+        // providers when user is unlocked later
+        app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
 
         mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
 
@@ -11024,14 +11026,6 @@ public final class ActivityManagerService extends ActivityManagerNative
      * belonging to any running apps.
      */
     private void installEncryptionUnawareProviders(int userId) {
-        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
-            // have already been spun up.
-            return;
-        }
-
         // We're only interested in providers that are encryption unaware, and
         // we don't care about uninstalled apps, since there's no way they're
         // running at this point.
index 6622b34..572653b 100644 (file)
@@ -683,8 +683,8 @@ class ActivityStarter {
                     Binder.restoreCallingIdentity(token);
                 }
                 if (parent != null
-                        && userManager.isUserUnlocked(parent.getUserHandle())
-                        && !userManager.isUserUnlocked(userInfo.getUserHandle())) {
+                        && userManager.isUserUnlockingOrUnlocked(parent.getUserHandle())
+                        && !userManager.isUserUnlockingOrUnlocked(userInfo.getUserHandle())) {
                     rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
                             PackageManager.MATCH_DIRECT_BOOT_AWARE
                                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
index cdb68d8..d030d6a 100644 (file)
@@ -270,7 +270,7 @@ final class UserController {
             if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
 
             // Only keep marching forward if user is actually unlocked
-            if (!isUserKeyUnlocked(userId)) return;
+            if (!StorageManager.isUserKeyUnlocked(userId)) return;
 
             if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) {
                 uss.mUnlockProgress.start();
@@ -281,9 +281,29 @@ final class UserController {
                 mUserManager.onBeforeUnlockUser(userId);
                 uss.mUnlockProgress.setProgress(20);
 
-                // Dispatch unlocked to system services
-                mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss.mUnlockProgress)
+                // Dispatch unlocked to system services; when fully dispatched,
+                // that calls through to the next "unlocked" phase
+                mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss)
                         .sendToTarget();
+            }
+        }
+    }
+
+    /**
+     * Step from {@link UserState#STATE_RUNNING_UNLOCKING} to
+     * {@link UserState#STATE_RUNNING_UNLOCKED}.
+     */
+    void finishUserUnlocked(final UserState uss) {
+        final int userId = uss.mHandle.getIdentifier();
+        synchronized (mService) {
+            // Bail if we ended up with a stale user
+            if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return;
+
+            // Only keep marching forward if user is actually unlocked
+            if (!StorageManager.isUserKeyUnlocked(userId)) return;
+
+            if (uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) {
+                uss.mUnlockProgress.finish();
 
                 // Dispatch unlocked to external apps
                 final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
@@ -310,27 +330,25 @@ final class UserController {
                     }
                 }
 
-                // Send PRE_BOOT broadcasts if fingerprint changed
+                // Send PRE_BOOT broadcasts if user fingerprint changed; we
+                // purposefully block sending BOOT_COMPLETED until after all
+                // PRE_BOOT receivers are finished to avoid ANR'ing apps
                 final UserInfo info = getUserInfo(userId);
                 if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) {
                     new PreBootBroadcaster(mService, userId, null) {
                         @Override
                         public void onFinished() {
-                            finishUserUnlocked(uss);
+                            finishUserUnlockedCompleted(uss);
                         }
                     }.sendNext();
                 } else {
-                    finishUserUnlocked(uss);
+                    finishUserUnlockedCompleted(uss);
                 }
             }
         }
     }
 
-    /**
-     * Step from {@link UserState#STATE_RUNNING_UNLOCKING} to
-     * {@link UserState#STATE_RUNNING_UNLOCKED}.
-     */
-    private void finishUserUnlocked(UserState uss) {
+    private void finishUserUnlockedCompleted(UserState uss) {
         final int userId = uss.mHandle.getIdentifier();
         synchronized (mService) {
             // Bail if we ended up with a stale user
@@ -341,39 +359,38 @@ final class UserController {
             }
 
             // Only keep marching forward if user is actually unlocked
-            if (!isUserKeyUnlocked(userId)) return;
-
-            if (uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) {
-                // Remember that we logged in
-                mUserManager.onUserLoggedIn(userId);
-
-                if (!userInfo.isInitialized()) {
-                    if (userId != UserHandle.USER_SYSTEM) {
-                        Slog.d(TAG, "Initializing user #" + userId);
-                        Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
-                        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-                        mService.broadcastIntentLocked(null, null, intent, null,
-                                new IIntentReceiver.Stub() {
-                                    @Override
-                                    public void performReceive(Intent intent, int resultCode,
-                                            String data, Bundle extras, boolean ordered,
-                                            boolean sticky, int sendingUser) {
-                                        // Note: performReceive is called with mService lock held
-                                        getUserManager().makeInitialized(userInfo.id);
-                                    }
-                                }, 0, null, null, null, AppOpsManager.OP_NONE,
-                                null, true, false, MY_PID, SYSTEM_UID, userId);
-                    }
+            if (!StorageManager.isUserKeyUnlocked(userId)) return;
+
+            // Remember that we logged in
+            mUserManager.onUserLoggedIn(userId);
+
+            if (!userInfo.isInitialized()) {
+                if (userId != UserHandle.USER_SYSTEM) {
+                    Slog.d(TAG, "Initializing user #" + userId);
+                    Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE);
+                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+                    mService.broadcastIntentLocked(null, null, intent, null,
+                            new IIntentReceiver.Stub() {
+                                @Override
+                                public void performReceive(Intent intent, int resultCode,
+                                        String data, Bundle extras, boolean ordered,
+                                        boolean sticky, int sendingUser) {
+                                    // Note: performReceive is called with mService lock held
+                                    getUserManager().makeInitialized(userInfo.id);
+                                }
+                            }, 0, null, null, null, AppOpsManager.OP_NONE,
+                            null, true, false, MY_PID, SYSTEM_UID, userId);
                 }
-                Slog.d(TAG, "Sending BOOT_COMPLETE user #" + userId);
-                final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
-                bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
-                bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
-                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-                mService.broadcastIntentLocked(null, null, bootIntent, null, null, 0, null, null,
-                        new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
-                        AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
             }
+
+            Slog.d(TAG, "Sending BOOT_COMPLETE user #" + userId);
+            final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
+            bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+            bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT
+                    | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+            mService.broadcastIntentLocked(null, null, bootIntent, null, null, 0, null, null,
+                    new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED },
+                    AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
         }
     }
 
@@ -680,20 +697,6 @@ final class UserController {
         return IMountService.Stub.asInterface(ServiceManager.getService("mount"));
     }
 
-    private boolean isUserKeyUnlocked(int userId) {
-        final IMountService mountService = getMountService();
-        if (mountService != null) {
-            try {
-                return mountService.isUserKeyUnlocked(userId);
-            } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
-            }
-        } else {
-            Slog.w(TAG, "Mount service not published; guessing locked state based on property");
-            return !StorageManager.isFileEncryptedNativeOrEmulated();
-        }
-    }
-
     /**
      * Start user, if its not already running.
      * <p>The user will be brought to the foreground, if {@code foreground} parameter is set.
@@ -935,7 +938,7 @@ final class UserController {
             }
         }
 
-        if (!isUserKeyUnlocked(userId)) {
+        if (!StorageManager.isUserKeyUnlocked(userId)) {
             final UserInfo userInfo = getUserInfo(userId);
             final IMountService mountService = getMountService();
             try {
@@ -1321,30 +1324,31 @@ final class UserController {
         if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
             return true;
         }
-
-        final boolean unlocked;
-        switch (state.state) {
-            case UserState.STATE_STOPPING:
-            case UserState.STATE_SHUTDOWN:
-            default:
-                return false;
-
-            case UserState.STATE_BOOTING:
-            case UserState.STATE_RUNNING_LOCKED:
-                unlocked = false;
-                break;
-
-            case UserState.STATE_RUNNING_UNLOCKING:
-            case UserState.STATE_RUNNING_UNLOCKED:
-                unlocked = true;
-                break;
-        }
-
         if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) {
-            return !unlocked;
+            switch (state.state) {
+                case UserState.STATE_BOOTING:
+                case UserState.STATE_RUNNING_LOCKED:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        if ((flags & ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED) != 0) {
+            switch (state.state) {
+                case UserState.STATE_RUNNING_UNLOCKING:
+                case UserState.STATE_RUNNING_UNLOCKED:
+                    return true;
+                default:
+                    return false;
+            }
         }
         if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0) {
-            return unlocked;
+            switch (state.state) {
+                case UserState.STATE_RUNNING_UNLOCKED:
+                    return true;
+                default:
+                    return false;
+            }
         }
 
         // One way or another, we're running!
index 4b0eeed..6567965 100644 (file)
@@ -2662,14 +2662,8 @@ public class PackageManagerService extends IPackageManager.Stub {
             // Prepare storage for system user really early during boot,
             // since core system apps like SettingsProvider and SystemUI
             // can't wait for user to start
-            final int storageFlags;
-            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
-                storageFlags = StorageManager.FLAG_STORAGE_DE;
-            } else {
-                storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
-            }
             reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL, UserHandle.USER_SYSTEM,
-                    storageFlags);
+                    StorageManager.FLAG_STORAGE_DE);
 
             // If this is first boot after an OTA, and a normal boot, then
             // we need to clear code cache directories.
@@ -3100,7 +3094,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
     @Override
     public void checkPackageStartable(String packageName, int userId) {
-        final boolean userKeyUnlocked = isUserKeyUnlocked(userId);
+        final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
 
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
@@ -3451,30 +3445,6 @@ public class PackageManagerService extends IPackageManager.Stub {
     }
 
     /**
-     * Return if the user key is currently unlocked.
-     */
-    private boolean isUserKeyUnlocked(int userId) {
-        if (StorageManager.isFileEncryptedNativeOrEmulated()) {
-            final IMountService mount = IMountService.Stub
-                    .asInterface(ServiceManager.getService("mount"));
-            if (mount == null) {
-                Slog.w(TAG, "Early during boot, assuming locked");
-                return false;
-            }
-            final long token = Binder.clearCallingIdentity();
-            try {
-                return mount.isUserKeyUnlocked(userId);
-            } catch (RemoteException e) {
-                throw e.rethrowAsRuntimeException();
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
-        } else {
-            return true;
-        }
-    }
-
-    /**
      * Update given flags based on encryption status of current user.
      */
     private int updateFlags(int flags, int userId) {
@@ -3485,7 +3455,7 @@ public class PackageManagerService extends IPackageManager.Stub {
             // give them what they want
         } else {
             // Caller expressed no opinion, so match based on user state
-            if (isUserKeyUnlocked(userId)) {
+            if (StorageManager.isUserKeyUnlocked(userId)) {
                 flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
             } else {
                 flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE;
@@ -16046,7 +16016,7 @@ public class PackageManagerService extends IPackageManager.Stub {
 
         final UserManager um = mContext.getSystemService(UserManager.class);
         final int flags;
-        if (um.isUserUnlocked(userId)) {
+        if (um.isUserUnlockingOrUnlocked(userId)) {
             flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
         } else if (um.isUserRunning(userId)) {
             flags = StorageManager.FLAG_STORAGE_DE;
@@ -18730,7 +18700,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         final UserManager um = mContext.getSystemService(UserManager.class);
         for (UserInfo user : um.getUsers()) {
             final int flags;
-            if (um.isUserUnlocked(user.id)) {
+            if (um.isUserUnlockingOrUnlocked(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (um.isUserRunning(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
@@ -19044,7 +19014,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         // First look for stale data that doesn't belong, and check if things
         // have changed since we did our last restorecon
         if ((flags & StorageManager.FLAG_STORAGE_CE) != 0) {
-            if (!isUserKeyUnlocked(userId)) {
+            if (!StorageManager.isUserKeyUnlocked(userId)) {
                 throw new RuntimeException(
                         "Yikes, someone asked us to reconcile CE storage while " + userId
                                 + " was still locked; this would have caused massive data loss!");
@@ -19152,7 +19122,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         final UserManager um = mContext.getSystemService(UserManager.class);
         for (UserInfo user : um.getUsers()) {
             final int flags;
-            if (um.isUserUnlocked(user.id)) {
+            if (um.isUserUnlockingOrUnlocked(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (um.isUserRunning(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
index a085370..a2d859b 100644 (file)
@@ -692,7 +692,7 @@ public class UserManagerService extends IUserManager.Stub {
     @Override
     public boolean trySetQuietModeDisabled(int userHandle, IntentSender target) {
         final int credentialOwnerUserId = getCredentialOwnerProfile(userHandle);
-        if (mContext.getSystemService(StorageManager.class).isUserKeyUnlocked(userHandle)
+        if (StorageManager.isUserKeyUnlocked(userHandle)
                 || !mLockPatternUtils.isSecure(credentialOwnerUserId)) {
             // if the user is already unlocked, no need to show a profile challenge
             setQuietModeEnabled(userHandle, false);
index e3e1097..4d91814 100644 (file)
@@ -112,7 +112,7 @@ public class SearchManagerService extends ISearchManager.Stub {
             if (um.getUserInfo(userId) == null) {
                 throw new IllegalStateException("User " + userId + " doesn't exist");
             }
-            if (!um.isUserUnlocked(userId)) {
+            if (!um.isUserUnlockingOrUnlocked(userId)) {
                 throw new IllegalStateException("User " + userId + " isn't unlocked");
             }
         } finally {
index 56e2001..93fbe5c 100644 (file)
@@ -6224,6 +6224,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     }
 
     private void enforceUserUnlocked(int userId) {
+        // Since we're doing this operation on behalf of an app, we only
+        // want to use the actual "unlocked" state.
         Preconditions.checkState(mUserManager.isUserUnlocked(userId),
                 "User must be running and unlocked");
     }
index 4d02928..f2c995b 100644 (file)
@@ -727,7 +727,7 @@ public final class PrintManagerService extends SystemService {
 
                 @Override
                 public void onPackageModified(String packageName) {
-                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
+                    if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return;
                     UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false);
 
                     synchronized (mLock) {
@@ -742,7 +742,7 @@ public final class PrintManagerService extends SystemService {
 
                 @Override
                 public void onPackageRemoved(String packageName, int uid) {
-                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
+                    if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return;
                     UserState userState = getOrCreateUserStateLocked(getChangingUserId(), false);
 
                     synchronized (mLock) {
@@ -757,7 +757,7 @@ public final class PrintManagerService extends SystemService {
                 @Override
                 public boolean onHandleForceStop(Intent intent, String[] stoppedPackages,
                         int uid, boolean doit) {
-                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return false;
+                    if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return false;
                     synchronized (mLock) {
                         // A background user/profile's print jobs are running but there is
                         // no UI shown. Hence, if the packages of such a user change we need
@@ -795,7 +795,7 @@ public final class PrintManagerService extends SystemService {
 
                 @Override
                 public void onPackageAdded(String packageName, int uid) {
-                    if (!mUserManager.isUserUnlocked(getChangingUserId())) return;
+                    if (!mUserManager.isUserUnlockingOrUnlocked(getChangingUserId())) return;
                     synchronized (mLock) {
                         if (hasPrintService(packageName)) {
                             UserState userState = getOrCreateUserStateLocked(getChangingUserId(),
@@ -812,7 +812,7 @@ public final class PrintManagerService extends SystemService {
         }
 
         private UserState getOrCreateUserStateLocked(int userId, boolean lowPriority) {
-            if (!mUserManager.isUserUnlocked(userId)) {
+            if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
                 throw new IllegalStateException(
                         "User " + userId + " must be unlocked for printing to be available");
             }