summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/17.txt2
-rw-r--r--api/current.txt2
-rw-r--r--core/java/android/app/ActivityManager.java2
-rw-r--r--core/java/android/app/ActivityManagerNative.java6
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/os/UserManager.java35
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java47
7 files changed, 83 insertions, 13 deletions
diff --git a/api/17.txt b/api/17.txt
index f8ad4d9..bebd566 100644
--- a/api/17.txt
+++ b/api/17.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/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++;
+ }
}
}