Allow caller to specify target to start in setQuietModeEnabled
So, UMS can start the target once user is unlocked.
Test: No secure lock. Try turn off and on work mode by tapping work app.
Test: Have secure lock. Try turn off and on work mode by tapping work app.
Test: Turn off work mode. Reboot. Try to tap on any work app to turn on work mode.
BUG:69926710
Change-Id: Iaaccd5d763f7e36e5a43bad5261f1eb16060f9d6
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5e67396..6c5129b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23824,7 +23824,13 @@
*/
@Override
public boolean startUserInBackground(final int userId) {
- return mUserController.startUser(userId, /* foreground */ false);
+ return startUserInBackgroundWithListener(userId, null);
+ }
+
+ @Override
+ public boolean startUserInBackgroundWithListener(final int userId,
+ @Nullable IProgressListener unlockListener) {
+ return mUserController.startUser(userId, /* foreground */ false, unlockListener);
}
@Override
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 4e3d8d2..6bd599b 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -24,6 +24,7 @@
import static android.app.ActivityManager.USER_OP_SUCCESS;
import static android.os.Process.SHELL_UID;
import static android.os.Process.SYSTEM_UID;
+
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -37,6 +38,7 @@
import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKING;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppGlobals;
@@ -830,6 +832,9 @@
private IStorageManager getStorageManager() {
return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
}
+ boolean startUser(final int userId, final boolean foreground) {
+ return startUser(userId, foreground, null);
+ }
/**
* Start user, if its not already running.
@@ -860,7 +865,10 @@
* @param foreground true if user should be brought to the foreground
* @return true if the user has been successfully started
*/
- boolean startUser(final int userId, final boolean foreground) {
+ boolean startUser(
+ final int userId,
+ final boolean foreground,
+ @Nullable IProgressListener unlockListener) {
if (mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: switchUser() from pid="
@@ -918,6 +926,10 @@
final Integer userIdInt = userId;
mUserLru.remove(userIdInt);
mUserLru.add(userIdInt);
+
+ if (unlockListener != null) {
+ uss.mUnlockProgress.addListener(unlockListener);
+ }
}
if (updateUmState) {
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index dbf413f..dc481ca 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -27,7 +27,6 @@
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
-import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
import android.app.KeyguardManager;
@@ -50,6 +49,7 @@
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IProgressListener;
import android.os.IUserManager;
import android.os.Message;
import android.os.ParcelFileDescriptor;
@@ -71,10 +71,6 @@
import android.os.storage.StorageManager;
import android.security.GateKeeper;
import android.service.gatekeeper.IGateKeeperService;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.text.TextUtils;
import android.util.AtomicFile;
import android.util.IntArray;
import android.util.Log;
@@ -113,9 +109,9 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
@@ -378,22 +374,45 @@
private final BroadcastReceiver mDisableQuietModeCallback = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK.equals(intent.getAction())) {
- final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT);
- final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_ID, 0);
- setQuietModeEnabled(userHandle, false);
- if (target != null) {
- try {
- mContext.startIntentSender(target, null, 0, 0, 0);
- } catch (IntentSender.SendIntentException e) {
- /* ignore */
- }
- }
+ if (!ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK.equals(intent.getAction())) {
+ return;
}
+ final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT);
+ final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.USER_NULL);
+ setQuietModeEnabled(userHandle, false, target);
}
};
/**
+ * Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
+ *
+ * @see {@link #trySetQuietModeDisabled(int, IntentSender)}
+ */
+ private class DisableQuietModeUserUnlockedCallback extends IProgressListener.Stub {
+ private final IntentSender mTarget;
+
+ public DisableQuietModeUserUnlockedCallback(IntentSender target) {
+ Preconditions.checkNotNull(target);
+ mTarget = target;
+ }
+
+ @Override
+ public void onStarted(int id, Bundle extras) {}
+
+ @Override
+ public void onProgress(int id, int progress, Bundle extras) {}
+
+ @Override
+ public void onFinished(int id, Bundle extras) {
+ try {
+ mContext.startIntentSender(mTarget, null, 0, 0, 0);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(LOG_TAG, "Failed to start the target in the callback", e);
+ }
+ }
+ }
+
+ /**
* Whether all users should be created ephemeral.
*/
@GuardedBy("mUsersLock")
@@ -765,7 +784,7 @@
}
@Override
- public void setQuietModeEnabled(int userHandle, boolean enableQuietMode) {
+ public void setQuietModeEnabled(int userHandle, boolean enableQuietMode, IntentSender target) {
checkManageUsersPermission("silence profile");
boolean changed = false;
UserInfo profile, parent;
@@ -792,7 +811,11 @@
LocalServices.getService(ActivityManagerInternal.class)
.killForegroundAppsForUser(userHandle);
} else {
- ActivityManager.getService().startUserInBackground(userHandle);
+ IProgressListener callback = target != null
+ ? new DisableQuietModeUserUnlockedCallback(target)
+ : null;
+ ActivityManager.getService().startUserInBackgroundWithListener(
+ userHandle, callback);
}
} catch (RemoteException e) {
Slog.e(LOG_TAG, "fail to start/stop user for quiet mode", e);
@@ -820,12 +843,13 @@
}
@Override
- public boolean trySetQuietModeDisabled(int userHandle, IntentSender target) {
+ public boolean trySetQuietModeDisabled(
+ @UserIdInt int userHandle, @Nullable IntentSender target) {
checkManageUsersPermission("silence profile");
if (StorageManager.isUserKeyUnlocked(userHandle)
|| !mLockPatternUtils.isSecure(userHandle)) {
// if the user is already unlocked, no need to show a profile challenge
- setQuietModeEnabled(userHandle, false);
+ setQuietModeEnabled(userHandle, false, target);
return true;
}