diff options
| -rw-r--r-- | core/java/android/content/pm/multiuser.aconfig | 9 | ||||
| -rw-r--r-- | core/java/com/android/internal/app/SetScreenLockDialogActivity.java | 160 | ||||
| -rw-r--r-- | core/res/AndroidManifest.xml | 6 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 7 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 6 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/UserManagerService.java | 23 |
6 files changed, 209 insertions, 2 deletions
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 56849291e52a..1513e9af3d52 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -144,6 +144,13 @@ flag { } flag { + name: "show_set_screen_lock_dialog" + namespace: "profile_experiences" + description: "Display the dialog to set up screen lock when private space unlock operation is requested" + bug: "316129700" +} + +flag { name: "reorder_wallpaper_during_user_switch" namespace: "multiuser" description: "Reorder loading home and lock screen wallpapers during a user switch." @@ -162,4 +169,4 @@ flag { namespace: "profile_experiences" description: "Disables adding items belonging to Private Space on Home Screen manually as well as automatically" bug: "287975131" -} +}
\ No newline at end of file diff --git a/core/java/com/android/internal/app/SetScreenLockDialogActivity.java b/core/java/com/android/internal/app/SetScreenLockDialogActivity.java new file mode 100644 index 000000000000..93fe37c974b2 --- /dev/null +++ b/core/java/com/android/internal/app/SetScreenLockDialogActivity.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.app; + +import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; +import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static android.hardware.biometrics.BiometricManager.Authenticators.DEVICE_CREDENTIAL; +import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL; +import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED; + +import android.Manifest; +import android.annotation.IntDef; +import android.annotation.RequiresPermission; +import android.app.AlertDialog; +import android.app.KeyguardManager; +import android.content.ComponentName; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.UserInfo; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; +import android.util.Log; + +import com.android.internal.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A dialog shown to the user that prompts them to set the screen lock for the current foreground + * user. Should be called from the context of foreground user. + */ +public class SetScreenLockDialogActivity extends AlertActivity + implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener { + private static final String TAG = "SetScreenLockDialog"; + public static final String EXTRA_LAUNCH_REASON = "launch_reason"; + /** + * User id associated with the workflow that wants to launch the prompt to set up the + * screen lock + */ + public static final String EXTRA_ORIGIN_USER_ID = "origin_user_id"; + private static final String PACKAGE_NAME = "android"; + @IntDef(prefix = "LAUNCH_REASON_", value = { + LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS, + LAUNCH_REASON_DISABLE_QUIET_MODE, + LAUNCH_REASON_UNKNOWN, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface LaunchReason { + } + public static final int LAUNCH_REASON_UNKNOWN = -1; + public static final int LAUNCH_REASON_DISABLE_QUIET_MODE = 1; + public static final int LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS = 2; + private @LaunchReason int mReason; + private int mOriginUserId; + + @Override + @RequiresPermission(HIDE_OVERLAY_WINDOWS) + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (!(android.os.Flags.allowPrivateProfile() + && android.multiuser.Flags.showSetScreenLockDialog())) { + finish(); + return; + } + Intent intent = getIntent(); + mReason = intent.getIntExtra(EXTRA_LAUNCH_REASON, LAUNCH_REASON_UNKNOWN); + mOriginUserId = intent.getIntExtra(EXTRA_ORIGIN_USER_ID, UserHandle.USER_NULL); + + if (mReason == LAUNCH_REASON_UNKNOWN) { + Log.e(TAG, "Invalid launch reason: " + mReason); + finish(); + return; + } + + final KeyguardManager km = getSystemService(KeyguardManager.class); + if (km == null) { + Log.e(TAG, "Error fetching keyguard manager"); + return; + } + if (km.isDeviceSecure()) { + Log.w(TAG, "Closing the activity since screen lock is already set"); + return; + } + + Log.d(TAG, "Launching screen lock setup dialog due to " + mReason); + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.set_up_screen_lock_title) + .setOnDismissListener(this) + .setPositiveButton(R.string.set_up_screen_lock_action_label, this) + .setNegativeButton(R.string.cancel, this); + setLaunchUserSpecificMessage(builder); + final AlertDialog dialog = builder.create(); + dialog.create(); + getWindow().setHideOverlayWindows(true); + dialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true); + dialog.show(); + } + + @Override + public void onDismiss(DialogInterface dialog) { + finish(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + if (which == DialogInterface.BUTTON_POSITIVE) { + Intent setNewLockIntent = new Intent(ACTION_BIOMETRIC_ENROLL); + setNewLockIntent.putExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, DEVICE_CREDENTIAL); + startActivity(setNewLockIntent); + } else { + finish(); + } + } + + @RequiresPermission(anyOf = { + Manifest.permission.MANAGE_USERS, + Manifest.permission.CREATE_USERS, + Manifest.permission.QUERY_USERS}) + private void setLaunchUserSpecificMessage(AlertDialog.Builder builder) { + if (mReason == LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS) { + // Always set private space message if launch reason is specific to private space + builder.setMessage(R.string.private_space_set_up_screen_lock_message); + return; + } + final UserManager userManager = getApplicationContext().getSystemService(UserManager.class); + if (userManager != null) { + UserInfo userInfo = userManager.getUserInfo(mOriginUserId); + if (userInfo != null && userInfo.isPrivateProfile()) { + builder.setMessage(R.string.private_space_set_up_screen_lock_message); + } + } + } + + /** Returns a basic intent to display the screen lock dialog */ + public static Intent createBaseIntent(@LaunchReason int launchReason) { + Intent intent = new Intent(); + intent.setComponent(new ComponentName(PACKAGE_NAME, + SetScreenLockDialogActivity.class.getName())); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); + intent.putExtra(EXTRA_LAUNCH_REASON, launchReason); + return intent; + } +} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 710b5f8a5a6a..8720f947bb8d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -8370,6 +8370,12 @@ android:process=":ui"> </activity> + <activity android:name="com.android.internal.app.SetScreenLockDialogActivity" + android:theme="@style/Theme.Dialog.Confirmation" + android:excludeFromRecents="true" + android:process=":ui"> + </activity> + <activity android:name="com.android.internal.app.BlockedAppActivity" android:theme="@style/Theme.Dialog.Confirmation" android:excludeFromRecents="true" diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index e9996955a9c0..59066eb83f1c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -5448,6 +5448,13 @@ <!-- Title for button to launch the personal safety app to make an emergency call --> <string name="work_mode_emergency_call_button">Emergency</string> + <!-- Title of the alert dialog prompting the user to set up a screen lock [CHAR LIMIT=30] --> + <string name="set_up_screen_lock_title">Set a screen lock</string> + <!-- Action label for the dialog prompting the user to set up a screen lock [CHAR LIMIT=30] --> + <string name="set_up_screen_lock_action_label">Set screen lock</string> + <!-- Message shown in the dialog prompting the user to set up a screen lock to access private space [CHAR LIMIT=30] --> + <string name="private_space_set_up_screen_lock_message">To use your private space, set a screen lock on this device</string> + <!-- Title of the dialog that is shown when the user tries to launch a blocked application [CHAR LIMIT=50] --> <string name="app_blocked_title">App is not available</string> <!-- Default message shown in the dialog that is shown when the user tries to launch a blocked application [CHAR LIMIT=NONE] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index cf9c02a93267..3284791ef384 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3247,6 +3247,12 @@ <java-symbol type="string" name="work_mode_off_title" /> <java-symbol type="string" name="work_mode_turn_on" /> + <!-- Alert dialog prompting the user to set up a screen lock --> + <java-symbol type="string" name="set_up_screen_lock_title" /> + <java-symbol type="string" name="set_up_screen_lock_action_label" /> + <!-- Message for the alert dialog prompting the user to set up a screen lock to access private space --> + <java-symbol type="string" name="private_space_set_up_screen_lock_message" /> + <java-symbol type="string" name="deprecated_target_sdk_message" /> <java-symbol type="string" name="deprecated_target_sdk_app_store" /> diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index b505a7c1b743..7349755402b1 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.content.Intent.ACTION_SCREEN_OFF; import static android.content.Intent.ACTION_SCREEN_ON; +import static android.content.Intent.EXTRA_USER_ID; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.os.UserManager.DEV_CREATE_OVERRIDE_PROPERTY; @@ -25,6 +26,8 @@ import static android.os.UserManager.DISALLOW_USER_SWITCH; import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY; import static android.os.UserManager.USER_OPERATION_ERROR_UNKNOWN; +import static com.android.internal.app.SetScreenLockDialogActivity.EXTRA_ORIGIN_USER_ID; +import static com.android.internal.app.SetScreenLockDialogActivity.LAUNCH_REASON_DISABLE_QUIET_MODE; import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR; import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_ABORTED; import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_UNSPECIFIED; @@ -137,6 +140,7 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsService; +import com.android.internal.app.SetScreenLockDialogActivity; import com.android.internal.logging.MetricsLogger; import com.android.internal.os.BackgroundThread; import com.android.internal.os.RoSystemProperties; @@ -1676,6 +1680,10 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mUsersLock) { userInfo = getUserInfo(userId); } + if (userInfo == null) { + throw new IllegalArgumentException("Invalid user. Can't find user details " + + "for userId " + userId); + } if (!userInfo.isManagedProfile()) { throw new IllegalArgumentException("Invalid flags: " + flags + ". Can't skip credential check for the user"); @@ -1692,6 +1700,19 @@ public class UserManagerService extends IUserManager.Stub { if (onlyIfCredentialNotRequired) { return false; } + + if (android.multiuser.Flags.showSetScreenLockDialog()) { + // Show the prompt to set a new screen lock if the device does not have one + final KeyguardManager km = mContext.getSystemService(KeyguardManager.class); + if (km != null && !km.isDeviceSecure()) { + Intent setScreenLockPromptIntent = + SetScreenLockDialogActivity + .createBaseIntent(LAUNCH_REASON_DISABLE_QUIET_MODE); + setScreenLockPromptIntent.putExtra(EXTRA_ORIGIN_USER_ID, userId); + mContext.startActivity(setScreenLockPromptIntent); + return false; + } + } showConfirmCredentialToDisableQuietMode(userId, target, callingPackage); return false; } @@ -1915,7 +1936,7 @@ public class UserManagerService extends IUserManager.Stub { if (target != null) { callBackIntent.putExtra(Intent.EXTRA_INTENT, target); } - callBackIntent.putExtra(Intent.EXTRA_USER_ID, userId); + callBackIntent.putExtra(EXTRA_USER_ID, userId); callBackIntent.setPackage(mContext.getPackageName()); callBackIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, callingPackage); callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); |