1 /* 2 * Copyright (C) 2018 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.car.settings.users; 18 19 import android.car.drivingstate.CarUxRestrictions; 20 import android.car.userlib.CarUserManagerHelper; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.AsyncTask; 24 import android.os.Bundle; 25 import android.view.View; 26 import android.widget.ProgressBar; 27 28 import androidx.annotation.XmlRes; 29 30 import com.android.car.settings.R; 31 import com.android.car.settings.common.ConfirmationDialogFragment; 32 import com.android.car.settings.common.ErrorDialog; 33 import com.android.car.settings.common.SettingsFragment; 34 import com.android.car.ui.toolbar.MenuItem; 35 import com.android.internal.annotations.VisibleForTesting; 36 37 import java.util.Collections; 38 import java.util.List; 39 40 /** 41 * Lists all Users available on this device. 42 */ 43 public class UsersListFragment extends SettingsFragment implements 44 ConfirmExitRetailModeDialog.ConfirmExitRetailModeListener, 45 AddNewUserTask.AddNewUserListener { 46 private static final String FACTORY_RESET_PACKAGE_NAME = "android"; 47 private static final String FACTORY_RESET_REASON = "ExitRetailModeConfirmed"; 48 49 private CarUserManagerHelper mCarUserManagerHelper; 50 51 private ProgressBar mProgressBar; 52 private MenuItem mAddUserButton; 53 54 private AsyncTask mAddNewUserTask; 55 /** Indicates that a task is running. */ 56 private boolean mIsBusy; 57 58 @VisibleForTesting 59 final ConfirmationDialogFragment.ConfirmListener mConfirmListener = arguments -> { 60 mAddNewUserTask = new AddNewUserTask(mCarUserManagerHelper, /* addNewUserListener= */ 61 this).execute(getContext().getString(R.string.user_new_user_name)); 62 mIsBusy = true; 63 updateUi(); 64 }; 65 66 @Override getToolbarMenuItems()67 public List<MenuItem> getToolbarMenuItems() { 68 return Collections.singletonList(mAddUserButton); 69 } 70 71 @Override onCreate(Bundle savedInstanceState)72 public void onCreate(Bundle savedInstanceState) { 73 super.onCreate(savedInstanceState); 74 75 mAddUserButton = new MenuItem.Builder(getContext()) 76 .setOnClickListener(i -> handleAddUserClicked()) 77 .setTitle(mCarUserManagerHelper.isCurrentProcessDemoUser() 78 ? R.string.exit_retail_button_text : R.string.user_add_user_menu) 79 .setVisible(mCarUserManagerHelper.isCurrentProcessDemoUser() 80 || mCarUserManagerHelper.canCurrentProcessAddUsers()) 81 .setUxRestrictions(CarUxRestrictions.UX_RESTRICTIONS_NO_SETUP) 82 .build(); 83 } 84 85 @Override 86 @XmlRes getPreferenceScreenResId()87 protected int getPreferenceScreenResId() { 88 return R.xml.users_list_fragment; 89 } 90 91 @Override onAttach(Context context)92 public void onAttach(Context context) { 93 super.onAttach(context); 94 mCarUserManagerHelper = new CarUserManagerHelper(getContext()); 95 } 96 97 @Override onActivityCreated(Bundle savedInstanceState)98 public void onActivityCreated(Bundle savedInstanceState) { 99 super.onActivityCreated(savedInstanceState); 100 mProgressBar = getToolbar().getProgressBar(); 101 } 102 103 /** 104 * Will perform a factory reset. Copied from 105 * {@link com.android.settings.MasterClearConfirm#doMasterClear()} 106 */ 107 @Override onExitRetailModeConfirmed()108 public void onExitRetailModeConfirmed() { 109 Intent intent = new Intent(Intent.ACTION_FACTORY_RESET); 110 intent.setPackage(FACTORY_RESET_PACKAGE_NAME); 111 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 112 intent.putExtra(Intent.EXTRA_REASON, FACTORY_RESET_REASON); 113 intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true); 114 intent.putExtra(Intent.EXTRA_WIPE_ESIMS, true); 115 getActivity().sendBroadcast(intent); 116 // Intent handling is asynchronous -- assume it will happen soon. 117 } 118 119 @Override onStart()120 public void onStart() { 121 super.onStart(); 122 updateUi(); 123 } 124 125 @Override onStop()126 public void onStop() { 127 super.onStop(); 128 mProgressBar.setVisibility(View.GONE); 129 } 130 131 @Override onDestroy()132 public void onDestroy() { 133 super.onDestroy(); 134 135 if (mAddNewUserTask != null) { 136 mAddNewUserTask.cancel(/* mayInterruptIfRunning= */ false); 137 } 138 } 139 140 @Override onUserAddedSuccess()141 public void onUserAddedSuccess() { 142 mIsBusy = false; 143 updateUi(); 144 } 145 146 @Override onUserAddedFailure()147 public void onUserAddedFailure() { 148 mIsBusy = false; 149 updateUi(); 150 // Display failure dialog. 151 ErrorDialog.show(this, R.string.add_user_error_title); 152 } 153 updateUi()154 private void updateUi() { 155 mAddUserButton.setEnabled(!mIsBusy); 156 mProgressBar.setVisibility(mIsBusy ? View.VISIBLE : View.GONE); 157 } 158 handleAddUserClicked()159 private void handleAddUserClicked() { 160 // If the user is a demo user, show a dialog asking if they want to exit retail/demo mode. 161 if (mCarUserManagerHelper.isCurrentProcessDemoUser()) { 162 ConfirmExitRetailModeDialog dialog = new ConfirmExitRetailModeDialog(); 163 dialog.setConfirmExitRetailModeListener(this); 164 dialog.show(this); 165 return; 166 } 167 168 // If no more users can be added because the maximum allowed number is reached, let the user 169 // know. 170 if (mCarUserManagerHelper.isUserLimitReached()) { 171 MaxUsersLimitReachedDialog dialog = new MaxUsersLimitReachedDialog( 172 mCarUserManagerHelper.getMaxSupportedRealUsers()); 173 dialog.show(this); 174 return; 175 } 176 177 // Only add the add user button if the current user is allowed to add a user. 178 if (mCarUserManagerHelper.canCurrentProcessAddUsers()) { 179 ConfirmationDialogFragment dialogFragment = 180 UsersDialogProvider.getConfirmCreateNewUserDialogFragment(getContext(), 181 mConfirmListener, null); 182 183 dialogFragment.show(getFragmentManager(), ConfirmationDialogFragment.TAG); 184 } 185 } 186 } 187