blob: d4d93dda217fba071a21f1aa0d2e936a9ae501a9 [file] [log] [blame]
Amith Yamasani43c69782010-12-01 09:04:36 -08001/*
2 * Copyright (C) 2008 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
17package com.android.settings.accounts;
18
Maurice Lam2eb170c2017-04-28 16:18:47 -070019import static android.content.Intent.EXTRA_USER;
20
Amith Yamasani43c69782010-12-01 09:04:36 -080021import android.accounts.AccountManager;
22import android.accounts.AccountManagerCallback;
23import android.accounts.AccountManagerFuture;
24import android.accounts.AuthenticatorException;
25import android.accounts.OperationCanceledException;
26import android.app.Activity;
Costin Manolacheb22a2422011-07-18 16:30:36 -070027import android.app.PendingIntent;
Carlos Valdiviaf5d3e742014-09-07 17:45:58 -070028import android.content.ComponentName;
Maggie Benthall0c5a4012013-03-14 17:41:27 -040029import android.content.Context;
Amith Yamasani43c69782010-12-01 09:04:36 -080030import android.content.Intent;
31import android.os.Bundle;
Alexandra Gherghina7d748c02014-06-27 12:33:42 +010032import android.os.UserHandle;
Maggie Benthall0c5a4012013-03-14 17:41:27 -040033import android.os.UserManager;
Amith Yamasani43c69782010-12-01 09:04:36 -080034import android.util.Log;
Amith Yamasanic39dcc12013-04-13 18:30:59 -070035import android.widget.Toast;
Amith Yamasani43c69782010-12-01 09:04:36 -080036
Amith Yamasanic39dcc12013-04-13 18:30:59 -070037import com.android.settings.R;
Jason Monkb7e43802016-06-06 16:01:58 -040038import com.android.settings.Settings;
Amith Yamasanieb71f262012-09-26 17:57:15 -070039import com.android.settings.Utils;
Maurice Lam2eb170c2017-04-28 16:18:47 -070040import com.android.settings.password.ChooseLockSettingsHelper;
Amith Yamasanieb71f262012-09-26 17:57:15 -070041
Amith Yamasani43c69782010-12-01 09:04:36 -080042import java.io.IOException;
Amith Yamasani43c69782010-12-01 09:04:36 -080043/**
Alexandra Gherghina7d748c02014-06-27 12:33:42 +010044 * Entry point Activity for account setup. Works as follows
Amith Yamasani21c29042012-10-02 15:16:21 -070045 *
Amith Yamasani43c69782010-12-01 09:04:36 -080046 * 1) When the other Activities launch this Activity, it launches {@link ChooseAccountActivity}
47 * without showing anything.
48 * 2) After receiving an account type from ChooseAccountActivity, this Activity launches the
49 * account setup specified by AccountManager.
50 * 3) After the account setup, this Activity finishes without showing anything.
51 *
52 * Note:
53 * Previously this Activity did what {@link ChooseAccountActivity} does right now, but we
54 * currently delegate the work to the other Activity. When we let this Activity do that work, users
55 * would see the list of account types when leaving this Activity, since the UI is already ready
56 * when returning from each account setup, which doesn't look good.
Alexandra Gherghina7d748c02014-06-27 12:33:42 +010057 *
58 * An extra {@link UserHandle} can be specified in the intent as {@link EXTRA_USER}, if the user for
59 * which the action needs to be performed is different to the one the Settings App will run in.
Amith Yamasani43c69782010-12-01 09:04:36 -080060 */
61public class AddAccountSettings extends Activity {
Costin Manolacheb22a2422011-07-18 16:30:36 -070062 /**
Russell Brenner84d04c22012-10-01 17:30:59 -070063 *
Costin Manolacheb22a2422011-07-18 16:30:36 -070064 */
65 private static final String KEY_ADD_CALLED = "AddAccountCalled";
66
67 /**
68 * Extra parameter to identify the caller. Applications may display a
69 * different UI if the calls is made from Settings or from a specific
70 * application.
71 */
72 private static final String KEY_CALLER_IDENTITY = "pendingIntent";
Carlos Valdiviaf5d3e742014-09-07 17:45:58 -070073 private static final String SHOULD_NOT_RESOLVE = "SHOULDN'T RESOLVE!";
Costin Manolacheb22a2422011-07-18 16:30:36 -070074
Doris Lingf074f0f2017-02-24 15:20:05 -080075 private static final String TAG = "AddAccountSettings";
Amith Yamasani43c69782010-12-01 09:04:36 -080076
77 /* package */ static final String EXTRA_SELECTED_ACCOUNT = "selected_account";
78
Russell Brenner84d04c22012-10-01 17:30:59 -070079 // show additional info regarding the use of a device with multiple users
80 static final String EXTRA_HAS_MULTIPLE_USERS = "hasMultipleUsers";
81
Amith Yamasani43c69782010-12-01 09:04:36 -080082 private static final int CHOOSE_ACCOUNT_REQUEST = 1;
Amith Yamasanicbabf192012-10-10 16:42:20 -070083 private static final int ADD_ACCOUNT_REQUEST = 2;
Nicolas Prevota599c8f2016-04-06 11:19:08 +010084 private static final int UNLOCK_WORK_PROFILE_REQUEST = 3;
Amith Yamasani43c69782010-12-01 09:04:36 -080085
Costin Manolacheb22a2422011-07-18 16:30:36 -070086 private PendingIntent mPendingIntent;
87
Maggie Benthall0c5a4012013-03-14 17:41:27 -040088 private final AccountManagerCallback<Bundle> mCallback = new AccountManagerCallback<Bundle>() {
89 @Override
Amith Yamasani43c69782010-12-01 09:04:36 -080090 public void run(AccountManagerFuture<Bundle> future) {
Amith Yamasanicbabf192012-10-10 16:42:20 -070091 boolean done = true;
Amith Yamasani43c69782010-12-01 09:04:36 -080092 try {
93 Bundle bundle = future.getResult();
Amith Yamasanicbabf192012-10-10 16:42:20 -070094 //bundle.keySet();
95 Intent intent = (Intent) bundle.get(AccountManager.KEY_INTENT);
96 if (intent != null) {
97 done = false;
98 Bundle addAccountOptions = new Bundle();
99 addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
100 addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS,
101 Utils.hasMultipleUsers(AddAccountSettings.this));
Alexandra Gherghina7d748c02014-06-27 12:33:42 +0100102 addAccountOptions.putParcelable(EXTRA_USER, mUserHandle);
Jason Chiu3e4d0022019-05-16 17:44:13 +0800103 intent.putExtras(addAccountOptions)
104 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
105 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
Alexandra Gherghina9ce0da92014-07-07 15:10:15 +0100106 startActivityForResultAsUser(intent, ADD_ACCOUNT_REQUEST, mUserHandle);
Amith Yamasanicbabf192012-10-10 16:42:20 -0700107 } else {
108 setResult(RESULT_OK);
109 if (mPendingIntent != null) {
110 mPendingIntent.cancel();
111 mPendingIntent = null;
112 }
Costin Manolacheb22a2422011-07-18 16:30:36 -0700113 }
114
Amith Yamasani43c69782010-12-01 09:04:36 -0800115 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "account added: " + bundle);
116 } catch (OperationCanceledException e) {
117 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount was canceled");
118 } catch (IOException e) {
119 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount failed: " + e);
120 } catch (AuthenticatorException e) {
121 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "addAccount failed: " + e);
122 } finally {
Amith Yamasanicbabf192012-10-10 16:42:20 -0700123 if (done) {
124 finish();
125 }
Amith Yamasani43c69782010-12-01 09:04:36 -0800126 }
127 }
128 };
129
Costin Manolacheb22a2422011-07-18 16:30:36 -0700130 private boolean mAddAccountCalled = false;
Alexandra Gherghina7d748c02014-06-27 12:33:42 +0100131 private UserHandle mUserHandle;
Costin Manolacheb22a2422011-07-18 16:30:36 -0700132
Amith Yamasani43c69782010-12-01 09:04:36 -0800133 @Override
134 public void onCreate(Bundle savedInstanceState) {
135 super.onCreate(savedInstanceState);
Amith Yamasani7bb8f722011-06-02 18:05:40 -0700136
Costin Manolacheb22a2422011-07-18 16:30:36 -0700137 if (savedInstanceState != null) {
138 mAddAccountCalled = savedInstanceState.getBoolean(KEY_ADD_CALLED);
139 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "restored");
140 }
141
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400142 final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
Alexandra Gherghina7d748c02014-06-27 12:33:42 +0100143 mUserHandle = Utils.getSecureTargetUser(getActivityToken(), um, null /* arguments */,
144 getIntent().getExtras());
145 if (um.hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, mUserHandle)) {
Amith Yamasanic39dcc12013-04-13 18:30:59 -0700146 // We aren't allowed to add an account.
147 Toast.makeText(this, R.string.user_cannot_add_accounts_message, Toast.LENGTH_LONG)
148 .show();
149 finish();
150 return;
151 }
152 if (mAddAccountCalled) {
Amith Yamasani21c29042012-10-02 15:16:21 -0700153 // We already called add account - maybe the callback was lost.
154 finish();
155 return;
Costin Manolacheb22a2422011-07-18 16:30:36 -0700156 }
Nicolas Prevotbd4c570b2016-04-21 12:26:48 +0100157 if (Utils.startQuietModeDialogIfNecessary(this, um, mUserHandle.getIdentifier())) {
158 finish();
159 return;
160 }
161 if (um.isUserUnlocked(mUserHandle)) {
Nicolas Prevota599c8f2016-04-06 11:19:08 +0100162 requestChooseAccount();
Nicolas Prevotbd4c570b2016-04-21 12:26:48 +0100163 } else {
164 // If the user is locked by fbe: we couldn't start the authenticator. So we must ask the
165 // user to unlock it first.
166 ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(this);
167 if (!helper.launchConfirmationActivity(UNLOCK_WORK_PROFILE_REQUEST,
168 getString(R.string.unlock_set_unlock_launch_picker_title),
169 false,
170 mUserHandle.getIdentifier())) {
171 requestChooseAccount();
172 }
Amith Yamasani43c69782010-12-01 09:04:36 -0800173 }
Amith Yamasani43c69782010-12-01 09:04:36 -0800174 }
175
176 @Override
177 public void onActivityResult(int requestCode, int resultCode, Intent data) {
178 switch (requestCode) {
Nicolas Prevota599c8f2016-04-06 11:19:08 +0100179 case UNLOCK_WORK_PROFILE_REQUEST:
180 if (resultCode == Activity.RESULT_OK) {
181 requestChooseAccount();
182 } else {
183 finish();
184 }
185 break;
Amith Yamasani43c69782010-12-01 09:04:36 -0800186 case CHOOSE_ACCOUNT_REQUEST:
187 if (resultCode == RESULT_CANCELED) {
Sudheer Shankaf755baf2016-01-29 22:12:30 +0000188 if (data != null) {
189 startActivityAsUser(data, mUserHandle);
190 }
Amith Yamasani43c69782010-12-01 09:04:36 -0800191 setResult(resultCode);
192 finish();
193 return;
194 }
195 // Go to account setup screen. finish() is called inside mCallback.
196 addAccount(data.getStringExtra(EXTRA_SELECTED_ACCOUNT));
197 break;
Amith Yamasanicbabf192012-10-10 16:42:20 -0700198 case ADD_ACCOUNT_REQUEST:
199 setResult(resultCode);
200 if (mPendingIntent != null) {
201 mPendingIntent.cancel();
202 mPendingIntent = null;
203 }
204 finish();
205 break;
Amith Yamasani43c69782010-12-01 09:04:36 -0800206 }
207 }
208
Maggie Benthall0c5a4012013-03-14 17:41:27 -0400209 @Override
Costin Manolacheb22a2422011-07-18 16:30:36 -0700210 protected void onSaveInstanceState(Bundle outState) {
211 super.onSaveInstanceState(outState);
212 outState.putBoolean(KEY_ADD_CALLED, mAddAccountCalled);
213 if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "saved");
214 }
215
Nicolas Prevota599c8f2016-04-06 11:19:08 +0100216 private void requestChooseAccount() {
217 final String[] authorities =
218 getIntent().getStringArrayExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
219 final String[] accountTypes =
220 getIntent().getStringArrayExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
Jason Monkb7e43802016-06-06 16:01:58 -0400221 final Intent intent = new Intent(this, Settings.ChooseAccountActivity.class);
Nicolas Prevota599c8f2016-04-06 11:19:08 +0100222 if (authorities != null) {
223 intent.putExtra(AccountPreferenceBase.AUTHORITIES_FILTER_KEY, authorities);
224 }
225 if (accountTypes != null) {
226 intent.putExtra(AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY, accountTypes);
227 }
228 intent.putExtra(EXTRA_USER, mUserHandle);
229 startActivityForResult(intent, CHOOSE_ACCOUNT_REQUEST);
230 }
231
Amith Yamasani43c69782010-12-01 09:04:36 -0800232 private void addAccount(String accountType) {
Costin Manolacheb22a2422011-07-18 16:30:36 -0700233 Bundle addAccountOptions = new Bundle();
Carlos Valdiviaf5d3e742014-09-07 17:45:58 -0700234 /*
235 * The identityIntent is for the purposes of establishing the identity
236 * of the caller and isn't intended for launching activities, services
237 * or broadcasts.
238 *
239 * Unfortunately for legacy reasons we still need to support this. But
240 * we can cripple the intent so that 3rd party authenticators can't
241 * fill in addressing information and launch arbitrary actions.
242 */
243 Intent identityIntent = new Intent();
244 identityIntent.setComponent(new ComponentName(SHOULD_NOT_RESOLVE, SHOULD_NOT_RESOLVE));
245 identityIntent.setAction(SHOULD_NOT_RESOLVE);
246 identityIntent.addCategory(SHOULD_NOT_RESOLVE);
247
248 mPendingIntent = PendingIntent.getBroadcast(this, 0, identityIntent, 0);
Costin Manolacheb22a2422011-07-18 16:30:36 -0700249 addAccountOptions.putParcelable(KEY_CALLER_IDENTITY, mPendingIntent);
Russell Brenner84d04c22012-10-01 17:30:59 -0700250 addAccountOptions.putBoolean(EXTRA_HAS_MULTIPLE_USERS, Utils.hasMultipleUsers(this));
Alexandra Gherghina9ce0da92014-07-07 15:10:15 +0100251 AccountManager.get(this).addAccountAsUser(
Amith Yamasani43c69782010-12-01 09:04:36 -0800252 accountType,
253 null, /* authTokenType */
254 null, /* requiredFeatures */
Costin Manolacheb22a2422011-07-18 16:30:36 -0700255 addAccountOptions,
Amith Yamasanicbabf192012-10-10 16:42:20 -0700256 null,
Amith Yamasani43c69782010-12-01 09:04:36 -0800257 mCallback,
Alexandra Gherghina9ce0da92014-07-07 15:10:15 +0100258 null /* handler */,
259 mUserHandle);
Costin Manolacheb22a2422011-07-18 16:30:36 -0700260 mAddAccountCalled = true;
Amith Yamasani43c69782010-12-01 09:04:36 -0800261 }
Amith Yamasani43c69782010-12-01 09:04:36 -0800262}