blob: 24946641c011f03bfa07994aa11ef73dc884a590 [file] [log] [blame]
Doris Lingfd06d2f2016-12-29 14:41:15 -08001/*
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 */
16package com.android.settings.accounts;
17
18import android.accounts.Account;
19import android.accounts.AccountManager;
20import android.accounts.AccountManagerCallback;
21import android.accounts.AccountManagerFuture;
22import android.accounts.AuthenticatorException;
23import android.accounts.OperationCanceledException;
24import android.app.Activity;
Doris Lingfd06d2f2016-12-29 14:41:15 -080025import android.app.Dialog;
Doris Lingfd06d2f2016-12-29 14:41:15 -080026import android.content.Context;
27import android.content.DialogInterface;
Tony Makef4c8392017-03-07 13:37:38 +000028import android.content.Intent;
Doris Lingfd06d2f2016-12-29 14:41:15 -080029import android.os.Bundle;
Tony Makef4c8392017-03-07 13:37:38 +000030import android.os.UserHandle;
phweiss7a34e9c2017-06-02 19:38:50 +020031import android.os.UserManager;
Doris Lingfd06d2f2016-12-29 14:41:15 -080032import android.view.View;
33import android.view.View.OnClickListener;
34import android.widget.Button;
35
Fan Zhang23f8d592018-08-28 15:11:40 -070036import androidx.appcompat.app.AlertDialog;
37import androidx.fragment.app.Fragment;
38import androidx.preference.PreferenceScreen;
39
Doris Lingfd06d2f2016-12-29 14:41:15 -080040import com.android.internal.logging.nano.MetricsProto;
41import com.android.settings.R;
42import com.android.settings.applications.LayoutPreference;
Tony Mantler1d583e12017-06-13 13:09:25 -070043import com.android.settings.core.PreferenceControllerMixin;
Doris Lingfd06d2f2016-12-29 14:41:15 -080044import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
yuemingw5f0f6b92018-03-12 16:38:50 +000045import com.android.settingslib.RestrictedLockUtils;
46import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
Philip P. Moltmanne3f72112018-08-28 15:01:43 -070047import com.android.settingslib.RestrictedLockUtilsInternal;
Tony Mantler1d583e12017-06-13 13:09:25 -070048import com.android.settingslib.core.AbstractPreferenceController;
Doris Lingfd06d2f2016-12-29 14:41:15 -080049
50import java.io.IOException;
51
Tony Mantler1d583e12017-06-13 13:09:25 -070052public class RemoveAccountPreferenceController extends AbstractPreferenceController
53 implements PreferenceControllerMixin, OnClickListener {
Doris Lingfd06d2f2016-12-29 14:41:15 -080054
55 private static final String KEY_REMOVE_ACCOUNT = "remove_account";
56
57 private Account mAccount;
58 private Fragment mParentFragment;
Tony Makef4c8392017-03-07 13:37:38 +000059 private UserHandle mUserHandle;
Doris Lingfd06d2f2016-12-29 14:41:15 -080060
61 public RemoveAccountPreferenceController(Context context, Fragment parent) {
62 super(context);
63 mParentFragment = parent;
64 }
65
66 @Override
67 public void displayPreference(PreferenceScreen screen) {
68 super.displayPreference(screen);
69 final LayoutPreference removeAccountPreference =
Fan Zhangaab36de2018-03-30 16:58:28 -070070 (LayoutPreference) screen.findPreference(KEY_REMOVE_ACCOUNT);
Doris Lingfd06d2f2016-12-29 14:41:15 -080071 Button removeAccountButton = (Button) removeAccountPreference.findViewById(R.id.button);
72 removeAccountButton.setOnClickListener(this);
73 }
74
75 @Override
76 public boolean isAvailable() {
77 return true;
78 }
79
80 @Override
81 public String getPreferenceKey() {
82 return KEY_REMOVE_ACCOUNT;
83 }
84
85 @Override
86 public void onClick(View v) {
yuemingw5f0f6b92018-03-12 16:38:50 +000087 if (mUserHandle != null) {
Philip P. Moltmanne3f72112018-08-28 15:01:43 -070088 final EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
89 mContext, UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle.getIdentifier());
yuemingw5f0f6b92018-03-12 16:38:50 +000090 if (admin != null) {
91 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, admin);
92 return;
93 }
phweiss7a34e9c2017-06-02 19:38:50 +020094 }
yuemingw5f0f6b92018-03-12 16:38:50 +000095
Tony Makef4c8392017-03-07 13:37:38 +000096 ConfirmRemoveAccountDialog.show(mParentFragment, mAccount, mUserHandle);
Doris Lingfd06d2f2016-12-29 14:41:15 -080097 }
98
Tony Makef4c8392017-03-07 13:37:38 +000099 public void init(Account account, UserHandle userHandle) {
Doris Lingfd06d2f2016-12-29 14:41:15 -0800100 mAccount = account;
Tony Makef4c8392017-03-07 13:37:38 +0000101 mUserHandle = userHandle;
Doris Lingfd06d2f2016-12-29 14:41:15 -0800102 }
103
104 /**
105 * Dialog to confirm with user about account removal
106 */
107 public static class ConfirmRemoveAccountDialog extends InstrumentedDialogFragment implements
108 DialogInterface.OnClickListener {
Tony Makef4c8392017-03-07 13:37:38 +0000109 private static final String KEY_ACCOUNT = "account";
Doris Lingfd06d2f2016-12-29 14:41:15 -0800110 private static final String REMOVE_ACCOUNT_DIALOG = "confirmRemoveAccount";
111 private Account mAccount;
Tony Makef4c8392017-03-07 13:37:38 +0000112 private UserHandle mUserHandle;
Doris Lingfd06d2f2016-12-29 14:41:15 -0800113
Tony Makef4c8392017-03-07 13:37:38 +0000114 public static ConfirmRemoveAccountDialog show(
115 Fragment parent, Account account, UserHandle userHandle) {
Doris Lingfd06d2f2016-12-29 14:41:15 -0800116 if (!parent.isAdded()) {
117 return null;
118 }
119 final ConfirmRemoveAccountDialog dialog = new ConfirmRemoveAccountDialog();
Tony Makef4c8392017-03-07 13:37:38 +0000120 Bundle bundle = new Bundle();
121 bundle.putParcelable(KEY_ACCOUNT, account);
122 bundle.putParcelable(Intent.EXTRA_USER, userHandle);
123 dialog.setArguments(bundle);
Doris Lingfd06d2f2016-12-29 14:41:15 -0800124 dialog.setTargetFragment(parent, 0);
125 dialog.show(parent.getFragmentManager(), REMOVE_ACCOUNT_DIALOG);
126 return dialog;
127 }
128
129 @Override
Tony Makef4c8392017-03-07 13:37:38 +0000130 public void onCreate(Bundle savedInstanceState) {
131 super.onCreate(savedInstanceState);
132 final Bundle arguments = getArguments();
133 mAccount = arguments.getParcelable(KEY_ACCOUNT);
134 mUserHandle = arguments.getParcelable(Intent.EXTRA_USER);
135 }
136
137 @Override
Doris Lingfd06d2f2016-12-29 14:41:15 -0800138 public Dialog onCreateDialog(Bundle savedInstanceState) {
139 final Context context = getActivity();
Doris Lingfd06d2f2016-12-29 14:41:15 -0800140 return new AlertDialog.Builder(context)
Fan Zhangaab36de2018-03-30 16:58:28 -0700141 .setTitle(R.string.really_remove_account_title)
142 .setMessage(R.string.really_remove_account_message)
143 .setNegativeButton(android.R.string.cancel, null)
144 .setPositiveButton(R.string.remove_account_label, this)
145 .create();
Doris Lingfd06d2f2016-12-29 14:41:15 -0800146 }
147
148 @Override
Doris Lingfd06d2f2016-12-29 14:41:15 -0800149 public int getMetricsCategory() {
150 return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_REMOVE;
151 }
152
153 @Override
154 public void onClick(DialogInterface dialog, int which) {
155 Activity activity = getTargetFragment().getActivity();
156 AccountManager.get(activity).removeAccountAsUser(mAccount, activity,
157 new AccountManagerCallback<Bundle>() {
158 @Override
159 public void run(AccountManagerFuture<Bundle> future) {
160 // If already out of this screen, don't proceed.
161 if (!getTargetFragment().isResumed()) {
162 return;
163 }
164 boolean failed = true;
165 try {
166 if (future.getResult()
Fan Zhangaab36de2018-03-30 16:58:28 -0700167 .getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
Doris Lingfd06d2f2016-12-29 14:41:15 -0800168 failed = false;
169 }
170 } catch (OperationCanceledException e) {
171 // handled below
172 } catch (IOException e) {
173 // handled below
174 } catch (AuthenticatorException e) {
175 // handled below
176 }
177 final Activity activity = getTargetFragment().getActivity();
178 if (failed && activity != null && !activity.isFinishing()) {
179 RemoveAccountFailureDialog.show(getTargetFragment());
180 } else {
181 activity.finish();
182 }
183 }
Tony Makef4c8392017-03-07 13:37:38 +0000184 }, null, mUserHandle);
Doris Lingfd06d2f2016-12-29 14:41:15 -0800185 }
186 }
187
188 /**
189 * Dialog to tell user about account removal failure
190 */
191 public static class RemoveAccountFailureDialog extends InstrumentedDialogFragment {
192
193 private static final String FAILED_REMOVAL_DIALOG = "removeAccountFailed";
194
195 public static void show(Fragment parent) {
196 if (!parent.isAdded()) {
197 return;
198 }
199 final RemoveAccountFailureDialog dialog = new RemoveAccountFailureDialog();
200 dialog.setTargetFragment(parent, 0);
201 dialog.show(parent.getFragmentManager(), FAILED_REMOVAL_DIALOG);
202 }
203
204 @Override
205 public Dialog onCreateDialog(Bundle savedInstanceState) {
206 final Context context = getActivity();
207
208 return new AlertDialog.Builder(context)
Fan Zhangaab36de2018-03-30 16:58:28 -0700209 .setTitle(R.string.really_remove_account_title)
210 .setMessage(R.string.remove_account_failed)
211 .setPositiveButton(android.R.string.ok, null)
212 .create();
Doris Lingfd06d2f2016-12-29 14:41:15 -0800213 }
214
215 @Override
216 public int getMetricsCategory() {
217 return MetricsProto.MetricsEvent.DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL;
218 }
219
220 }
221}