Home | History | Annotate | Download | only in accounts
      1 /*
      2  * Copyright (C) 2017 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 package com.android.car.settings.accounts;
     17 
     18 import android.accounts.Account;
     19 import android.accounts.AccountManager;
     20 import android.accounts.AccountManagerCallback;
     21 import android.accounts.AccountManagerFuture;
     22 import android.accounts.AuthenticatorException;
     23 import android.accounts.OperationCanceledException;
     24 import android.app.Activity;
     25 import android.app.Dialog;
     26 import android.content.DialogInterface;
     27 import android.content.Intent;
     28 import android.content.pm.UserInfo;
     29 import android.graphics.drawable.Drawable;
     30 import android.os.Bundle;
     31 import android.os.UserHandle;
     32 import android.support.v4.app.DialogFragment;
     33 import android.support.v4.app.Fragment;
     34 import android.text.TextUtils;
     35 import android.widget.Button;
     36 
     37 import androidx.car.app.CarAlertDialog;
     38 import androidx.car.widget.ListItem;
     39 import androidx.car.widget.ListItemProvider;
     40 import androidx.car.widget.TextListItem;
     41 
     42 import com.android.car.settings.R;
     43 import com.android.car.settings.common.ListItemSettingsFragment;
     44 import com.android.car.settings.common.Logger;
     45 import com.android.settingslib.accounts.AuthenticatorHelper;
     46 
     47 import java.io.IOException;
     48 import java.util.ArrayList;
     49 import java.util.List;
     50 
     51 /**
     52  * Shows account details, and delete account option.
     53  */
     54 public class AccountDetailsFragment extends ListItemSettingsFragment
     55         implements AuthenticatorHelper.OnAccountsUpdateListener {
     56     public static final String EXTRA_ACCOUNT_INFO = "extra_account_info";
     57     public static final String EXTRA_USER_INFO = "extra_user_info";
     58 
     59     private Account mAccount;
     60     private UserInfo mUserInfo;
     61     private ListItemProvider mItemProvider;
     62     private AccountManagerHelper mAccountManagerHelper;
     63 
     64     public static AccountDetailsFragment newInstance(
     65             Account account, UserInfo userInfo) {
     66         AccountDetailsFragment
     67                 accountDetailsFragment = new AccountDetailsFragment();
     68         Bundle bundle = ListItemSettingsFragment.getBundle();
     69         bundle.putInt(EXTRA_ACTION_BAR_LAYOUT, R.layout.action_bar_with_button);
     70         bundle.putInt(EXTRA_TITLE_ID, R.string.account_details_title);
     71         bundle.putParcelable(EXTRA_ACCOUNT_INFO, account);
     72         bundle.putParcelable(EXTRA_USER_INFO, userInfo);
     73         accountDetailsFragment.setArguments(bundle);
     74         return accountDetailsFragment;
     75     }
     76 
     77     @Override
     78     public void onCreate(Bundle savedInstanceState) {
     79         super.onCreate(savedInstanceState);
     80         mAccount = getArguments().getParcelable(EXTRA_ACCOUNT_INFO);
     81         mUserInfo = getArguments().getParcelable(EXTRA_USER_INFO);
     82     }
     83 
     84     @Override
     85     public void onActivityCreated(Bundle savedInstanceState) {
     86         // Should be created before calling getListItem().
     87         mAccountManagerHelper = new AccountManagerHelper(getContext(), this);
     88         mAccountManagerHelper.startListeningToAccountUpdates();
     89 
     90         mItemProvider = new ListItemProvider.ListProvider(getListItems());
     91 
     92         // Super is called only AFTER item provider is instantiated, because
     93         // super.onActivityCreated calls getItemProvider().
     94         super.onActivityCreated(savedInstanceState);
     95 
     96         // Title was set in super.onActivityCreated, but override if account label is available.
     97         setFragmentTitle();
     98 
     99         showRemoveButton();
    100     }
    101 
    102     @Override
    103     public void onAccountsUpdate(UserHandle userHandle) {
    104         if (!mAccountManagerHelper.accountExists(mAccount)) {
    105             // The account was deleted. Pop back.
    106             getFragmentController().goBack();
    107         }
    108     }
    109 
    110     @Override
    111     public ListItemProvider getItemProvider() {
    112         return mItemProvider;
    113     }
    114 
    115     private void showRemoveButton() {
    116         Button removeAccountBtn = getActivity().findViewById(R.id.action_button1);
    117         removeAccountBtn.setText(R.string.remove_button);
    118         removeAccountBtn.setOnClickListener(v -> removeAccount());
    119     }
    120 
    121     private void setFragmentTitle() {
    122         CharSequence accountLabel = mAccountManagerHelper.getLabelForType(mAccount.type);
    123         if (!TextUtils.isEmpty(accountLabel)) {
    124             setTitle(accountLabel);
    125         }
    126     }
    127 
    128     private List<ListItem> getListItems() {
    129         Drawable icon = mAccountManagerHelper.getDrawableForType(mAccount.type);
    130 
    131         TextListItem item = new TextListItem(getContext());
    132         item.setPrimaryActionIcon(icon, /* useLargeIcon= */ false);
    133         item.setTitle(mAccount.name);
    134 
    135         List<ListItem> items = new ArrayList<>();
    136         items.add(item);
    137         return items;
    138     }
    139 
    140     public void removeAccount() {
    141         ConfirmRemoveAccountDialog.show(this, mAccount, mUserInfo.getUserHandle());
    142     }
    143 
    144     /**
    145      * Dialog to confirm with user about account removal
    146      */
    147     public static class ConfirmRemoveAccountDialog extends DialogFragment implements
    148             DialogInterface.OnClickListener {
    149         private static final String KEY_ACCOUNT = "account";
    150         private static final String DIALOG_TAG = "confirmRemoveAccount";
    151         private static final Logger LOG = new Logger(ConfirmRemoveAccountDialog.class);
    152         private Account mAccount;
    153         private UserHandle mUserHandle;
    154 
    155         private final AccountManagerCallback<Bundle> mCallback =
    156             new AccountManagerCallback<Bundle>() {
    157                 @Override
    158                 public void run(AccountManagerFuture<Bundle> future) {
    159                     // If already out of this screen, don't proceed.
    160                     if (!getTargetFragment().isResumed()) {
    161                         return;
    162                     }
    163 
    164                     boolean success = false;
    165                     try {
    166                         success =
    167                                 future.getResult().getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
    168                     } catch (OperationCanceledException | IOException | AuthenticatorException e) {
    169                         LOG.v("removeAccount error: " + e);
    170                     }
    171                     final Activity activity = getTargetFragment().getActivity();
    172                     if (!success && activity != null && !activity.isFinishing()) {
    173                         RemoveAccountFailureDialog.show(getTargetFragment());
    174                     } else {
    175                         getTargetFragment().getFragmentManager().popBackStack();
    176                     }
    177                 }
    178             };
    179 
    180         public static void show(
    181                 Fragment parent, Account account, UserHandle userHandle) {
    182             final ConfirmRemoveAccountDialog dialog = new ConfirmRemoveAccountDialog();
    183             Bundle bundle = new Bundle();
    184             bundle.putParcelable(KEY_ACCOUNT, account);
    185             bundle.putParcelable(Intent.EXTRA_USER, userHandle);
    186             dialog.setArguments(bundle);
    187             dialog.setTargetFragment(parent, 0);
    188             dialog.show(parent.getFragmentManager(), DIALOG_TAG);
    189         }
    190 
    191         @Override
    192         public void onCreate(Bundle savedInstanceState) {
    193             super.onCreate(savedInstanceState);
    194             final Bundle arguments = getArguments();
    195             mAccount = arguments.getParcelable(KEY_ACCOUNT);
    196             mUserHandle = arguments.getParcelable(Intent.EXTRA_USER);
    197         }
    198 
    199         @Override
    200         public Dialog onCreateDialog(Bundle savedInstanceState) {
    201             return new CarAlertDialog.Builder(getContext())
    202                     .setTitle(R.string.really_remove_account_title)
    203                     .setBody(R.string.really_remove_account_message)
    204                     .setNegativeButton(android.R.string.cancel, null)
    205                     .setPositiveButton(R.string.remove_account_title, this)
    206                     .create();
    207         }
    208 
    209         @Override
    210         public void onClick(DialogInterface dialog, int which) {
    211             Activity activity = getTargetFragment().getActivity();
    212             AccountManager.get(activity).removeAccountAsUser(
    213                     mAccount, activity, mCallback, null, mUserHandle);
    214             dialog.dismiss();
    215         }
    216     }
    217 
    218     /**
    219      * Dialog to tell user about account removal failure
    220      */
    221     public static class RemoveAccountFailureDialog extends DialogFragment {
    222 
    223         private static final String DIALOG_TAG = "removeAccountFailed";
    224 
    225         public static void show(Fragment parent) {
    226             final RemoveAccountFailureDialog dialog = new RemoveAccountFailureDialog();
    227             dialog.setTargetFragment(parent, 0);
    228             dialog.show(parent.getFragmentManager(), DIALOG_TAG);
    229         }
    230 
    231         @Override
    232         public Dialog onCreateDialog(Bundle savedInstanceState) {
    233             return new CarAlertDialog.Builder(getContext())
    234                     .setTitle(R.string.really_remove_account_title)
    235                     .setBody(R.string.remove_account_failed)
    236                     .setPositiveButton(android.R.string.ok, null)
    237                     .create();
    238         }
    239 
    240     }
    241 }
    242