1 /*
2  * Copyright (C) 2014 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 
17 package com.android.tv.settings.accounts;
18 
19 import static com.android.tv.settings.accounts.AccountsUtil.ACCOUNTS_FRAGMENT_DEFAULT;
20 
21 import android.accounts.AccountManager;
22 import android.accounts.AccountManagerCallback;
23 import android.accounts.AccountManagerFuture;
24 import android.accounts.AuthenticatorException;
25 import android.accounts.OperationCanceledException;
26 import android.app.Activity;
27 import android.app.AlertDialog;
28 import android.content.DialogInterface;
29 import android.content.Intent;
30 import android.os.Bundle;
31 import android.provider.Settings;
32 import android.util.Log;
33 
34 import androidx.fragment.app.FragmentActivity;
35 
36 import com.android.tv.settings.R;
37 import com.android.tv.settings.overlay.FlavorUtils;
38 
39 import java.io.IOException;
40 
41 
42 public class AddAccountWithTypeActivity extends FragmentActivity {
43 
44     // Must match com.google.android.gms.common.AccountPicker.
45     public static final String EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY = "allowableAccountTypes";
46 
47     private static final String TAG = "AddAccountWithType";
48 
49     private static final int REQUEST_CHOOSE_ACCOUNT_TYPE = 0;
50     private static final int REQUEST_ADD_ACCOUNT = 1;
51     private static final String CHOOSE_ACCOUNT_TYPE_ACTION =
52             "com.google.android.gms.common.account.CHOOSE_ACCOUNT_TYPE";
53 
54     private final AccountManagerCallback<Bundle> mCallback = new AccountManagerCallback<Bundle>() {
55         @Override
56         public void run(AccountManagerFuture<Bundle> future) {
57             try {
58                 Intent addAccountIntent = future.getResult()
59                         .getParcelable(AccountManager.KEY_INTENT);
60                 if (addAccountIntent == null) {
61                     Log.e(TAG, "Failed to retrieve add account intent from authenticator");
62                     AlertDialog dialog = new AlertDialog.Builder(
63                             AddAccountWithTypeActivity.this)
64                             .setMessage(R.string.add_account_intent_not_available_dialog_message)
65                             .setNegativeButton(android.R.string.ok,
66                                     new DialogInterface.OnClickListener() {
67                                         @Override
68                                         public void onClick(DialogInterface dialog, int which) {
69                                             setResultAndFinish(Activity.RESULT_CANCELED);
70                                         }
71                                     })
72                             .create();
73                     dialog.show();
74                 } else {
75                     startActivityForResult(new Intent(addAccountIntent), REQUEST_ADD_ACCOUNT);
76                 }
77             } catch (IOException|AuthenticatorException|OperationCanceledException e) {
78                 Log.e(TAG, "Failed to get add account intent: ", e);
79                 AlertDialog dialog = new AlertDialog.Builder(AddAccountWithTypeActivity.this)
80                         .setMessage(R.string.add_account_failed_dialog_message)
81                         .setNegativeButton(android.R.string.ok,
82                                 new DialogInterface.OnClickListener() {
83                                     @Override
84                                     public void onClick(DialogInterface dialog, int which) {
85                                         setResultAndFinish(Activity.RESULT_CANCELED);
86                                     }
87                                 })
88                         .create();
89                 dialog.show();
90             }
91         }
92     };
93 
94     @Override
onCreate(Bundle savedInstanceState)95     protected void onCreate(Bundle savedInstanceState) {
96         super.onCreate(savedInstanceState);
97         // Show AccountsFragment if DO is active and this activity was started through
98         // ADD_ACCOUNT_SETTINGS intent. This ensures that organization info. is displayed and
99         // restrictions are enforced, if present.
100         if (FlavorUtils.getFeatureFactory(this).getEnterprisePrivacyFeatureProvider(
101                 this).hasDeviceOwner() && Settings.ACTION_ADD_ACCOUNT.equals(
102                 getIntent().getAction())) {
103             startAccountsActivity();
104             setResultAndFinish(Activity.RESULT_CANCELED);
105         } else {
106             String accountType = getIntent().getStringExtra(AccountManager.KEY_ACCOUNT_TYPE);
107             if (accountType != null) {
108                 startAddAccount(accountType);
109             } else {
110                 String[] allowedTypes = getIntent().getStringArrayExtra(
111                         EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY);
112                 if (allowedTypes == null || allowedTypes.length == 0) {
113                     allowedTypes = getIntent().getStringArrayExtra(Settings.EXTRA_ACCOUNT_TYPES);
114                 }
115                 startAccountTypePicker(allowedTypes);
116             }
117         }
118     }
119 
120     @SuppressWarnings("MissingSuperCall") // TODO: fix me
121     @Override
onActivityResult(int requestCode, int resultCode, Intent data)122     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
123         // User selected an account type, so kick off the add account flow for that.
124         if (requestCode == REQUEST_CHOOSE_ACCOUNT_TYPE && resultCode == Activity.RESULT_OK) {
125             String accountType = data.getExtras().getString(AccountManager.KEY_ACCOUNT_TYPE);
126             startAddAccount(accountType);
127         } else {
128             setResultAndFinish(resultCode);
129         }
130     }
131 
startAccountTypePicker(String[] allowedTypes)132     private void startAccountTypePicker(String[] allowedTypes) {
133         Intent i = new Intent(CHOOSE_ACCOUNT_TYPE_ACTION);
134         i.putExtra(EXTRA_ALLOWABLE_ACCOUNT_TYPES_STRING_ARRAY, allowedTypes);
135         startActivityForResult(i, REQUEST_CHOOSE_ACCOUNT_TYPE);
136     }
137 
startAddAccount(String accountType)138     private void startAddAccount(String accountType) {
139         AccountManager.get(this).addAccount(
140                 accountType,
141                 null, /* authTokenType */
142                 null, /* requiredFeatures */
143                 null, /* accountOptions */
144                 null, mCallback, null);
145     }
146 
setResultAndFinish(int resultCode)147     private void setResultAndFinish(int resultCode) {
148         setResult(resultCode);
149         finish();
150     }
151 
startAccountsActivity()152     private void startAccountsActivity() {
153         Intent intent = new Intent(this, AccountsActivity.class);
154         intent.putExtra(AccountsActivity.EXTRA_FRAGMENT_TYPE, ACCOUNTS_FRAGMENT_DEFAULT);
155         startActivity(intent);
156     }
157 }
158