• 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.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.AlertDialog;
26 import android.app.Dialog;
27 import android.app.Fragment;
28 import android.content.Context;
29 import android.content.DialogInterface;
30 import android.content.Intent;
31 import android.os.Bundle;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.support.v7.preference.PreferenceScreen;
35 import android.view.View;
36 import android.view.View.OnClickListener;
37 import android.widget.Button;
38 
39 import com.android.internal.logging.nano.MetricsProto;
40 import com.android.settings.R;
41 import com.android.settings.applications.LayoutPreference;
42 import com.android.settings.core.PreferenceControllerMixin;
43 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
44 import com.android.settingslib.RestrictedLockUtils;
45 import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
46 import com.android.settingslib.core.AbstractPreferenceController;
47 
48 import java.io.IOException;
49 
50 public class RemoveAccountPreferenceController extends AbstractPreferenceController
51         implements PreferenceControllerMixin, OnClickListener {
52 
53     private static final String KEY_REMOVE_ACCOUNT = "remove_account";
54 
55     private Account mAccount;
56     private Fragment mParentFragment;
57     private UserHandle mUserHandle;
58 
RemoveAccountPreferenceController(Context context, Fragment parent)59     public RemoveAccountPreferenceController(Context context, Fragment parent) {
60         super(context);
61         mParentFragment = parent;
62     }
63 
64     @Override
displayPreference(PreferenceScreen screen)65     public void displayPreference(PreferenceScreen screen) {
66         super.displayPreference(screen);
67         final LayoutPreference removeAccountPreference =
68                 (LayoutPreference) screen.findPreference(KEY_REMOVE_ACCOUNT);
69         Button removeAccountButton = (Button) removeAccountPreference.findViewById(R.id.button);
70         removeAccountButton.setOnClickListener(this);
71     }
72 
73     @Override
isAvailable()74     public boolean isAvailable() {
75         return true;
76     }
77 
78     @Override
getPreferenceKey()79     public String getPreferenceKey() {
80         return KEY_REMOVE_ACCOUNT;
81     }
82 
83     @Override
onClick(View v)84     public void onClick(View v) {
85         if (mUserHandle != null) {
86             final EnforcedAdmin admin = RestrictedLockUtils.checkIfRestrictionEnforced(mContext,
87                     UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier());
88             if (admin != null) {
89                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin);
90                 return;
91             }
92         }
93 
94         ConfirmRemoveAccountDialog.show(mParentFragment, mAccount, mUserHandle);
95     }
96 
init(Account account, UserHandle userHandle)97     public void init(Account account, UserHandle userHandle) {
98         mAccount = account;
99         mUserHandle = userHandle;
100     }
101 
102     /**
103      * Dialog to confirm with user about account removal
104      */
105     public static class ConfirmRemoveAccountDialog extends InstrumentedDialogFragment implements
106             DialogInterface.OnClickListener {
107         private static final String KEY_ACCOUNT = "account";
108         private static final String REMOVE_ACCOUNT_DIALOG = "confirmRemoveAccount";
109         private Account mAccount;
110         private UserHandle mUserHandle;
111 
show( Fragment parent, Account account, UserHandle userHandle)112         public static ConfirmRemoveAccountDialog show(
113                 Fragment parent, Account account, UserHandle userHandle) {
114             if (!parent.isAdded()) {
115                 return null;
116             }
117             final ConfirmRemoveAccountDialog dialog = new ConfirmRemoveAccountDialog();
118             Bundle bundle = new Bundle();
119             bundle.putParcelable(KEY_ACCOUNT, account);
120             bundle.putParcelable(Intent.EXTRA_USER, userHandle);
121             dialog.setArguments(bundle);
122             dialog.setTargetFragment(parent, 0);
123             dialog.show(parent.getFragmentManager(), REMOVE_ACCOUNT_DIALOG);
124             return dialog;
125         }
126 
127         @Override
onCreate(Bundle savedInstanceState)128         public void onCreate(Bundle savedInstanceState) {
129             super.onCreate(savedInstanceState);
130             final Bundle arguments = getArguments();
131             mAccount = arguments.getParcelable(KEY_ACCOUNT);
132             mUserHandle = arguments.getParcelable(Intent.EXTRA_USER);
133         }
134 
135         @Override
onCreateDialog(Bundle savedInstanceState)136         public Dialog onCreateDialog(Bundle savedInstanceState) {
137             final Context context = getActivity();
138             return new AlertDialog.Builder(context)
139                     .setTitle(R.string.really_remove_account_title)
140                     .setMessage(R.string.really_remove_account_message)
141                     .setNegativeButton(android.R.string.cancel, null)
142                     .setPositiveButton(R.string.remove_account_label, this)
143                     .create();
144         }
145 
146         @Override
getMetricsCategory()147         public int getMetricsCategory() {
148             return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_REMOVE;
149         }
150 
151         @Override
onClick(DialogInterface dialog, int which)152         public void onClick(DialogInterface dialog, int which) {
153             Activity activity = getTargetFragment().getActivity();
154             AccountManager.get(activity).removeAccountAsUser(mAccount, activity,
155                     new AccountManagerCallback<Bundle>() {
156                         @Override
157                         public void run(AccountManagerFuture<Bundle> future) {
158                             // If already out of this screen, don't proceed.
159                             if (!getTargetFragment().isResumed()) {
160                                 return;
161                             }
162                             boolean failed = true;
163                             try {
164                                 if (future.getResult()
165                                         .getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
166                                     failed = false;
167                                 }
168                             } catch (OperationCanceledException e) {
169                                 // handled below
170                             } catch (IOException e) {
171                                 // handled below
172                             } catch (AuthenticatorException e) {
173                                 // handled below
174                             }
175                             final Activity activity = getTargetFragment().getActivity();
176                             if (failed && activity != null && !activity.isFinishing()) {
177                                 RemoveAccountFailureDialog.show(getTargetFragment());
178                             } else {
179                                 activity.finish();
180                             }
181                         }
182                     }, null, mUserHandle);
183         }
184     }
185 
186     /**
187      * Dialog to tell user about account removal failure
188      */
189     public static class RemoveAccountFailureDialog extends InstrumentedDialogFragment {
190 
191         private static final String FAILED_REMOVAL_DIALOG = "removeAccountFailed";
192 
show(Fragment parent)193         public static void show(Fragment parent) {
194             if (!parent.isAdded()) {
195                 return;
196             }
197             final RemoveAccountFailureDialog dialog = new RemoveAccountFailureDialog();
198             dialog.setTargetFragment(parent, 0);
199             dialog.show(parent.getFragmentManager(), FAILED_REMOVAL_DIALOG);
200         }
201 
202         @Override
onCreateDialog(Bundle savedInstanceState)203         public Dialog onCreateDialog(Bundle savedInstanceState) {
204             final Context context = getActivity();
205 
206             return new AlertDialog.Builder(context)
207                     .setTitle(R.string.really_remove_account_title)
208                     .setMessage(R.string.remove_account_failed)
209                     .setPositiveButton(android.R.string.ok, null)
210                     .create();
211         }
212 
213         @Override
getMetricsCategory()214         public int getMetricsCategory() {
215             return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL;
216         }
217 
218     }
219 }
220