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.car.settings.profiles; 18 19 import static com.android.car.settings.common.ActionButtonsPreference.ActionButtons; 20 21 import android.car.drivingstate.CarUxRestrictions; 22 import android.content.Context; 23 import android.content.pm.UserInfo; 24 import android.os.UserManager; 25 26 import androidx.annotation.VisibleForTesting; 27 28 import com.android.car.settings.R; 29 import com.android.car.settings.common.ActionButtonInfo; 30 import com.android.car.settings.common.ActionButtonsPreference; 31 import com.android.car.settings.common.ConfirmationDialogFragment; 32 import com.android.car.settings.common.FragmentController; 33 34 /** 35 * Displays the action buttons for profile details. 36 * 37 * <p>The actions shown depends on the current and selected profile. 38 * <ol> 39 * <li>Rename: shown if selected profile is the current profile 40 * <li>Make admin: shown if current profile is an admin and the selected profile is not 41 * <li>Manage other profiles: shown if selected profile is the current profile and 42 * there are other profiles 43 * <li>Add a profile: shown if selected profile is the current profile and 44 * there are no other profiles 45 * <li> Exit demo: shown if selected profile is the current profile and is a demo 46 * <li>Delete: shown if the current profile is allowed to remove profiles, is not a demo 47 * profile, and selected profile is not the current profile 48 * </ol> 49 */ 50 public final class ProfileDetailsActionButtonsPreferenceController 51 extends ProfileDetailsBasePreferenceController<ActionButtonsPreference> { 52 53 @VisibleForTesting 54 static final String MAKE_ADMIN_DIALOG_TAG = "MakeAdminDialogFragment"; 55 56 private final ProfileHelper mProfileHelper; 57 private final UserManager mUserManager; 58 private DemoProfileDialogHandler mDemoProfileDialogHandler; 59 private AddProfileHandler mAddProfileHandler; 60 61 @VisibleForTesting 62 final ConfirmationDialogFragment.ConfirmListener mMakeAdminConfirmListener = 63 arguments -> { 64 UserInfo profileToMakeAdmin = 65 (UserInfo) arguments.get(ProfilesDialogProvider.KEY_PROFILE_TO_MAKE_ADMIN); 66 android.car.userlib.UserHelper.grantAdminPermissions(getContext(), 67 profileToMakeAdmin); 68 getFragmentController().goBack(); 69 }; 70 71 private final RemoveProfileHandler mRemoveProfileHandler; 72 ProfileDetailsActionButtonsPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)73 public ProfileDetailsActionButtonsPreferenceController(Context context, 74 String preferenceKey, FragmentController fragmentController, 75 CarUxRestrictions uxRestrictions) { 76 this(context, preferenceKey, fragmentController, uxRestrictions, 77 ProfileHelper.getInstance(context), UserManager.get(context), 78 new RemoveProfileHandler(context, ProfileHelper.getInstance(context), 79 UserManager.get(context), fragmentController)); 80 } 81 82 @VisibleForTesting ProfileDetailsActionButtonsPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions, ProfileHelper profileHelper, UserManager userManager, RemoveProfileHandler removeProfileHandler)83 ProfileDetailsActionButtonsPreferenceController(Context context, 84 String preferenceKey, FragmentController fragmentController, 85 CarUxRestrictions uxRestrictions, ProfileHelper profileHelper, UserManager userManager, 86 RemoveProfileHandler removeProfileHandler) { 87 super(context, preferenceKey, fragmentController, uxRestrictions); 88 mProfileHelper = profileHelper; 89 mUserManager = userManager; 90 mRemoveProfileHandler = removeProfileHandler; 91 mDemoProfileDialogHandler = new DemoProfileDialogHandler(context, fragmentController); 92 mAddProfileHandler = new AddProfileHandler(context, fragmentController, this); 93 } 94 95 @Override getPreferenceType()96 protected Class<ActionButtonsPreference> getPreferenceType() { 97 return ActionButtonsPreference.class; 98 } 99 100 @Override onCreateInternal()101 protected void onCreateInternal() { 102 super.onCreateInternal(); 103 104 mDemoProfileDialogHandler.onCreateInternal(); 105 mAddProfileHandler.onCreateInternal(); 106 107 ConfirmationDialogFragment makeAdminDialog = 108 (ConfirmationDialogFragment) getFragmentController().findDialogByTag( 109 MAKE_ADMIN_DIALOG_TAG); 110 ConfirmationDialogFragment.resetListeners( 111 makeAdminDialog, 112 mMakeAdminConfirmListener, 113 /* rejectListener= */ null, 114 /* neutralListener= */ null); 115 116 mRemoveProfileHandler.resetListeners(); 117 } 118 119 @Override onStartInternal()120 protected void onStartInternal() { 121 super.onStartInternal(); 122 123 ActionButtonInfo renameButton = getPreference().getButton(ActionButtons.BUTTON1); 124 ActionButtonInfo makeAdminButton = getPreference().getButton(ActionButtons.BUTTON2); 125 ActionButtonInfo profilesButton = getPreference().getButton(ActionButtons.BUTTON3); 126 ActionButtonInfo deleteButton = getPreference().getButton(ActionButtons.BUTTON4); 127 128 boolean isDemoProfile = mUserManager.isDemoUser(); 129 boolean shouldShowAddProfile = mUserManager.isAdminUser() 130 && mProfileHelper.isCurrentProcessUser(getUserInfo()) 131 && mAddProfileHandler.canAddProfiles(mUserManager) 132 && !areThereOtherProfiles(); 133 boolean shouldShowProfilesButton = isDemoProfile || shouldShowAddProfile 134 || mUserManager.isAdminUser() && mProfileHelper.isCurrentProcessUser(getUserInfo()) 135 && areThereOtherProfiles(); 136 137 int profileButtonText; 138 if (shouldShowAddProfile && isDemoProfile) { 139 profileButtonText = R.string.exit_retail_button_text; 140 } else if (shouldShowAddProfile) { 141 profileButtonText = R.string.add_a_profile_button_text; 142 } else { 143 profileButtonText = R.string.manage_other_profiles_button_text; 144 } 145 146 renameButton 147 .setText(R.string.bluetooth_rename_button) 148 .setIcon(R.drawable.ic_edit) 149 .setVisible(mProfileHelper.isCurrentProcessUser(getUserInfo())) 150 .setOnClickListener(v -> getFragmentController().launchFragment( 151 EditProfileNameFragment.newInstance(getUserInfo()))); 152 153 makeAdminButton 154 .setText(R.string.grant_admin_permissions_button_text) 155 .setIcon(R.drawable.ic_person) 156 .setVisible(ProfileUtils.isAdminViewingNonAdmin(mUserManager, getUserInfo())) 157 .setOnClickListener(v -> showConfirmMakeAdminDialog()); 158 159 profilesButton 160 .setText(profileButtonText) 161 .setVisible(shouldShowProfilesButton) 162 .setOnClickListener(v -> { 163 if (shouldShowAddProfile && isDemoProfile) { 164 mDemoProfileDialogHandler.showExitRetailDialog(); 165 } else if (shouldShowAddProfile) { 166 mAddProfileHandler.showAddProfileDialog(); 167 } else { 168 getFragmentController().launchFragment( 169 new ProfilesListFragment()); 170 } 171 }); 172 173 if (!isDemoProfile && shouldShowAddProfile) { 174 profilesButton.setIcon(R.drawable.ic_add); 175 } else if (!isDemoProfile && shouldShowProfilesButton) { 176 profilesButton.setIcon(R.drawable.ic_people); 177 } 178 179 // Do not show delete button if the current profile can't remove the selected profile 180 deleteButton 181 .setText(R.string.delete_button) 182 .setIcon(R.drawable.ic_delete) 183 .setVisible(mRemoveProfileHandler.canRemoveProfile(getUserInfo()) 184 && !mProfileHelper.isCurrentProcessUser(getUserInfo())) 185 .setOnClickListener(v -> mRemoveProfileHandler.showConfirmRemoveProfileDialog()); 186 } 187 188 @Override setUserInfo(UserInfo userInfo)189 public void setUserInfo(UserInfo userInfo) { 190 super.setUserInfo(userInfo); 191 mRemoveProfileHandler.setUserInfo(userInfo); 192 } 193 194 @Override onStopInternal()195 protected void onStopInternal() { 196 super.onStopInternal(); 197 mAddProfileHandler.onStopInternal(); 198 } 199 200 @Override onDestroyInternal()201 protected void onDestroyInternal() { 202 super.onDestroyInternal(); 203 mAddProfileHandler.onDestroyInternal(); 204 } 205 206 @Override updateState(ActionButtonsPreference preference)207 protected void updateState(ActionButtonsPreference preference) { 208 mAddProfileHandler.updateState(preference); 209 } 210 showConfirmMakeAdminDialog()211 private void showConfirmMakeAdminDialog() { 212 ConfirmationDialogFragment dialogFragment = 213 ProfilesDialogProvider.getConfirmGrantAdminDialogFragment(getContext(), 214 mMakeAdminConfirmListener, /* rejectListener= */ null, getUserInfo()); 215 216 getFragmentController().showDialog(dialogFragment, MAKE_ADMIN_DIALOG_TAG); 217 } 218 areThereOtherProfiles()219 private boolean areThereOtherProfiles() { 220 UserInfo currUserInfo = mProfileHelper.getCurrentProcessUserInfo(); 221 return !mProfileHelper.getAllLivingProfiles( 222 userInfo -> !userInfo.isGuest() && userInfo.id != currUserInfo.id).isEmpty(); 223 } 224 } 225