1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.app; 18 19 import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; 20 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; 21 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 22 import static android.hardware.biometrics.BiometricManager.Authenticators.DEVICE_CREDENTIAL; 23 import static android.provider.Settings.ACTION_BIOMETRIC_ENROLL; 24 import static android.provider.Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED; 25 26 import android.Manifest; 27 import android.annotation.IntDef; 28 import android.annotation.RequiresPermission; 29 import android.app.AlertDialog; 30 import android.app.KeyguardManager; 31 import android.content.ComponentName; 32 import android.content.DialogInterface; 33 import android.content.Intent; 34 import android.content.pm.UserInfo; 35 import android.os.Bundle; 36 import android.os.UserHandle; 37 import android.os.UserManager; 38 import android.util.Log; 39 40 import com.android.internal.R; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 45 /** 46 * A dialog shown to the user that prompts them to set the screen lock for the current foreground 47 * user. Should be called from the context of foreground user. 48 */ 49 public class SetScreenLockDialogActivity extends AlertActivity 50 implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener { 51 private static final String TAG = "SetScreenLockDialog"; 52 public static final String EXTRA_LAUNCH_REASON = "launch_reason"; 53 /** 54 * User id associated with the workflow that wants to launch the prompt to set up the 55 * screen lock 56 */ 57 public static final String EXTRA_ORIGIN_USER_ID = "origin_user_id"; 58 private static final String PACKAGE_NAME = "android"; 59 @IntDef(prefix = "LAUNCH_REASON_", value = { 60 LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS, 61 LAUNCH_REASON_DISABLE_QUIET_MODE, 62 LAUNCH_REASON_UNKNOWN, 63 LAUNCH_REASON_RESET_PRIVATE_SPACE_SETTINGS_ACCESS, 64 }) 65 @Retention(RetentionPolicy.SOURCE) 66 public @interface LaunchReason { 67 } 68 public static final int LAUNCH_REASON_UNKNOWN = -1; 69 public static final int LAUNCH_REASON_DISABLE_QUIET_MODE = 1; 70 public static final int LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS = 2; 71 public static final int LAUNCH_REASON_RESET_PRIVATE_SPACE_SETTINGS_ACCESS = 3; 72 private @LaunchReason int mReason; 73 private int mOriginUserId; 74 75 @Override 76 @RequiresPermission(HIDE_OVERLAY_WINDOWS) onCreate(Bundle savedInstanceState)77 protected void onCreate(Bundle savedInstanceState) { 78 super.onCreate(savedInstanceState); 79 if (!(android.os.Flags.allowPrivateProfile() 80 && android.multiuser.Flags.showSetScreenLockDialog() 81 && android.multiuser.Flags.enablePrivateSpaceFeatures())) { 82 finish(); 83 return; 84 } 85 Intent intent = getIntent(); 86 mReason = intent.getIntExtra(EXTRA_LAUNCH_REASON, LAUNCH_REASON_UNKNOWN); 87 mOriginUserId = intent.getIntExtra(EXTRA_ORIGIN_USER_ID, UserHandle.USER_NULL); 88 89 if (mReason == LAUNCH_REASON_UNKNOWN) { 90 Log.e(TAG, "Invalid launch reason: " + mReason); 91 finish(); 92 return; 93 } 94 95 final KeyguardManager km = getSystemService(KeyguardManager.class); 96 if (km == null) { 97 Log.e(TAG, "Error fetching keyguard manager"); 98 return; 99 } 100 if (km.isDeviceSecure()) { 101 Log.w(TAG, "Closing the activity since screen lock is already set"); 102 return; 103 } 104 105 Log.d(TAG, "Launching screen lock setup dialog due to " + mReason); 106 final AlertDialog.Builder builder = new AlertDialog.Builder(this); 107 builder.setTitle(R.string.set_up_screen_lock_title) 108 .setOnDismissListener(this) 109 .setPositiveButton(R.string.set_up_screen_lock_action_label, this) 110 .setNegativeButton(R.string.cancel, this); 111 setLaunchUserSpecificMessage(builder); 112 final AlertDialog dialog = builder.create(); 113 dialog.create(); 114 getWindow().setHideOverlayWindows(true); 115 dialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true); 116 dialog.show(); 117 } 118 119 @Override onDismiss(DialogInterface dialog)120 public void onDismiss(DialogInterface dialog) { 121 finish(); 122 } 123 124 @Override onClick(DialogInterface dialog, int which)125 public void onClick(DialogInterface dialog, int which) { 126 if (which == DialogInterface.BUTTON_POSITIVE) { 127 Intent setNewLockIntent = new Intent(ACTION_BIOMETRIC_ENROLL); 128 setNewLockIntent.putExtra(EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED, DEVICE_CREDENTIAL); 129 startActivity(setNewLockIntent); 130 } else { 131 finish(); 132 } 133 } 134 135 @RequiresPermission(anyOf = { 136 Manifest.permission.MANAGE_USERS, 137 Manifest.permission.CREATE_USERS, 138 Manifest.permission.QUERY_USERS}) setLaunchUserSpecificMessage(AlertDialog.Builder builder)139 private void setLaunchUserSpecificMessage(AlertDialog.Builder builder) { 140 if (mReason == LAUNCH_REASON_PRIVATE_SPACE_SETTINGS_ACCESS) { 141 // Always set private space message if launch reason is specific to private space 142 builder.setMessage(R.string.private_space_set_up_screen_lock_message); 143 return; 144 } else if (mReason == LAUNCH_REASON_RESET_PRIVATE_SPACE_SETTINGS_ACCESS) { 145 builder.setMessage(R.string.private_space_set_up_screen_lock_for_reset); 146 return; 147 } 148 149 final UserManager userManager = getApplicationContext().getSystemService(UserManager.class); 150 if (userManager != null) { 151 UserInfo userInfo = userManager.getUserInfo(mOriginUserId); 152 if (userInfo != null && userInfo.isPrivateProfile()) { 153 builder.setMessage(R.string.private_space_set_up_screen_lock_message); 154 } 155 } 156 } 157 158 /** Returns a basic intent to display the screen lock dialog */ createBaseIntent(@aunchReason int launchReason)159 public static Intent createBaseIntent(@LaunchReason int launchReason) { 160 Intent intent = new Intent(); 161 intent.setComponent(new ComponentName(PACKAGE_NAME, 162 SetScreenLockDialogActivity.class.getName())); 163 intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 164 intent.putExtra(EXTRA_LAUNCH_REASON, launchReason); 165 return intent; 166 } 167 } 168