• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
newInstance( Account account, UserInfo userInfo)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
onCreate(Bundle savedInstanceState)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
onActivityCreated(Bundle savedInstanceState)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
onAccountsUpdate(UserHandle userHandle)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
getItemProvider()111     public ListItemProvider getItemProvider() {
112         return mItemProvider;
113     }
114 
showRemoveButton()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 
setFragmentTitle()121     private void setFragmentTitle() {
122         CharSequence accountLabel = mAccountManagerHelper.getLabelForType(mAccount.type);
123         if (!TextUtils.isEmpty(accountLabel)) {
124             setTitle(accountLabel);
125         }
126     }
127 
getListItems()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 
removeAccount()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 
show( Fragment parent, Account account, UserHandle userHandle)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
onCreate(Bundle savedInstanceState)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
onCreateDialog(Bundle savedInstanceState)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
onClick(DialogInterface dialog, int which)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 
show(Fragment parent)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
onCreateDialog(Bundle savedInstanceState)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