diff options
-rw-r--r-- | api/17.txt | 2 | ||||
-rw-r--r-- | api/current.txt | 2 | ||||
-rw-r--r-- | core/java/android/app/ActivityManager.java | 2 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 6 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
-rw-r--r-- | core/java/android/os/UserManager.java | 35 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 47 |
7 files changed, 83 insertions, 13 deletions
@@ -16620,6 +16620,8 @@ package android.os { method public android.os.UserHandle getUserForSerialNumber(long); method public java.lang.String getUserName(); method public boolean isUserAGoat(); + method public boolean isUserRunning(android.os.UserHandle); + method public boolean isUserRunningOrStopping(android.os.UserHandle); } public abstract class Vibrator { diff --git a/api/current.txt b/api/current.txt index f8ad4d9..bebd566 100644 --- a/api/current.txt +++ b/api/current.txt @@ -16620,6 +16620,8 @@ package android.os { method public android.os.UserHandle getUserForSerialNumber(long); method public java.lang.String getUserName(); method public boolean isUserAGoat(); + method public boolean isUserRunning(android.os.UserHandle); + method public boolean isUserRunningOrStopping(android.os.UserHandle); } public abstract class Vibrator { diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 0eda6b4..594be68 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1981,7 +1981,7 @@ public class ActivityManager { */ public boolean isUserRunning(int userid) { try { - return ActivityManagerNative.getDefault().isUserRunning(userid); + return ActivityManagerNative.getDefault().isUserRunning(userid, false); } catch (RemoteException e) { return false; } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index bb62c9e..7492629 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1608,7 +1608,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM case IS_USER_RUNNING_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int userid = data.readInt(); - boolean result = isUserRunning(userid); + boolean orStopping = data.readInt() != 0; + boolean result = isUserRunning(userid, orStopping); reply.writeNoException(); reply.writeInt(result ? 1 : 0); return true; @@ -3865,11 +3866,12 @@ class ActivityManagerProxy implements IActivityManager return userInfo; } - public boolean isUserRunning(int userid) throws RemoteException { + public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeInt(userid); + data.writeInt(orStopping ? 1 : 0); mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0); reply.readException(); boolean result = reply.readInt() != 0; diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index da844ef..97250e9 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -326,7 +326,7 @@ public interface IActivityManager extends IInterface { public boolean switchUser(int userid) throws RemoteException; public int stopUser(int userid, IStopUserCallback callback) throws RemoteException; public UserInfo getCurrentUser() throws RemoteException; - public boolean isUserRunning(int userid) throws RemoteException; + public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException; public int[] getRunningUserIds() throws RemoteException; public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException; diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 83a0c78..2739cac 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -16,6 +16,8 @@ package android.os; import com.android.internal.R; + +import android.app.ActivityManagerNative; import android.content.Context; import android.content.pm.UserInfo; import android.graphics.Bitmap; @@ -82,6 +84,39 @@ public class UserManager { } /** + * Return whether the given user is actively running. This means that + * the user is in the "started" state, not "stopped" -- it is currently + * allowed to run code through scheduled alarms, receiving broadcasts, + * etc. A started user may be either the current foreground user or a + * background user; the result here does not distinguish between the two. + * @param user The user to retrieve the running state for. + */ + public boolean isUserRunning(UserHandle user) { + try { + return ActivityManagerNative.getDefault().isUserRunning( + user.getIdentifier(), false); + } catch (RemoteException e) { + return false; + } + } + + /** + * Return whether the given user is actively running <em>or</em> stopping. + * This is like {@link #isUserRunning(UserHandle)}, but will also return + * true if the user had been running but is in the process of being stopped + * (but is not yet fully stopped, and still running some code). + * @param user The user to retrieve the running state for. + */ + public boolean isUserRunningOrStopping(UserHandle user) { + try { + return ActivityManagerNative.getDefault().isUserRunning( + user.getIdentifier(), true); + } catch (RemoteException e) { + return false; + } + } + + /** * Returns the UserInfo object describing a specific user. * Requires {@link android.Manifest.permission#MANAGE_USERS} permission. * @param userHandle the user handle of the user whose information is being requested. diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index c2aa3a5..6b7e29c 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3585,7 +3585,7 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, "Failed trying to unstop package " + packageName + ": " + e); } - if (isUserRunningLocked(user)) { + if (isUserRunningLocked(user, false)) { forceStopPackageLocked(packageName, pkgUid); } } @@ -9338,6 +9338,12 @@ public final class ActivityManagerService extends ActivityManagerNative pw.print(" User #"); pw.print(uss.mHandle.getIdentifier()); pw.print(": "); uss.dump("", pw); } + pw.print(" mStartedUserArray: ["); + for (int i=0; i<mStartedUserArray.length; i++) { + if (i > 0) pw.print(", "); + pw.print(mStartedUserArray[i]); + } + pw.println("]"); pw.print(" mUserLru: ["); for (int i=0; i<mUserLru.size(); i++) { if (i > 0) pw.print(", "); @@ -14134,10 +14140,12 @@ public final class ActivityManagerService extends ActivityManagerNative // so we can just fairly silently bring the user back from // the almost-dead. uss.mState = UserStartedState.STATE_RUNNING; + updateStartedUserArrayLocked(); } else if (uss.mState == UserStartedState.STATE_SHUTDOWN) { // This means ACTION_SHUTDOWN has been sent, so we will // need to treat this as a new boot of the user. uss.mState = UserStartedState.STATE_BOOTING; + updateStartedUserArrayLocked(); } mHandler.removeMessages(REPORT_USER_SWITCH_MSG); @@ -14318,8 +14326,7 @@ public final class ActivityManagerService extends ActivityManagerNative void finishUserSwitch(UserStartedState uss) { synchronized (this) { - if ((uss.mState == UserStartedState.STATE_BOOTING - || uss.mState == UserStartedState.STATE_SHUTDOWN) + if (uss.mState == UserStartedState.STATE_BOOTING && mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) { uss.mState = UserStartedState.STATE_RUNNING; final int userId = uss.mHandle.getIdentifier(); @@ -14410,6 +14417,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (uss.mState != UserStartedState.STATE_STOPPING && uss.mState != UserStartedState.STATE_SHUTDOWN) { uss.mState = UserStartedState.STATE_STOPPING; + updateStartedUserArrayLocked(); long ident = Binder.clearCallingIdentity(); try { @@ -14514,7 +14522,7 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public boolean isUserRunning(int userId) { + public boolean isUserRunning(int userId, boolean orStopped) { if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) { String msg = "Permission Denial: isUserRunning() from pid=" @@ -14525,13 +14533,19 @@ public final class ActivityManagerService extends ActivityManagerNative throw new SecurityException(msg); } synchronized (this) { - return isUserRunningLocked(userId); + return isUserRunningLocked(userId, orStopped); } } - boolean isUserRunningLocked(int userId) { + boolean isUserRunningLocked(int userId, boolean orStopped) { UserStartedState state = mStartedUsers.get(userId); - return state != null && state.mState != UserStartedState.STATE_STOPPING + if (state == null) { + return false; + } + if (orStopped) { + return true; + } + return state.mState != UserStartedState.STATE_STOPPING && state.mState != UserStartedState.STATE_SHUTDOWN; } @@ -14552,9 +14566,24 @@ public final class ActivityManagerService extends ActivityManagerNative } private void updateStartedUserArrayLocked() { - mStartedUserArray = new int[mStartedUsers.size()]; + int num = 0; for (int i=0; i<mStartedUsers.size(); i++) { - mStartedUserArray[i] = mStartedUsers.keyAt(i); + UserStartedState uss = mStartedUsers.valueAt(i); + // This list does not include stopping users. + if (uss.mState != UserStartedState.STATE_STOPPING + && uss.mState != UserStartedState.STATE_SHUTDOWN) { + num++; + } + } + mStartedUserArray = new int[num]; + num = 0; + for (int i=0; i<mStartedUsers.size(); i++) { + UserStartedState uss = mStartedUsers.valueAt(i); + if (uss.mState != UserStartedState.STATE_STOPPING + && uss.mState != UserStartedState.STATE_SHUTDOWN) { + mStartedUserArray[num] = mStartedUsers.keyAt(i); + num++; + } } } |