1 /*
2  * Copyright (C) 2011 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.contacts.editor;
18 
19 import android.accounts.Account;
20 import android.accounts.AccountManager;
21 import android.app.Activity;
22 import android.content.ContentUris;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.net.Uri;
26 import android.os.Bundle;
27 import android.provider.ContactsContract;
28 import android.text.TextUtils;
29 
30 import com.android.contacts.model.account.AccountWithDataSet;
31 import com.android.contacts.preference.ContactsPreferences;
32 
33 import java.util.List;
34 
35 /**
36  * Utility methods for the "account changed" notification in the new contact creation flow.
37  */
38 public class ContactEditorUtils {
39     private static final String TAG = "ContactEditorUtils";
40 
41     private final ContactsPreferences mContactsPrefs;
42 
ContactEditorUtils(Context context)43     private ContactEditorUtils(Context context) {
44         mContactsPrefs = new ContactsPreferences(context);
45     }
46 
create(Context context)47     public static ContactEditorUtils create(Context context) {
48         return new ContactEditorUtils(context.getApplicationContext());
49     }
50 
51     /**
52      * Returns a legacy version of the given contactLookupUri if a legacy Uri was originally
53      * passed to the contact editor.
54      *
55      * @param contactLookupUri The Uri to possibly convert to legacy format.
56      * @param requestLookupUri The lookup Uri originally passed to the contact editor
57      *                         (via Intent data), may be null.
58      */
maybeConvertToLegacyLookupUri(Context context, Uri contactLookupUri, Uri requestLookupUri)59     static Uri maybeConvertToLegacyLookupUri(Context context, Uri contactLookupUri,
60             Uri requestLookupUri) {
61         final String legacyAuthority = "contacts";
62         final String requestAuthority = requestLookupUri == null
63                 ? null : requestLookupUri.getAuthority();
64         if (legacyAuthority.equals(requestAuthority)) {
65             // Build a legacy Uri if that is what was requested by caller
66             final long contactId = ContentUris.parseId(ContactsContract.Contacts.lookupContact(
67                     context.getContentResolver(), contactLookupUri));
68             final Uri legacyContentUri = Uri.parse("content://contacts/people");
69             return ContentUris.withAppendedId(legacyContentUri, contactId);
70         }
71         // Otherwise pass back a lookup-style Uri
72         return contactLookupUri;
73     }
74 
cleanupForTest()75     void cleanupForTest() {
76         mContactsPrefs.clearDefaultAccount();
77     }
78 
removeDefaultAccountForTest()79     void removeDefaultAccountForTest() {
80         mContactsPrefs.clearDefaultAccount();
81     }
82 
83     /**
84      * Saves the default account, which can later be obtained with {@link #getOnlyOrDefaultAccount}.
85      *
86      * This should be called when saving a newly created contact.
87      *
88      * @param defaultAccount the account used to save a newly created contact.
89      */
saveDefaultAccount(AccountWithDataSet defaultAccount)90     public void saveDefaultAccount(AccountWithDataSet defaultAccount) {
91         if (defaultAccount == null) {
92             mContactsPrefs.clearDefaultAccount();
93         } else {
94             mContactsPrefs.setDefaultAccount(defaultAccount);
95         }
96     }
97 
98     /**
99      * @return the first account if there is only a single account or the default account saved
100      * with {@link #saveDefaultAccount}.
101      *
102      * A null return value indicates that there is multiple accounts and a default hasn't been set
103      *
104      * Also note that the returned account may have been removed already.
105      */
getOnlyOrDefaultAccount( List<AccountWithDataSet> currentWritableAccounts)106     public AccountWithDataSet getOnlyOrDefaultAccount(
107             List<AccountWithDataSet> currentWritableAccounts) {
108         if (currentWritableAccounts.size() == 1) {
109             return currentWritableAccounts.get(0);
110         }
111 
112         return mContactsPrefs.getDefaultAccount();
113     }
114 
shouldShowAccountChangedNotification(List<AccountWithDataSet> writableAccounts)115     public boolean shouldShowAccountChangedNotification(List<AccountWithDataSet> writableAccounts) {
116         return mContactsPrefs.shouldShowAccountChangedNotification(writableAccounts);
117     }
118 
119     /**
120      * Sets the only non-device account to be default if it is not already.
121      */
maybeUpdateDefaultAccount(List<AccountWithDataSet> currentWritableAccounts)122     public void maybeUpdateDefaultAccount(List<AccountWithDataSet> currentWritableAccounts) {
123         if (currentWritableAccounts.size() == 1) {
124             final AccountWithDataSet onlyAccount = currentWritableAccounts.get(0);
125             if (!onlyAccount.isNullAccount()
126                     && !onlyAccount.equals(mContactsPrefs.getDefaultAccount())) {
127                 mContactsPrefs.setDefaultAccount(onlyAccount);
128             }
129         }
130     }
131 
132     /**
133      * Parses a result from {@link AccountManager#newChooseAccountIntent(Account, List, String[],
134      *     String, String, String[], Bundle)} and returns the created {@link Account}, or null if
135      * the user has canceled the wizard.
136      *
137      * <p>Pass the {@code resultCode} and {@code data} parameters passed to
138      * {@link Activity#onActivityResult} or {@link android.app.Fragment#onActivityResult}.
139      * </p>
140      *
141      * <p>
142      * Note although the return type is {@link AccountWithDataSet}, return values from this method
143      * will never have {@link AccountWithDataSet#dataSet} set, as there's no way to create an
144      * extension package account from setup wizard.
145      * </p>
146      */
getCreatedAccount(int resultCode, Intent resultData)147     public AccountWithDataSet getCreatedAccount(int resultCode, Intent resultData) {
148         // Javadoc doesn't say anything about resultCode but that the data intent will be non null
149         // on success.
150         if (resultData == null) return null;
151 
152         final String accountType = resultData.getStringExtra(AccountManager.KEY_ACCOUNT_TYPE);
153         final String accountName = resultData.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
154 
155         // Just in case
156         if (TextUtils.isEmpty(accountType) || TextUtils.isEmpty(accountName)) return null;
157 
158         return new AccountWithDataSet(accountName, accountType, null);
159     }
160 }
161