1 /* 2 * Copyright (C) 2020 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.systemui.user; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.app.IActivityManager; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.graphics.drawable.Drawable; 25 import android.os.Bundle; 26 import android.os.RemoteException; 27 import android.util.Log; 28 import android.window.OnBackInvokedCallback; 29 import android.window.OnBackInvokedDispatcher; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 34 import com.android.settingslib.users.EditUserInfoController; 35 import com.android.systemui.R; 36 import com.android.systemui.plugins.ActivityStarter; 37 38 import javax.inject.Inject; 39 40 /** 41 * This screen shows a Dialog for choosing nickname and photo for a new user, and then delegates the 42 * user creation to a UserCreator. 43 */ 44 public class CreateUserActivity extends Activity { 45 46 /** 47 * Creates an intent to start this activity. 48 */ createIntentForStart(Context context)49 public static Intent createIntentForStart(Context context) { 50 Intent intent = new Intent(context, CreateUserActivity.class); 51 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); 52 return intent; 53 } 54 55 private static final String TAG = "CreateUserActivity"; 56 private static final String DIALOG_STATE_KEY = "create_user_dialog_state"; 57 58 private final UserCreator mUserCreator; 59 private final EditUserInfoController mEditUserInfoController; 60 private final IActivityManager mActivityManager; 61 private final ActivityStarter mActivityStarter; 62 63 private Dialog mSetupUserDialog; 64 private final OnBackInvokedCallback mBackCallback = this::onBackInvoked; 65 66 @Inject CreateUserActivity(UserCreator userCreator, EditUserInfoController editUserInfoController, IActivityManager activityManager, ActivityStarter activityStarter)67 public CreateUserActivity(UserCreator userCreator, 68 EditUserInfoController editUserInfoController, IActivityManager activityManager, 69 ActivityStarter activityStarter) { 70 mUserCreator = userCreator; 71 mEditUserInfoController = editUserInfoController; 72 mActivityManager = activityManager; 73 mActivityStarter = activityStarter; 74 } 75 76 @Override onCreate(@ullable Bundle savedInstanceState)77 protected void onCreate(@Nullable Bundle savedInstanceState) { 78 super.onCreate(savedInstanceState); 79 setShowWhenLocked(true); 80 setContentView(R.layout.activity_create_new_user); 81 82 if (savedInstanceState != null) { 83 mEditUserInfoController.onRestoreInstanceState(savedInstanceState); 84 } 85 86 mSetupUserDialog = createDialog(); 87 mSetupUserDialog.show(); 88 89 getOnBackInvokedDispatcher().registerOnBackInvokedCallback( 90 OnBackInvokedDispatcher.PRIORITY_DEFAULT, 91 mBackCallback); 92 } 93 94 @Override onSaveInstanceState(@onNull Bundle outState)95 protected void onSaveInstanceState(@NonNull Bundle outState) { 96 if (mSetupUserDialog != null && mSetupUserDialog.isShowing()) { 97 outState.putBundle(DIALOG_STATE_KEY, mSetupUserDialog.onSaveInstanceState()); 98 } 99 100 mEditUserInfoController.onSaveInstanceState(outState); 101 super.onSaveInstanceState(outState); 102 } 103 104 @Override onRestoreInstanceState(@onNull Bundle savedInstanceState)105 protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { 106 super.onRestoreInstanceState(savedInstanceState); 107 Bundle savedDialogState = savedInstanceState.getBundle(DIALOG_STATE_KEY); 108 if (savedDialogState != null && mSetupUserDialog != null) { 109 mSetupUserDialog.onRestoreInstanceState(savedDialogState); 110 } 111 } 112 createDialog()113 private Dialog createDialog() { 114 String defaultUserName = getString(com.android.settingslib.R.string.user_new_user_name); 115 116 return mEditUserInfoController.createDialog( 117 this, 118 this::startActivity, 119 null, 120 defaultUserName, 121 getString(com.android.settingslib.R.string.user_add_user), 122 this::addUserNow, 123 this::finish 124 ); 125 } 126 127 @Override onActivityResult(int requestCode, int resultCode, Intent data)128 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 129 super.onActivityResult(requestCode, resultCode, data); 130 mEditUserInfoController.onActivityResult(requestCode, resultCode, data); 131 } 132 133 @Override onBackPressed()134 public void onBackPressed() { 135 onBackInvoked(); 136 } 137 onBackInvoked()138 private void onBackInvoked() { 139 if (mSetupUserDialog != null) { 140 mSetupUserDialog.dismiss(); 141 } 142 finish(); 143 } 144 145 @Override onDestroy()146 protected void onDestroy() { 147 getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mBackCallback); 148 super.onDestroy(); 149 } 150 addUserNow(String userName, Drawable userIcon)151 private void addUserNow(String userName, Drawable userIcon) { 152 mSetupUserDialog.dismiss(); 153 154 userName = (userName == null || userName.trim().isEmpty()) 155 ? getString(com.android.settingslib.R.string.user_new_user_name) 156 : userName; 157 158 mUserCreator.createUser(userName, userIcon, 159 userInfo -> { 160 switchToUser(userInfo.id); 161 finishIfNeeded(); 162 }, () -> { 163 Log.e(TAG, "Unable to create user"); 164 finishIfNeeded(); 165 }); 166 } 167 finishIfNeeded()168 private void finishIfNeeded() { 169 if (!isFinishing() && !isDestroyed()) { 170 finish(); 171 } 172 } 173 switchToUser(int userId)174 private void switchToUser(int userId) { 175 try { 176 mActivityManager.switchUser(userId); 177 } catch (RemoteException e) { 178 Log.e(TAG, "Couldn't switch user.", e); 179 } 180 } 181 182 /** 183 * Lambda to start activity from an intent. Ensures that device is unlocked first. 184 * @param intent 185 * @param requestCode 186 */ startActivity(Intent intent, int requestCode)187 private void startActivity(Intent intent, int requestCode) { 188 mActivityStarter.dismissKeyguardThenExecute(() -> { 189 mEditUserInfoController.startingActivityForResult(); 190 startActivityForResult(intent, requestCode); 191 return true; 192 }, /* cancel= */ null, /* afterKeyguardGone= */ true); 193 } 194 } 195