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
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index d55201f..1948df9 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -998,6 +998,7 @@
/** {@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 f399719..551ea6b 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -126,4 +126,18 @@
* 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 e8f4b3e..c4e39c9 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 @@
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 @@
private final LockPatternUtils mLockPatternUtils;
+ private UserManagerInternal mUserManagerInternal;
+
UserController(ActivityManagerService service) {
mService = service;
mHandler = mService.mHandler;
@@ -273,6 +276,7 @@
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 @@
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 @@
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 @@
}
uss.setState(UserState.STATE_SHUTDOWN);
}
+ getUserManagerInternal().setUserUnlockingOrUnlocked(userId, false);
mService.mBatteryStatsService.noteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
@@ -806,6 +813,9 @@
// 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 @@
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 d7693b0..5c45b0f 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.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 @@
// List of packages names to keep cached, even if they are uninstalled for all users
private List<String> mKeepUninstalledPackages;
+ private UserManagerInternal mUserManagerInternal;
+
private static class IFVerificationParams {
PackageParser.Package pkg;
boolean replacing;
@@ -3481,7 +3484,7 @@
// 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 @@
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 a2d859b..6b0e582 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 @@
@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 @@
synchronized (mUsersLock) {
mUsers.remove(userHandle);
mIsUserManaged.delete(userHandle);
+ mUnlockingOrUnlockedUsers.delete(userHandle);
}
synchronized (mRestrictionsLock) {
mBaseUserRestrictions.remove(userHandle);
@@ -3159,6 +3163,20 @@
}
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. */