Skip to content

Commit a8a9bd6

Browse files
author
Dianne Hackborn
committed
Fix issue #7311376: Add API to allow apps to know if they are...
...running as the foreground user Add UserManager.isUserRunning() which is the public version of the existing method on ActivityManager. Also add UserManager.isUserRunningOrStopping() since that seems like it will be useful. And fix the internal function that returns the array of currently running users to not include stopped users. Change-Id: I84672fa8748fc027fd402729586b5603f640e498
1 parent 3b9e7f3 commit a8a9bd6

7 files changed

Lines changed: 83 additions & 13 deletions

File tree

api/17.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16620,6 +16620,8 @@ package android.os {
1662016620
method public android.os.UserHandle getUserForSerialNumber(long);
1662116621
method public java.lang.String getUserName();
1662216622
method public boolean isUserAGoat();
16623+
method public boolean isUserRunning(android.os.UserHandle);
16624+
method public boolean isUserRunningOrStopping(android.os.UserHandle);
1662316625
}
1662416626

1662516627
public abstract class Vibrator {

api/current.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16620,6 +16620,8 @@ package android.os {
1662016620
method public android.os.UserHandle getUserForSerialNumber(long);
1662116621
method public java.lang.String getUserName();
1662216622
method public boolean isUserAGoat();
16623+
method public boolean isUserRunning(android.os.UserHandle);
16624+
method public boolean isUserRunningOrStopping(android.os.UserHandle);
1662316625
}
1662416626

1662516627
public abstract class Vibrator {

core/java/android/app/ActivityManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1981,7 +1981,7 @@ public boolean switchUser(int userid) {
19811981
*/
19821982
public boolean isUserRunning(int userid) {
19831983
try {
1984-
return ActivityManagerNative.getDefault().isUserRunning(userid);
1984+
return ActivityManagerNative.getDefault().isUserRunning(userid, false);
19851985
} catch (RemoteException e) {
19861986
return false;
19871987
}

core/java/android/app/ActivityManagerNative.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,8 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
16081608
case IS_USER_RUNNING_TRANSACTION: {
16091609
data.enforceInterface(IActivityManager.descriptor);
16101610
int userid = data.readInt();
1611-
boolean result = isUserRunning(userid);
1611+
boolean orStopping = data.readInt() != 0;
1612+
boolean result = isUserRunning(userid, orStopping);
16121613
reply.writeNoException();
16131614
reply.writeInt(result ? 1 : 0);
16141615
return true;
@@ -3865,11 +3866,12 @@ public UserInfo getCurrentUser() throws RemoteException {
38653866
return userInfo;
38663867
}
38673868

3868-
public boolean isUserRunning(int userid) throws RemoteException {
3869+
public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException {
38693870
Parcel data = Parcel.obtain();
38703871
Parcel reply = Parcel.obtain();
38713872
data.writeInterfaceToken(IActivityManager.descriptor);
38723873
data.writeInt(userid);
3874+
data.writeInt(orStopping ? 1 : 0);
38733875
mRemote.transact(IS_USER_RUNNING_TRANSACTION, data, reply, 0);
38743876
reply.readException();
38753877
boolean result = reply.readInt() != 0;

core/java/android/app/IActivityManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ public void setPackageAskScreenCompat(String packageName, boolean ask)
326326
public boolean switchUser(int userid) throws RemoteException;
327327
public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
328328
public UserInfo getCurrentUser() throws RemoteException;
329-
public boolean isUserRunning(int userid) throws RemoteException;
329+
public boolean isUserRunning(int userid, boolean orStopping) throws RemoteException;
330330
public int[] getRunningUserIds() throws RemoteException;
331331

332332
public boolean removeSubTask(int taskId, int subTaskIndex) throws RemoteException;

core/java/android/os/UserManager.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
package android.os;
1717

1818
import com.android.internal.R;
19+
20+
import android.app.ActivityManagerNative;
1921
import android.content.Context;
2022
import android.content.pm.UserInfo;
2123
import android.graphics.Bitmap;
@@ -81,6 +83,39 @@ public boolean isUserAGoat() {
8183
return false;
8284
}
8385

86+
/**
87+
* Return whether the given user is actively running. This means that
88+
* the user is in the "started" state, not "stopped" -- it is currently
89+
* allowed to run code through scheduled alarms, receiving broadcasts,
90+
* etc. A started user may be either the current foreground user or a
91+
* background user; the result here does not distinguish between the two.
92+
* @param user The user to retrieve the running state for.
93+
*/
94+
public boolean isUserRunning(UserHandle user) {
95+
try {
96+
return ActivityManagerNative.getDefault().isUserRunning(
97+
user.getIdentifier(), false);
98+
} catch (RemoteException e) {
99+
return false;
100+
}
101+
}
102+
103+
/**
104+
* Return whether the given user is actively running <em>or</em> stopping.
105+
* This is like {@link #isUserRunning(UserHandle)}, but will also return
106+
* true if the user had been running but is in the process of being stopped
107+
* (but is not yet fully stopped, and still running some code).
108+
* @param user The user to retrieve the running state for.
109+
*/
110+
public boolean isUserRunningOrStopping(UserHandle user) {
111+
try {
112+
return ActivityManagerNative.getDefault().isUserRunning(
113+
user.getIdentifier(), true);
114+
} catch (RemoteException e) {
115+
return false;
116+
}
117+
}
118+
84119
/**
85120
* Returns the UserInfo object describing a specific user.
86121
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.

services/java/com/android/server/am/ActivityManagerService.java

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3585,7 +3585,7 @@ public void forceStopPackage(final String packageName, int userId) {
35853585
Slog.w(TAG, "Failed trying to unstop package "
35863586
+ packageName + ": " + e);
35873587
}
3588-
if (isUserRunningLocked(user)) {
3588+
if (isUserRunningLocked(user, false)) {
35893589
forceStopPackageLocked(packageName, pkgUid);
35903590
}
35913591
}
@@ -9338,6 +9338,12 @@ boolean dumpProcessesLocked(FileDescriptor fd, PrintWriter pw, String[] args,
93389338
pw.print(" User #"); pw.print(uss.mHandle.getIdentifier());
93399339
pw.print(": "); uss.dump("", pw);
93409340
}
9341+
pw.print(" mStartedUserArray: [");
9342+
for (int i=0; i<mStartedUserArray.length; i++) {
9343+
if (i > 0) pw.print(", ");
9344+
pw.print(mStartedUserArray[i]);
9345+
}
9346+
pw.println("]");
93419347
pw.print(" mUserLru: [");
93429348
for (int i=0; i<mUserLru.size(); i++) {
93439349
if (i > 0) pw.print(", ");
@@ -14134,10 +14140,12 @@ public boolean switchUser(int userId) {
1413414140
// so we can just fairly silently bring the user back from
1413514141
// the almost-dead.
1413614142
uss.mState = UserStartedState.STATE_RUNNING;
14143+
updateStartedUserArrayLocked();
1413714144
} else if (uss.mState == UserStartedState.STATE_SHUTDOWN) {
1413814145
// This means ACTION_SHUTDOWN has been sent, so we will
1413914146
// need to treat this as a new boot of the user.
1414014147
uss.mState = UserStartedState.STATE_BOOTING;
14148+
updateStartedUserArrayLocked();
1414114149
}
1414214150

1414314151
mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
@@ -14318,8 +14326,7 @@ void completeSwitchAndInitalizeLocked(UserStartedState uss) {
1431814326

1431914327
void finishUserSwitch(UserStartedState uss) {
1432014328
synchronized (this) {
14321-
if ((uss.mState == UserStartedState.STATE_BOOTING
14322-
|| uss.mState == UserStartedState.STATE_SHUTDOWN)
14329+
if (uss.mState == UserStartedState.STATE_BOOTING
1432314330
&& mStartedUsers.get(uss.mHandle.getIdentifier()) == uss) {
1432414331
uss.mState = UserStartedState.STATE_RUNNING;
1432514332
final int userId = uss.mHandle.getIdentifier();
@@ -14410,6 +14417,7 @@ public void run() {
1441014417
if (uss.mState != UserStartedState.STATE_STOPPING
1441114418
&& uss.mState != UserStartedState.STATE_SHUTDOWN) {
1441214419
uss.mState = UserStartedState.STATE_STOPPING;
14420+
updateStartedUserArrayLocked();
1441314421

1441414422
long ident = Binder.clearCallingIdentity();
1441514423
try {
@@ -14514,7 +14522,7 @@ int getCurrentUserIdLocked() {
1451414522
}
1451514523

1451614524
@Override
14517-
public boolean isUserRunning(int userId) {
14525+
public boolean isUserRunning(int userId, boolean orStopped) {
1451814526
if (checkCallingPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
1451914527
!= PackageManager.PERMISSION_GRANTED) {
1452014528
String msg = "Permission Denial: isUserRunning() from pid="
@@ -14525,13 +14533,19 @@ public boolean isUserRunning(int userId) {
1452514533
throw new SecurityException(msg);
1452614534
}
1452714535
synchronized (this) {
14528-
return isUserRunningLocked(userId);
14536+
return isUserRunningLocked(userId, orStopped);
1452914537
}
1453014538
}
1453114539

14532-
boolean isUserRunningLocked(int userId) {
14540+
boolean isUserRunningLocked(int userId, boolean orStopped) {
1453314541
UserStartedState state = mStartedUsers.get(userId);
14534-
return state != null && state.mState != UserStartedState.STATE_STOPPING
14542+
if (state == null) {
14543+
return false;
14544+
}
14545+
if (orStopped) {
14546+
return true;
14547+
}
14548+
return state.mState != UserStartedState.STATE_STOPPING
1453514549
&& state.mState != UserStartedState.STATE_SHUTDOWN;
1453614550
}
1453714551

@@ -14552,9 +14566,24 @@ public int[] getRunningUserIds() {
1455214566
}
1455314567

1455414568
private void updateStartedUserArrayLocked() {
14555-
mStartedUserArray = new int[mStartedUsers.size()];
14569+
int num = 0;
1455614570
for (int i=0; i<mStartedUsers.size(); i++) {
14557-
mStartedUserArray[i] = mStartedUsers.keyAt(i);
14571+
UserStartedState uss = mStartedUsers.valueAt(i);
14572+
// This list does not include stopping users.
14573+
if (uss.mState != UserStartedState.STATE_STOPPING
14574+
&& uss.mState != UserStartedState.STATE_SHUTDOWN) {
14575+
num++;
14576+
}
14577+
}
14578+
mStartedUserArray = new int[num];
14579+
num = 0;
14580+
for (int i=0; i<mStartedUsers.size(); i++) {
14581+
UserStartedState uss = mStartedUsers.valueAt(i);
14582+
if (uss.mState != UserStartedState.STATE_STOPPING
14583+
&& uss.mState != UserStartedState.STATE_SHUTDOWN) {
14584+
mStartedUserArray[num] = mStartedUsers.keyAt(i);
14585+
num++;
14586+
}
1455814587
}
1455914588
}
1456014589

0 commit comments

Comments
 (0)