| /* |
| * Copyright (C) 2021 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.car.settings.profiles; |
| |
| import static android.os.UserManager.DISALLOW_ADD_USER; |
| |
| import static com.android.car.settings.common.PreferenceController.AVAILABLE; |
| import static com.android.car.settings.common.PreferenceController.AVAILABLE_FOR_VIEWING; |
| import static com.android.car.settings.common.PreferenceController.DISABLED_FOR_PROFILE; |
| import static com.android.car.settings.enterprise.ActionDisabledByAdminDialogFragment.DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG; |
| import static com.android.car.settings.enterprise.EnterpriseUtils.hasUserRestrictionByDpm; |
| import static com.android.car.settings.enterprise.EnterpriseUtils.hasUserRestrictionByUm; |
| |
| import android.car.Car; |
| import android.car.user.CarUserManager; |
| import android.content.Context; |
| import android.os.UserManager; |
| import android.widget.Toast; |
| |
| import androidx.annotation.VisibleForTesting; |
| import androidx.preference.Preference; |
| |
| import com.android.car.settings.R; |
| import com.android.car.settings.common.ConfirmationDialogFragment; |
| import com.android.car.settings.common.ErrorDialog; |
| import com.android.car.settings.common.FragmentController; |
| import com.android.car.settings.common.PreferenceController; |
| import com.android.car.settings.enterprise.EnterpriseUtils; |
| |
| /** |
| * Consolidates adding profile logic into one handler so we can have consistent logic across various |
| * parts of the Settings app. |
| */ |
| public class AddProfileHandler implements AddNewProfileTask.AddNewProfileListener { |
| |
| @VisibleForTesting |
| static final String CONFIRM_CREATE_NEW_PROFILE_DIALOG_TAG = |
| "com.android.car.settings.profiles.ConfirmCreateNewProfileDialog"; |
| @VisibleForTesting |
| static final String MAX_PROFILES_LIMIT_REACHED_DIALOG_TAG = |
| "com.android.car.settings.profiles.MaxProfilesLimitReachedDialog"; |
| |
| @VisibleForTesting |
| AddNewProfileTask mAddNewProfileTask; |
| /** Indicates that a task is running. */ |
| private boolean mIsBusy; |
| |
| private final Context mContext; |
| private final FragmentController mFragmentController; |
| private final PreferenceController mPreferenceController; |
| private final Car mCar; |
| private CarUserManager mCarUserManager; |
| |
| @VisibleForTesting |
| ConfirmationDialogFragment.ConfirmListener mConfirmCreateNewProfileListener; |
| |
| public AddProfileHandler(Context context, FragmentController fragmentController, |
| PreferenceController preferenceController) { |
| mContext = context; |
| mFragmentController = fragmentController; |
| mPreferenceController = preferenceController; |
| mCar = Car.createCar(context); |
| mCarUserManager = (CarUserManager) mCar.getCarManager(Car.CAR_USER_SERVICE); |
| |
| mConfirmCreateNewProfileListener = arguments -> { |
| mAddNewProfileTask = new AddNewProfileTask(mContext, |
| mCarUserManager, /* addNewProfileListener= */ this); |
| mAddNewProfileTask.execute(mContext.getString(R.string.user_new_user_name)); |
| |
| mIsBusy = true; |
| mPreferenceController.refreshUi(); |
| }; |
| } |
| |
| /** |
| * Handles operations that should happen in host's onCreateInternal(). |
| * Resets listeners as they can get unregistered with certain configuration changes. |
| */ |
| public void onCreateInternal() { |
| ConfirmationDialogFragment.resetListeners( |
| (ConfirmationDialogFragment) mFragmentController.findDialogByTag( |
| CONFIRM_CREATE_NEW_PROFILE_DIALOG_TAG), |
| mConfirmCreateNewProfileListener, |
| /* rejectListener= */ null, |
| /* neutralListener= */ null); |
| } |
| |
| /** |
| * Handles operations that should happen in host's onStopInternal(). |
| */ |
| public void onStopInternal() { |
| mFragmentController.showProgressBar(false); |
| } |
| |
| /** |
| * Handles events that should happen in host's onDestroyInternal(). |
| */ |
| public void onDestroyInternal() { |
| if (mAddNewProfileTask != null) { |
| mAddNewProfileTask.cancel(/* mayInterruptIfRunning= */ false); |
| } |
| if (mCar != null) { |
| mCar.disconnect(); |
| } |
| } |
| |
| /** |
| * Handles events that should happen in host's updateState() when there is task running. |
| */ |
| public void updateState(Preference preference) { |
| preference.setEnabled(!mIsBusy); |
| mFragmentController.showProgressBar(mIsBusy); |
| } |
| |
| @Override |
| public void onProfileAddedSuccess() { |
| mIsBusy = false; |
| mPreferenceController.refreshUi(); |
| } |
| |
| @Override |
| public void onProfileAddedFailure() { |
| mIsBusy = false; |
| mPreferenceController.refreshUi(); |
| // Display failure dialog. |
| mFragmentController.showDialog( |
| ErrorDialog.newInstance(R.string.add_user_error_title), /* tag= */ null); |
| } |
| |
| /** |
| * Determines whether the user manager instance has the permission to add profiles |
| * |
| * @param userManager UserManager instance to evaluate |
| * @return whether the user has permissions to add profiles |
| */ |
| public static boolean canAddProfiles(UserManager userManager) { |
| return !userManager.hasUserRestriction(DISALLOW_ADD_USER); |
| } |
| |
| /** |
| * Returns {@code PreferenceController.AVAILABLE} when preference should be available, |
| * {@code PreferenceController.DISABLED_FOR_PROFILE} when preference should be unavailable, |
| * {@code PreferenceController.AVAILABLE_FOR_VIEWING} when preference is visible but |
| * disabled. |
| */ |
| public static int getAddProfilePreferenceAvailabilityStatus(Context context) { |
| UserManager um = getUserManager(context); |
| if (um.isDemoUser() || canAddProfiles(um)) { |
| return AVAILABLE; |
| } |
| if (hasUserRestrictionByUm(context, DISALLOW_ADD_USER)) { |
| return DISABLED_FOR_PROFILE; |
| } |
| return AVAILABLE_FOR_VIEWING; |
| } |
| |
| /** |
| * Display dialog to add a profile |
| */ |
| public void showAddProfileDialog() { |
| ConfirmationDialogFragment dialogFragment = |
| ProfilesDialogProvider.getConfirmCreateNewProfileDialogFragment( |
| mContext, mConfirmCreateNewProfileListener, null); |
| |
| mFragmentController.showDialog(dialogFragment, CONFIRM_CREATE_NEW_PROFILE_DIALOG_TAG); |
| } |
| |
| /** |
| * Shows a dialog or toast when the Preference is disabled while still visible. |
| */ |
| public void runClickableWhileDisabled() { |
| if (hasUserRestrictionByDpm(mContext, DISALLOW_ADD_USER)) { |
| // Shows a dialog if this PreferenceController is disabled because there is |
| // restriction set from DevicePolicyManager |
| showActionDisabledByAdminDialog(); |
| } else if (!getUserManager(mContext).canAddMoreUsers()) { |
| // Shows a dialog if no more profiles can be added because the maximum allowed number |
| // is reached |
| ConfirmationDialogFragment dialogFragment = |
| ProfilesDialogProvider.getMaxProfilesLimitReachedDialogFragment(mContext, |
| ProfileHelper.getInstance(mContext).getMaxSupportedRealProfiles()); |
| mFragmentController.showDialog(dialogFragment, MAX_PROFILES_LIMIT_REACHED_DIALOG_TAG); |
| } else { |
| Toast.makeText(mContext, mContext.getString(R.string.action_unavailable), |
| Toast.LENGTH_LONG).show(); |
| } |
| } |
| |
| private void showActionDisabledByAdminDialog() { |
| mFragmentController.showDialog( |
| EnterpriseUtils.getActionDisabledByAdminDialog(mContext, DISALLOW_ADD_USER), |
| DISABLED_BY_ADMIN_CONFIRM_DIALOG_TAG); |
| } |
| |
| private static UserManager getUserManager(Context context) { |
| return context.getSystemService(UserManager.class); |
| } |
| |
| @VisibleForTesting |
| void setCarUserManager(CarUserManager carUserManager) { |
| mCarUserManager = carUserManager; |
| } |
| } |