Introduce AMS.getLastResumedActivityUserId to fix work profile icon issue

Problem:
Work profile status bar icon feeature is relied on two callbacks
1. onForegroundProfileSwitch  (AMS.setResumedActivityLocked)
2. appTransitionStarting (WMS)

We assume callback 1 is always called before 2, but it is not the case.
These two callbacks are triggered by two handlers in two different threads,
and hence race condition happens.

Solution:
Not rely on onForegroundProfileSwitch to update mManagedProfileFocused
flag anymore. Query getLastResumedActivityUserId in appTransitionStarting.
Also, make sure mLastResumedActivity is updated before sending message
to WMS in setResumedActivityLocked.

Test: Start a work app, observe that the work icon is shown.
Test: Start a personal app, observe that work icon is gone.
Test: Dock the work app, tap on it (give it focus), observe that work
      icon is shown.
Test: Start a work app, switch user, can see the icon is gone. Switch back,
      icon is back.

Bug: 34159089

Change-Id: I2cee141d18e8b7d5607b26dd7a2fd5bc9cd0ebb3
This commit is contained in:
Tony Mak
2017-03-28 18:50:01 +01:00
parent 76c32a35a9
commit ec319aba34
3 changed files with 54 additions and 69 deletions

View File

@@ -629,6 +629,11 @@ interface IActivityManager {
*/ */
void setDisablePreviewScreenshots(IBinder token, boolean disable); void setDisablePreviewScreenshots(IBinder token, boolean disable);
/**
* Return the user id of last resumed activity.
*/
int getLastResumedActivityUserId();
// WARNING: when these transactions are updated, check if they are any callers on the native // WARNING: when these transactions are updated, check if they are any callers on the native
// side. If so, make sure they are using the correct transaction ids and arguments. // side. If so, make sure they are using the correct transaction ids and arguments.
// If a transaction which will also be used on the native side is being inserted, add it // If a transaction which will also be used on the native side is being inserted, add it

View File

@@ -127,7 +127,6 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
private boolean mVolumeVisible; private boolean mVolumeVisible;
private boolean mCurrentUserSetup; private boolean mCurrentUserSetup;
private boolean mManagedProfileFocused = false;
private boolean mManagedProfileIconVisible = false; private boolean mManagedProfileIconVisible = false;
private boolean mManagedProfileInQuietMode = false; private boolean mManagedProfileInQuietMode = false;
@@ -439,45 +438,30 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
} }
} }
private void profileChanged(int userId) {
UserInfo user = null;
if (userId == UserHandle.USER_CURRENT) {
try {
user = ActivityManager.getService().getCurrentUser();
} catch (RemoteException e) {
// Ignore
}
} else {
user = mUserManager.getUserInfo(userId);
}
mManagedProfileFocused = user != null && user.isManagedProfile();
if (DEBUG) Log.v(TAG, "profileChanged: mManagedProfileFocused: " + mManagedProfileFocused);
// Actually update the icon later when transition starts.
}
private void updateManagedProfile() { private void updateManagedProfile() {
if (DEBUG) { try {
Log.v(TAG, "updateManagedProfile: mManagedProfileFocused: " final boolean showIcon;
+ mManagedProfileFocused); final int userId = ActivityManager.getService().getLastResumedActivityUserId();
} if (mUserManager.isManagedProfile(userId) && !mKeyguardMonitor.isShowing()) {
final boolean showIcon; showIcon = true;
if (mManagedProfileFocused && !mKeyguardMonitor.isShowing()) { mIconController.setIcon(mSlotManagedProfile,
showIcon = true; R.drawable.stat_sys_managed_profile_status,
mIconController.setIcon(mSlotManagedProfile, mContext.getString(R.string.accessibility_managed_profile));
R.drawable.stat_sys_managed_profile_status, } else if (mManagedProfileInQuietMode) {
mContext.getString(R.string.accessibility_managed_profile)); showIcon = true;
} else if (mManagedProfileInQuietMode) { mIconController.setIcon(mSlotManagedProfile,
showIcon = true; R.drawable.stat_sys_managed_profile_status_off,
mIconController.setIcon(mSlotManagedProfile, mContext.getString(R.string.accessibility_managed_profile));
R.drawable.stat_sys_managed_profile_status_off, } else {
mContext.getString(R.string.accessibility_managed_profile)); showIcon = false;
} else { }
showIcon = false; if (mManagedProfileIconVisible != showIcon) {
} mIconController.setIconVisibility(mSlotManagedProfile, showIcon);
if (mManagedProfileIconVisible != showIcon) { mManagedProfileIconVisible = showIcon;
mIconController.setIconVisibility(mSlotManagedProfile, showIcon); }
mManagedProfileIconVisible = showIcon; } catch (RemoteException ex) {
Log.w(TAG, "updateManagedProfile: ", ex);
// ignore
} }
} }
@@ -556,35 +540,16 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
new SynchronousUserSwitchObserver() { new SynchronousUserSwitchObserver() {
@Override @Override
public void onUserSwitching(int newUserId) throws RemoteException { public void onUserSwitching(int newUserId) throws RemoteException {
mHandler.post(new Runnable() { mHandler.post(() -> mUserInfoController.reloadUserInfo());
@Override
public void run() {
mUserInfoController.reloadUserInfo();
}
});
} }
@Override @Override
public void onUserSwitchComplete(int newUserId) throws RemoteException { public void onUserSwitchComplete(int newUserId) throws RemoteException {
mHandler.post(new Runnable() { mHandler.post(() -> {
@Override updateAlarm();
public void run() { updateQuietState();
updateAlarm(); updateManagedProfile();
profileChanged(newUserId); updateForegroundInstantApps();
updateQuietState();
updateManagedProfile();
updateForegroundInstantApps();
}
});
}
@Override
public void onForegroundProfileSwitch(int newProfileId) {
mHandler.post(new Runnable() {
@Override
public void run() {
profileChanged(newProfileId);
}
}); });
} }
}; };

