From 6c915ead38db0a2a6393c40d4fbac959399439c5 Mon Sep 17 00:00:00 2001 From: Fyodor Kupolov Date: Mon, 9 May 2016 19:10:53 -0700 Subject: [PATCH] Push unlocking/unlocked state to UserManager Push unlocking/unlocked state to UserManagerInternal when it's changed in UserController. Use UserManagerInternal.isUserUnlockingOrUnlocked when updating flags for filtering in PackageManager. Bug: 28629076 Change-Id: I8440af090f533f93870d0cff0e3871e114c37efa --- core/java/android/os/UserManager.java | 1 + core/java/android/os/UserManagerInternal.java | 14 ++++++++++++++ .../com/android/server/am/UserController.java | 17 +++++++++++++++++ .../server/pm/PackageManagerService.java | 12 +++++++++++- .../android/server/pm/UserManagerService.java | 18 ++++++++++++++++++ 5 files changed, 61 insertions(+), 1 deletion(-) diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index d55201f709e92..1948df9b8ffff 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -998,6 +998,7 @@ public class UserManager { /** {@hide} */ public boolean isUserUnlockingOrUnlocked(@UserIdInt int userId) { + // TODO Switch to using UMS internal isUserUnlockingOrUnlocked try { return ActivityManagerNative.getDefault().isUserRunning(userId, ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED); diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java index f399719fa1fc2..551ea6b6c469c 100644 --- a/core/java/android/os/UserManagerInternal.java +++ b/core/java/android/os/UserManagerInternal.java @@ -126,4 +126,18 @@ public abstract class UserManagerInternal { * createAndManageUser is called by the device owner. */ public abstract UserInfo createUserEvenWhenDisallowed(String name, int flags); + + /** + * Return whether the given user is running in an + * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKING "unlocking"} or + * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKED "unlocked"} state. + */ + public abstract boolean isUserUnlockingOrUnlocked(int userId); + + /** + * Sets whether the given user is running in an + * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKING "unlocking"} or + * {@link com.android.server.am.UserState#STATE_RUNNING_UNLOCKED "unlocked"} state. + */ + public abstract void setUserUnlockingOrUnlocked(int userId, boolean unlockingOrUnlocked); } diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index e8f4b3e3fb743..c4e39c940e330 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.Manifest.permission.INTERACT_ACROSS_USERS; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; +import static android.app.ActivityManager.FLAG_AND_UNLOCKING_OR_UNLOCKED; import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM; import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; import static android.app.ActivityManager.USER_OP_IS_CURRENT; @@ -157,6 +158,8 @@ final class UserController { private final LockPatternUtils mLockPatternUtils; + private UserManagerInternal mUserManagerInternal; + UserController(ActivityManagerService service) { mService = service; mHandler = mService.mHandler; @@ -273,6 +276,7 @@ final class UserController { if (!StorageManager.isUserKeyUnlocked(userId)) return; if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) { + getUserManagerInternal().setUserUnlockingOrUnlocked(userId, true); uss.mUnlockProgress.start(); // Prepare app storage before we go any further @@ -303,6 +307,7 @@ final class UserController { if (!StorageManager.isUserKeyUnlocked(userId)) return; if (uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) { + getUserManagerInternal().setUserUnlockingOrUnlocked(userId, true); uss.mUnlockProgress.finish(); // Dispatch unlocked to external apps @@ -476,6 +481,7 @@ final class UserController { if (uss.state != UserState.STATE_STOPPING && uss.state != UserState.STATE_SHUTDOWN) { uss.setState(UserState.STATE_STOPPING); + getUserManagerInternal().setUserUnlockingOrUnlocked(userId, false); updateStartedUserArrayLocked(); long ident = Binder.clearCallingIdentity(); @@ -537,6 +543,7 @@ final class UserController { } uss.setState(UserState.STATE_SHUTDOWN); } + getUserManagerInternal().setUserUnlockingOrUnlocked(userId, false); mService.mBatteryStatsService.noteEvent( BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH, @@ -806,6 +813,9 @@ final class UserController { // so we can just fairly silently bring the user back from // the almost-dead. uss.setState(uss.lastState); + if (isUserRunningLocked(userId, FLAG_AND_UNLOCKING_OR_UNLOCKED)) { + getUserManagerInternal().setUserUnlockingOrUnlocked(userId, true); + } updateStartedUserArrayLocked(); needStart = true; } else if (uss.state == UserState.STATE_SHUTDOWN) { @@ -1465,6 +1475,13 @@ final class UserController { return mLockPatternUtils.isLockScreenDisabled(userId); } + private UserManagerInternal getUserManagerInternal() { + if (mUserManagerInternal == null) { + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); + } + return mUserManagerInternal; + } + void dump(PrintWriter pw, boolean dumpAll) { pw.println(" mStartedUsers:"); for (int i = 0; i < mStartedUsers.size(); i++) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index d7693b0ebe617..5c45b0f90aaaa 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -190,6 +190,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; +import android.os.UserManagerInternal; import android.os.storage.IMountService; import android.os.storage.MountServiceInternal; import android.os.storage.StorageEventListener; @@ -739,6 +740,8 @@ public class PackageManagerService extends IPackageManager.Stub { // List of packages names to keep cached, even if they are uninstalled for all users private List mKeepUninstalledPackages; + private UserManagerInternal mUserManagerInternal; + private static class IFVerificationParams { PackageParser.Package pkg; boolean replacing; @@ -3481,7 +3484,7 @@ public class PackageManagerService extends IPackageManager.Stub { // give them what they want } else { // Caller expressed no opinion, so match based on user state - if (StorageManager.isUserKeyUnlocked(userId)) { + if (getUserManagerInternal().isUserUnlockingOrUnlocked(userId)) { flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE; } else { flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE; @@ -3490,6 +3493,13 @@ public class PackageManagerService extends IPackageManager.Stub { return flags; } + private UserManagerInternal getUserManagerInternal() { + if (mUserManagerInternal == null) { + mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); + } + return mUserManagerInternal; + } + /** * Update given flags when being used to request {@link PackageInfo}. */ diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index a2d859b79d30e..6b0e5827d4e00 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -320,6 +320,9 @@ public class UserManagerService extends IUserManager.Stub { @GuardedBy("mUsersLock") private boolean mForceEphemeralUsers; + @GuardedBy("mUsersLock") + private final SparseBooleanArray mUnlockingOrUnlockedUsers = new SparseBooleanArray(); + private static UserManagerService sInstance; public static UserManagerService getInstance() { @@ -2302,6 +2305,7 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mUsersLock) { mUsers.remove(userHandle); mIsUserManaged.delete(userHandle); + mUnlockingOrUnlockedUsers.delete(userHandle); } synchronized (mRestrictionsLock) { mBaseUserRestrictions.remove(userHandle); @@ -3159,6 +3163,20 @@ public class UserManagerService extends IUserManager.Stub { } return user; } + + @Override + public void setUserUnlockingOrUnlocked(int userId, boolean unlockingOrUnlocked) { + synchronized (mUsersLock) { + mUnlockingOrUnlockedUsers.put(userId, unlockingOrUnlocked); + } + } + + @Override + public boolean isUserUnlockingOrUnlocked(int userId) { + synchronized (mUsersLock) { + return mUnlockingOrUnlockedUsers.get(userId); + } + } } /* Remove all the users except of the system one. */