View File

@@ -3212,18 +3212,18 @@ public class ActivityManagerService extends IActivityManager.Stub
} }
} }
mWindowManager.setFocusedApp(r.appToken, true);
applyUpdateLockStateLocked(r);
applyUpdateVrModeLocked(r);
if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) { if (mLastResumedActivity != null && r.userId != mLastResumedActivity.userId) {
mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG); mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
mHandler.obtainMessage( mHandler.obtainMessage(
FOREGROUND_PROFILE_CHANGED_MSG, r.userId, 0).sendToTarget(); FOREGROUND_PROFILE_CHANGED_MSG, r.userId, 0).sendToTarget();
} }
mLastResumedActivity = r; mLastResumedActivity = r;
mWindowManager.setFocusedApp(r.appToken, true);
applyUpdateLockStateLocked(r);
applyUpdateVrModeLocked(r);
EventLogTags.writeAmSetResumedActivity( EventLogTags.writeAmSetResumedActivity(
r == null ? -1 : r.userId, r == null ? -1 : r.userId,
r == null ? "NULL" : r.shortComponentName, r == null ? "NULL" : r.shortComponentName,
@@ -23599,6 +23599,21 @@ public class ActivityManagerService extends IActivityManager.Stub
} }
} }
/**
* Return the user id of the last resumed activity.
*/
@Override
public @UserIdInt int getLastResumedActivityUserId() {
enforceCallingPermission(
permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
synchronized (this) {
if (mLastResumedActivity == null) {
return mUserController.getCurrentUserIdLocked();
}
return mLastResumedActivity.userId;
}
}
private final class SleepTokenImpl extends SleepToken { private final class SleepTokenImpl extends SleepToken {
private final String mTag; private final String mTag;
private final long mAcquireTime; private final long mAcquireTime;