AccountManagerService.java revision 751fdc09bb7ab0ce6feac7b7a823e38ed858feb0
1603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/* 2603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Copyright (C) 2009 The Android Open Source Project 3603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 4603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Licensed under the Apache License, Version 2.0 (the "License"); 5603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * you may not use this file except in compliance with the License. 6603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * You may obtain a copy of the License at 7603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 8603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * http://www.apache.org/licenses/LICENSE-2.0 9603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * 10603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Unless required by applicable law or agreed to in writing, software 11603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * distributed under the License is distributed on an "AS IS" BASIS, 12603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * See the License for the specific language governing permissions and 14603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * limitations under the License. 15603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */ 16603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 17603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanapackage android.accounts; 18603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 19885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.Manifest; 20885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.Notification; 21885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.NotificationManager; 22885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.PendingIntent; 23a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.BroadcastReceiver; 24885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.ComponentName; 25a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.ContentValues; 26a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Context; 27a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Intent; 28a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.IntentFilter; 29b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintanaimport android.content.ServiceConnection; 30885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.ApplicationInfo; 31885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.PackageInfo; 32d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.PackageManager; 33d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.RegisteredServicesCache; 343ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanaimport android.content.pm.RegisteredServicesCacheListener; 35603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.Cursor; 36603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.DatabaseUtils; 37a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteDatabase; 38a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteOpenHelper; 39885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.os.Binder; 40a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Bundle; 41a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport android.os.Environment; 42a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Handler; 43a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.HandlerThread; 44a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.IBinder; 45a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Looper; 46a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Message; 47a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.RemoteException; 48885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.os.ServiceManager; 49a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.SystemClock; 50d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.os.SystemProperties; 51603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.telephony.TelephonyManager; 52a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.text.TextUtils; 53a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.util.Log; 54d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.util.Pair; 55603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 56a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport java.io.File; 57a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.FileDescriptor; 58a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.PrintWriter; 59a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.ArrayList; 60a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.Collection; 61a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.LinkedHashMap; 62d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.HashMap; 63d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicInteger; 64d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicReference; 65603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 6626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintanaimport com.android.internal.R; 67885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport com.android.internal.telephony.ITelephony; 68885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport com.android.internal.telephony.TelephonyIntents; 69603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 70603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/** 71603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * A system service that provides account, password, and authtoken management for all 72603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * accounts on the device. Some of these calls are implemented with the help of the corresponding 73603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * {@link IAccountAuthenticator} services. This service is not accessed by users directly, 74603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * instead one uses an instance of {@link AccountManager}, which can be accessed as follows: 75603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * AccountManager accountManager = 76603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * (AccountManager)context.getSystemService(Context.ACCOUNT_SERVICE) 773326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana * @hide 78603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */ 793ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanapublic class AccountManagerService 803ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana extends IAccountManager.Stub 815ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana implements RegisteredServicesCacheListener<AuthenticatorDescription> { 823348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache private static final String GOOGLE_ACCOUNT_TYPE = "com.google"; 8350c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller 8450c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller private static final String NO_BROADCAST_FLAG = "nobroadcast"; 8550c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller 86603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String TAG = "AccountManagerService"; 87603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 88603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final int TIMEOUT_DELAY_MS = 1000 * 60; 89603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String DATABASE_NAME = "accounts.db"; 903348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache private static final int DATABASE_VERSION = 4; 91603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 92603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final Context mContext; 93603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 94603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private HandlerThread mMessageThread; 95603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final MessageHandler mMessageHandler; 96603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 97603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana // Messages that can be sent on mHandler 98603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final int MESSAGE_TIMED_OUT = 3; 99603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 100603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final AccountAuthenticatorCache mAuthenticatorCache; 101603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final DatabaseHelper mOpenHelper; 102603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final SimWatcher mSimWatcher; 103603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 104603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String TABLE_ACCOUNTS = "accounts"; 105603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String ACCOUNTS_ID = "_id"; 106603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String ACCOUNTS_NAME = "name"; 107603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String ACCOUNTS_TYPE = "type"; 1081cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks private static final String ACCOUNTS_TYPE_COUNT = "count(type)"; 109603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String ACCOUNTS_PASSWORD = "password"; 110603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 111603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String TABLE_AUTHTOKENS = "authtokens"; 112603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String AUTHTOKENS_ID = "_id"; 113603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String AUTHTOKENS_ACCOUNTS_ID = "accounts_id"; 114603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String AUTHTOKENS_TYPE = "type"; 115603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String AUTHTOKENS_AUTHTOKEN = "authtoken"; 116603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 117d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static final String TABLE_GRANTS = "grants"; 118d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static final String GRANTS_ACCOUNTS_ID = "accounts_id"; 119d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static final String GRANTS_AUTH_TOKEN_TYPE = "auth_token_type"; 120d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static final String GRANTS_GRANTEE_UID = "uid"; 121d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 122603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String TABLE_EXTRAS = "extras"; 123603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String EXTRAS_ID = "_id"; 124603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String EXTRAS_ACCOUNTS_ID = "accounts_id"; 125603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String EXTRAS_KEY = "key"; 126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String EXTRAS_VALUE = "value"; 127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 128603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String TABLE_META = "meta"; 129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String META_KEY = "key"; 130603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String META_VALUE = "value"; 131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private static final String[] ACCOUNT_NAME_TYPE_PROJECTION = 133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana new String[]{ACCOUNTS_ID, ACCOUNTS_NAME, ACCOUNTS_TYPE}; 1341cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION = 1351cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT}; 1367be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana private static final Intent ACCOUNTS_CHANGED_INTENT; 137a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 138d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static final String COUNT_OF_MATCHING_GRANTS = "" 139d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS 140d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " WHERE " + GRANTS_ACCOUNTS_ID + "=" + ACCOUNTS_ID 141d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " AND " + GRANTS_GRANTEE_UID + "=?" 142d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " AND " + GRANTS_AUTH_TOKEN_TYPE + "=?" 143d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " AND " + ACCOUNTS_NAME + "=?" 144d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " AND " + ACCOUNTS_TYPE + "=?"; 145d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 146a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>(); 147d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private final AtomicInteger mNotificationIds = new AtomicInteger(1); 148d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 149d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private final HashMap<Pair<Pair<Account, String>, Integer>, Integer> 150d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mCredentialsPermissionNotificationIds = 151d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new HashMap<Pair<Pair<Account, String>, Integer>, Integer>(); 152d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private final HashMap<Account, Integer> mSigninRequiredNotificationIds = 153d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new HashMap<Account, Integer>(); 154d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static AtomicReference<AccountManagerService> sThis = 155d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new AtomicReference<AccountManagerService>(); 156d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 157d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private static final boolean isDebuggableMonkeyBuild = 15842c98ada113ae5b7c72ecb6d0de721ec1d0d3534Ying Wang SystemProperties.getBoolean("ro.monkey", false); 15931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{}; 1607be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana 1617be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana static { 162f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION); 1637be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1647be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana } 1657be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana 166d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana /** 167d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * This should only be called by system code. One should only call this after the service 168d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * has started. 169d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * @return a reference to the AccountManagerService instance 170d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * @hide 171d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana */ 172d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana public static AccountManagerService getSingleton() { 173d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return sThis.get(); 174d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 175603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 176603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public class AuthTokenKey { 177603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public final Account mAccount; 178603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public final String mAuthTokenType; 179603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private final int mHashCode; 180603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 181603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public AuthTokenKey(Account account, String authTokenType) { 182603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mAccount = account; 183603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mAuthTokenType = authTokenType; 184603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mHashCode = computeHashCode(); 185603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 186603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 187603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public boolean equals(Object o) { 188603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (o == this) { 189603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return true; 190603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 191603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (!(o instanceof AuthTokenKey)) { 192603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return false; 193603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 194603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana AuthTokenKey other = (AuthTokenKey)o; 195603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (!mAccount.equals(other.mAccount)) { 196603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return false; 197603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 198603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return (mAuthTokenType == null) 199603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana ? other.mAuthTokenType == null 200603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana : mAuthTokenType.equals(other.mAuthTokenType); 201603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 202603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 203603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private int computeHashCode() { 204603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana int result = 17; 205603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana result = 31 * result + mAccount.hashCode(); 206603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana result = 31 * result + ((mAuthTokenType == null) ? 0 : mAuthTokenType.hashCode()); 207603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return result; 208603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 209603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 210603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public int hashCode() { 211603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return mHashCode; 212603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 213603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 214603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 215603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public AccountManagerService(Context context) { 216603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mContext = context; 217603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 218603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mOpenHelper = new DatabaseHelper(mContext); 219603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 220603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mMessageThread = new HandlerThread("AccountManagerService"); 221603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mMessageThread.start(); 222603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mMessageHandler = new MessageHandler(mMessageThread.getLooper()); 223603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 224603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mAuthenticatorCache = new AccountAuthenticatorCache(mContext); 2255ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana mAuthenticatorCache.setListener(this, null /* Handler */); 226603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 227885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker mSimWatcher = new SimWatcher(mContext); 228d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana sThis.set(this); 229afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana 230afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana validateAccounts(); 231afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana } 232afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana 233afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana private void validateAccounts() { 234afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana boolean accountDeleted = false; 235afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 236afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana Cursor cursor = db.query(TABLE_ACCOUNTS, 237afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME}, 238afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana null, null, null, null, null); 239afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana try { 240afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana while (cursor.moveToNext()) { 241afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana final long accountId = cursor.getLong(0); 242afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana final String accountType = cursor.getString(1); 243afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana final String accountName = cursor.getString(2); 244afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana if (mAuthenticatorCache.getServiceInfo(AuthenticatorDescription.newKey(accountType)) 245afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana == null) { 246afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana Log.d(TAG, "deleting account " + accountName + " because type " 247afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana + accountType + " no longer has a registered authenticator"); 248afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null); 249afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana accountDeleted = true; 250afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana } 251afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana } 252afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana } finally { 253afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana cursor.close(); 254afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana if (accountDeleted) { 255afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana sendAccountsChangedBroadcast(); 256afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana } 257afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana } 2583ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana } 2593ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana 2605ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana public void onServiceChanged(AuthenticatorDescription desc, boolean removed) { 2613ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana boolean accountDeleted = false; 2623ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 2633ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana Cursor cursor = db.query(TABLE_ACCOUNTS, 2643ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME}, 2655ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana ACCOUNTS_TYPE + "=?", new String[]{desc.type}, null, null, null); 2663ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana try { 2673ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana while (cursor.moveToNext()) { 2683ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana final long accountId = cursor.getLong(0); 2693ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana final String accountType = cursor.getString(1); 2703ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana final String accountName = cursor.getString(2); 2715ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana Log.d(TAG, "deleting account " + accountName + " because type " 2725ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana + accountType + " no longer has a registered authenticator"); 2735ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null); 2745ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana accountDeleted = true; 2753ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana } 2763ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana } finally { 2773ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana cursor.close(); 2783ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana if (accountDeleted) { 2793ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana sendAccountsChangedBroadcast(); 2803ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana } 2813ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana } 282603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 283603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 284a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public String getPassword(Account account) { 285d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 286d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 28726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 288603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 289ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return readPasswordFromDatabase(account); 290603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 29126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 292603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 293603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 294603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 295ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private String readPasswordFromDatabase(Account account) { 29631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 29731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return null; 29831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 29931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana 300ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 301ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD}, 302ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", 303ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new String[]{account.name, account.type}, null, null, null); 304ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 305ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (cursor.moveToNext()) { 306ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return cursor.getString(0); 307ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 308ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return null; 309ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } finally { 310ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana cursor.close(); 311ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 312ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 313ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 314a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public String getUserData(Account account, String key) { 315d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 31626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 317603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 318ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return readUserDataFromDatabase(account, key); 319ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } finally { 320ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana restoreCallingIdentity(identityToken); 321ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 322ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 323ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 324ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private String readUserDataFromDatabase(Account account, String key) { 32531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 32631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return null; 32731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 32831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana 329ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 33086bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE}, 33186bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana EXTRAS_ACCOUNTS_ID 33286bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana + "=(select _id FROM accounts WHERE name=? AND type=?) AND " 33386bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana + EXTRAS_KEY + "=?", 33486bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana new String[]{account.name, account.type, key}, null, null, null); 335ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 33686bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana if (cursor.moveToNext()) { 33786bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana return cursor.getString(0); 338603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 33986bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana return null; 340603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 34186bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana cursor.close(); 342603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 343603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 344603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 3459788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana public AuthenticatorDescription[] getAuthenticatorTypes() { 34626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 34726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 3489788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>> 3499788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana authenticatorCollection = mAuthenticatorCache.getAllServices(); 3509788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana AuthenticatorDescription[] types = 3519788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana new AuthenticatorDescription[authenticatorCollection.size()]; 35226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana int i = 0; 3539788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator 354718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana : authenticatorCollection) { 355718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana types[i] = authenticator.type; 35626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana i++; 35726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 35826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return types; 35926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 36026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 361a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 362a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 363a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 364a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public Account[] getAccountsByType(String accountType) { 365ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 36626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana 367ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final String selection = accountType == null ? null : (ACCOUNTS_TYPE + "=?"); 368ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final String[] selectionArgs = accountType == null ? null : new String[]{accountType}; 369ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_NAME_TYPE_PROJECTION, 370ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana selection, selectionArgs, null, null, null); 371ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 372ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana int i = 0; 373ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Account[] accounts = new Account[cursor.getCount()]; 374ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana while (cursor.moveToNext()) { 375ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana accounts[i] = new Account(cursor.getString(1), cursor.getString(2)); 376ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana i++; 377603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 378ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return accounts; 379603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 380ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana cursor.close(); 381603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 382603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 383603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 384a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public boolean addAccount(Account account, String password, Bundle extras) { 385d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 386d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 387603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana // fails if the account already exists 38826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 389603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 390ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return insertAccountIntoDatabase(account, password, extras); 391ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } finally { 392ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana restoreCallingIdentity(identityToken); 393ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 394ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 395ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 396ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private boolean insertAccountIntoDatabase(Account account, String password, Bundle extras) { 397ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 398ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.beginTransaction(); 399ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 40031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 40131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return false; 40231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 40350c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller boolean noBroadcast = false; 40450c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller if (account.type.equals(GOOGLE_ACCOUNT_TYPE)) { 40550c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller // Look for the 'nobroadcast' flag and remove it since we don't want it to persist 40650c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller // in the db. 40750c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller noBroadcast = extras.getBoolean(NO_BROADCAST_FLAG, false); 40850c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller extras.remove(NO_BROADCAST_FLAG); 40950c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller } 41050c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller 411ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana long numMatches = DatabaseUtils.longForQuery(db, 412ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana "select count(*) from " + TABLE_ACCOUNTS 413ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", 414ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new String[]{account.name, account.type}); 415ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (numMatches > 0) { 416ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return false; 417ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 418ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana ContentValues values = new ContentValues(); 419ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana values.put(ACCOUNTS_NAME, account.name); 420ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana values.put(ACCOUNTS_TYPE, account.type); 421ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana values.put(ACCOUNTS_PASSWORD, password); 422ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values); 423ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (accountId < 0) { 424ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return false; 425ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 426ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (extras != null) { 427ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana for (String key : extras.keySet()) { 428ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final String value = extras.getString(key); 429ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (insertExtra(db, accountId, key, value) < 0) { 430ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return false; 431603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 432603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 433603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 434ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.setTransactionSuccessful(); 43550c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller if (!noBroadcast) { 43650c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller sendAccountsChangedBroadcast(); 43750c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller } 438ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return true; 439603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 440ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.endTransaction(); 441603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 442603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 443603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 444603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private long insertExtra(SQLiteDatabase db, long accountId, String key, String value) { 445603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana ContentValues values = new ContentValues(); 446603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana values.put(EXTRAS_KEY, key); 447603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana values.put(EXTRAS_ACCOUNTS_ID, accountId); 448603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana values.put(EXTRAS_VALUE, value); 449603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values); 450603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 451603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 4523084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana public void hasFeatures(IAccountManagerResponse response, 453bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana Account account, String[] features) { 454bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana checkReadAccountsPermission(); 455bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana long identityToken = clearCallingIdentity(); 456bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana try { 457bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana new TestFeaturesSession(response, account, features).bind(); 458bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } finally { 459bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana restoreCallingIdentity(identityToken); 460bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 461bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 462bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana 463bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana private class TestFeaturesSession extends Session { 464bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana private final String[] mFeatures; 465bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana private final Account mAccount; 466bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana 467bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana public TestFeaturesSession(IAccountManagerResponse response, 468bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana Account account, String[] features) { 469bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana super(response, account.type, false /* expectActivityLaunch */); 470bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana mFeatures = features; 471bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana mAccount = account; 472bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 473bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana 474bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana public void run() throws RemoteException { 475bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana try { 476bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana mAuthenticator.hasFeatures(this, mAccount, mFeatures); 477bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } catch (RemoteException e) { 478bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception"); 479bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 480bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 481bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana 482bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana public void onResult(Bundle result) { 483bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana IAccountManagerResponse response = getResponseAndClose(); 484bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana if (response != null) { 485bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana try { 486bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana if (result == null) { 487bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle"); 488bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana return; 489bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 490bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana final Bundle newResult = new Bundle(); 491bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana newResult.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, 492bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)); 493bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana response.onResult(newResult); 494bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } catch (RemoteException e) { 495bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana // if the caller is dead then there is no one to care about remote exceptions 496bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 497bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana Log.v(TAG, "failure while notifying response", e); 498bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 499bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 500bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 501bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 502bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana 503bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana protected String toDebugString(long now) { 5043084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana return super.toDebugString(now) + ", hasFeatures" 505bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana + ", " + mAccount 506bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null); 507bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 508bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana } 509307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 510ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void removeAccount(IAccountManagerResponse response, Account account) { 511d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 51226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 51326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 514ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new RemoveAccountSession(response, account).bind(); 51526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 51626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 517a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 518603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 519603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 520ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private class RemoveAccountSession extends Session { 521ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final Account mAccount; 522ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public RemoveAccountSession(IAccountManagerResponse response, Account account) { 523ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana super(response, account.type, false /* expectActivityLaunch */); 524ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mAccount = account; 525ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 526ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 527ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana protected String toDebugString(long now) { 528ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return super.toDebugString(now) + ", removeAccount" 529ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana + ", account " + mAccount; 530ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 531ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 532ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void run() throws RemoteException { 533ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana mAuthenticator.getAccountRemovalAllowed(this, mAccount); 534ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 535ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 536ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void onResult(Bundle result) { 537f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT) 538f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana && !result.containsKey(AccountManager.KEY_INTENT)) { 539f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT); 540ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (removalAllowed) { 541ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana removeAccount(mAccount); 542ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 543ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana IAccountManagerResponse response = getResponseAndClose(); 544ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (response != null) { 545ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana Bundle result2 = new Bundle(); 546f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result2.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, removalAllowed); 547ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 548ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana response.onResult(result2); 549ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } catch (RemoteException e) { 550ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana // ignore 551ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 552ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 553ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 554ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana super.onResult(result); 555ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 556ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 557ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 558ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private void removeAccount(Account account) { 559ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana final SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 560ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", 561ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new String[]{account.name, account.type}); 562ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana sendAccountsChangedBroadcast(); 563ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 564ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 565a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void invalidateAuthToken(String accountType, String authToken) { 566d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 56726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 568603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 56926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 57026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana db.beginTransaction(); 57126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 57226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana invalidateAuthToken(db, accountType, authToken); 57326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana db.setTransactionSuccessful(); 57426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 57526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana db.endTransaction(); 57626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 577603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 57826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 579603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 580603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 581603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 582603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private void invalidateAuthToken(SQLiteDatabase db, String accountType, String authToken) { 583ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (authToken == null || accountType == null) { 584ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 585ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 5863326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana Cursor cursor = db.rawQuery( 5873326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana "SELECT " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID 5883326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME 5893326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + ", " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_TYPE 5903326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + " FROM " + TABLE_ACCOUNTS 5913326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + " JOIN " + TABLE_AUTHTOKENS 5923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + " ON " + TABLE_ACCOUNTS + "." + ACCOUNTS_ID 5933326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + " = " + AUTHTOKENS_ACCOUNTS_ID 5943326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + " WHERE " + AUTHTOKENS_AUTHTOKEN + " = ? AND " 5953326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " = ?", 5963326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana new String[]{authToken, accountType}); 5973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 5983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana while (cursor.moveToNext()) { 5993326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana long authTokenId = cursor.getLong(0); 6003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana String accountName = cursor.getString(1); 6013326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana String authTokenType = cursor.getString(2); 6023326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null); 603603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 6043326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } finally { 6053326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana cursor.close(); 606603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 607603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 608603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 609603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private boolean saveAuthTokenToDatabase(Account account, String type, String authToken) { 61031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null || type == null) { 61131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return false; 61231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 6136dfd1382fe43592b9602fc6553e820c64067c759Fred Quintana cancelNotification(getSigninRequiredNotificationId(account)); 614603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 615603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.beginTransaction(); 616603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 6173326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana long accountId = getAccountId(db, account); 6183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (accountId < 0) { 6193326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return false; 6203326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 6213326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana db.delete(TABLE_AUTHTOKENS, 6223326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?", 6233326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana new String[]{type}); 6243326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana ContentValues values = new ContentValues(); 6253326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana values.put(AUTHTOKENS_ACCOUNTS_ID, accountId); 6263326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana values.put(AUTHTOKENS_TYPE, type); 6273326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana values.put(AUTHTOKENS_AUTHTOKEN, authToken); 6283326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (db.insert(TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values) >= 0) { 629603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.setTransactionSuccessful(); 630603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return true; 631603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 632603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return false; 633603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 634603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.endTransaction(); 635603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 636603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 637603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 638603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public String readAuthTokenFromDatabase(Account account, String authTokenType) { 63931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null || authTokenType == null) { 64031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return null; 64131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 642603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 64386bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana Cursor cursor = db.query(TABLE_AUTHTOKENS, new String[]{AUTHTOKENS_AUTHTOKEN}, 64486bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?) AND " 64586bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana + AUTHTOKENS_TYPE + "=?", 64686bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana new String[]{account.name, account.type, authTokenType}, 64786bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana null, null, null); 648603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 64986bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana if (cursor.moveToNext()) { 65086bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana return cursor.getString(0); 651603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 65286bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana return null; 653603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 65486bd084cf683e9877b4146918192b3fe5e268cf5Fred Quintana cursor.close(); 655603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 656603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 657603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 658a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public String peekAuthToken(Account account, String authTokenType) { 659d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 66026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 66126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 6623326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return readAuthTokenFromDatabase(account, authTokenType); 66326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 66426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 665603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 666603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 667603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 668a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void setAuthToken(Account account, String authTokenType, String authToken) { 669d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 67026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 67126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 6726dfd1382fe43592b9602fc6553e820c64067c759Fred Quintana saveAuthTokenToDatabase(account, authTokenType, authToken); 67326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 67426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 67526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 676603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 677603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 678a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void setPassword(Account account, String password) { 679d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 68026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 68126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 6823ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana setPasswordInDB(account, password); 68326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 68426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 68526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 686603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 687603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 6883ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana private void setPasswordInDB(Account account, String password) { 68931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 69031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return; 69131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 6923ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana ContentValues values = new ContentValues(); 6933ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana values.put(ACCOUNTS_PASSWORD, password); 6943ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana mOpenHelper.getWritableDatabase().update(TABLE_ACCOUNTS, values, 6953ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?", 6963ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana new String[]{account.name, account.type}); 6973ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana sendAccountsChangedBroadcast(); 6983ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana } 6993ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana 7003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana private void sendAccountsChangedBroadcast() { 7013326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mContext.sendBroadcast(ACCOUNTS_CHANGED_INTENT); 7023326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 7033326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 704a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void clearPassword(Account account) { 705d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 70626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 70726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 7083ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana setPasswordInDB(account, null); 70926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 71026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 71126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 712603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 713603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 714a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void setUserData(Account account, String key, String value) { 715d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkAuthenticateAccountsPermission(account); 71626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 71731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null) { 71831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return; 71931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 72050c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller if (account.type.equals(GOOGLE_ACCOUNT_TYPE) && key.equals("broadcast")) { 72150c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller sendAccountsChangedBroadcast(); 72250c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller return; 72350c05f38b3728b7430dd4bb8d98565d9c5e56798Jim Miller } 724603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 725ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana writeUserdataIntoDatabase(account, key, value); 726ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } finally { 727ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana restoreCallingIdentity(identityToken); 728ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 729ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 730ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 731ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana private void writeUserdataIntoDatabase(Account account, String key, String value) { 73231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null || key == null) { 73331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return; 73431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 735ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 736ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.beginTransaction(); 737ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 738ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana long accountId = getAccountId(db, account); 739ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (accountId < 0) { 740ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 741ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 742ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana long extrasId = getExtrasId(db, accountId, key); 743ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (extrasId < 0 ) { 744ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana extrasId = insertExtra(db, accountId, key, value); 745ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (extrasId < 0) { 746603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return; 747603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 748ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } else { 749ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana ContentValues values = new ContentValues(); 750ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana values.put(EXTRAS_VALUE, value); 751ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) { 752ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 75326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 754ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 755603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 756ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.setTransactionSuccessful(); 757603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 758ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana db.endTransaction(); 759603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 760603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 761603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 762d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void onResult(IAccountManagerResponse response, Bundle result) { 763d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana try { 764d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana response.onResult(result); 765d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } catch (RemoteException e) { 766d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // if the caller is dead then there is no one to care about remote 767d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // exceptions 768d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 769d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Log.v(TAG, "failure while notifying response", e); 770d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 771d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 772d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 773d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 774a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void getAuthToken(IAccountManagerResponse response, final Account account, 775a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final String authTokenType, final boolean notifyOnAuthFailure, 776a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final boolean expectActivityLaunch, final Bundle loginOptions) { 777d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkBinderPermission(Manifest.permission.USE_CREDENTIALS); 778d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final int callerUid = Binder.getCallingUid(); 779d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final boolean permissionGranted = permissionIsGranted(account, authTokenType, callerUid); 780d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 78126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 78226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 783d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // if the caller has permission, do the peek. otherwise go the more expensive 784d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // route of starting a Session 785d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (permissionGranted) { 786d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String authToken = readAuthTokenFromDatabase(account, authTokenType); 787d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (authToken != null) { 78826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana Bundle result = new Bundle(); 789f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(AccountManager.KEY_AUTHTOKEN, authToken); 790f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); 791f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); 792d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana onResult(response, result); 793d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return; 794a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 795a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 796603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 797ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new Session(response, account.type, expectActivityLaunch) { 79826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana protected String toDebugString(long now) { 79926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (loginOptions != null) loginOptions.keySet(); 80026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return super.toDebugString(now) + ", getAuthToken" 80126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", " + account 80226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", authTokenType " + authTokenType 80326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", loginOptions " + loginOptions 80426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", notifyOnAuthFailure " + notifyOnAuthFailure; 80526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 806a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 80726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana public void run() throws RemoteException { 808d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // If the caller doesn't have permission then create and return the 809d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // "grant permission" intent instead of the "getAuthToken" intent. 810d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (!permissionGranted) { 811d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mAuthenticator.getAuthTokenLabel(this, authTokenType); 812d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } else { 813d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions); 814d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 81526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 816a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 81726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana public void onResult(Bundle result) { 81826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (result != null) { 819f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) { 820d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Intent intent = newGrantCredentialsPermissionIntent(account, callerUid, 821d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new AccountAuthenticatorResponse(this), 822d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana authTokenType, 823f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL)); 824d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Bundle bundle = new Bundle(); 825f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana bundle.putParcelable(AccountManager.KEY_INTENT, intent); 826d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana onResult(bundle); 827d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return; 828d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 829f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana String authToken = result.getString(AccountManager.KEY_AUTHTOKEN); 83026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (authToken != null) { 831f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana String name = result.getString(AccountManager.KEY_ACCOUNT_NAME); 832f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE); 83326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) { 834f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, 83526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana "the type and name should not be empty"); 83626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return; 83726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 8386dfd1382fe43592b9602fc6553e820c64067c759Fred Quintana saveAuthTokenToDatabase(new Account(name, type), 8396dfd1382fe43592b9602fc6553e820c64067c759Fred Quintana authTokenType, authToken); 840a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 841603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 842f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana Intent intent = result.getParcelable(AccountManager.KEY_INTENT); 84326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (intent != null && notifyOnAuthFailure) { 844d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana doNotification( 845f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE), 84626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana intent); 84726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 848a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 84926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana super.onResult(result); 850a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 85126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana }.bind(); 85226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 85326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 85426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 855603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 856603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 857d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void createNoCredentialsPermissionNotification(Account account, Intent intent) { 858d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana int uid = intent.getIntExtra( 859d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1); 860d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String authTokenType = intent.getStringExtra( 861d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE); 862d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String authTokenLabel = intent.getStringExtra( 863d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL); 864d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 865d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Notification n = new Notification(android.R.drawable.stat_sys_warning, null, 866d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 0 /* when */); 867ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer final String titleAndSubtitle = 868ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer mContext.getString(R.string.permission_request_notification_with_subtitle, 869ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer account.name); 870ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer final int index = titleAndSubtitle.indexOf('\n'); 871ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer final String title = titleAndSubtitle.substring(0, index); 872ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer final String subtitle = titleAndSubtitle.substring(index + 1); 873d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana n.setLatestEventInfo(mContext, 874ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer title, subtitle, 875d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)); 876d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)) 877d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana .notify(getCredentialPermissionNotificationId(account, authTokenType, uid), n); 878d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 879d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 880d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private Intent newGrantCredentialsPermissionIntent(Account account, int uid, 881d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) { 882d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo = 883d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mAuthenticatorCache.getServiceInfo( 884ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana AuthenticatorDescription.newKey(account.type)); 885d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (serviceInfo == null) { 886ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new IllegalArgumentException("unknown account type: " + account.type); 887d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 888d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 889d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final Context authContext; 890d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana try { 891d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana authContext = mContext.createPackageContext( 892d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana serviceInfo.type.packageName, 0); 893d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } catch (PackageManager.NameNotFoundException e) { 894ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana throw new IllegalArgumentException("unknown account type: " + account.type); 895d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 896d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 897d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class); 898d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 899d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.addCategory( 900d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid))); 901d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account); 902d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL, authTokenLabel); 903d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType); 904d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response); 905d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT_TYPE_LABEL, 906d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana authContext.getString(serviceInfo.type.labelId)); 907d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_PACKAGES, 908d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mContext.getPackageManager().getPackagesForUid(uid)); 909d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid); 910d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return intent; 911d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 912d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 913d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private Integer getCredentialPermissionNotificationId(Account account, String authTokenType, 914d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana int uid) { 915d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Integer id; 916d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana synchronized(mCredentialsPermissionNotificationIds) { 917d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final Pair<Pair<Account, String>, Integer> key = 918d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new Pair<Pair<Account, String>, Integer>( 919d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new Pair<Account, String>(account, authTokenType), uid); 920d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana id = mCredentialsPermissionNotificationIds.get(key); 921d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (id == null) { 922d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana id = mNotificationIds.incrementAndGet(); 923d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mCredentialsPermissionNotificationIds.put(key, id); 924d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 925d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 926d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return id; 927d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 928d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 929d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private Integer getSigninRequiredNotificationId(Account account) { 930d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Integer id; 931d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana synchronized(mSigninRequiredNotificationIds) { 932d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana id = mSigninRequiredNotificationIds.get(account); 933d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (id == null) { 934d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana id = mNotificationIds.incrementAndGet(); 935d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mSigninRequiredNotificationIds.put(account, id); 936d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 937d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 938d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return id; 939d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 940d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 941a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 9423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void addAcount(final IAccountManagerResponse response, final String accountType, 9433326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana final String authTokenType, final String[] requiredFeatures, 944a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final boolean expectActivityLaunch, final Bundle options) { 945d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 94626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 94726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 94826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana new Session(response, accountType, expectActivityLaunch) { 94926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana public void run() throws RemoteException { 9503348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures, 9513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana options); 95226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 953a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 95426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana protected String toDebugString(long now) { 95526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return super.toDebugString(now) + ", addAccount" 9563326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + ", accountType " + accountType 9573326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + ", requiredFeatures " 9583326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + (requiredFeatures != null 9593326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana ? TextUtils.join(",", requiredFeatures) 9603326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana : null); 96126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 96226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana }.bind(); 96326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 96426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 96526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 966603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 967603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 968a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void confirmCredentials(IAccountManagerResponse response, 969f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana final Account account, final Bundle options, final boolean expectActivityLaunch) { 970d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 97126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 97226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 973ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new Session(response, account.type, expectActivityLaunch) { 97426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana public void run() throws RemoteException { 975f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana mAuthenticator.confirmCredentials(this, account, options); 97626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 97726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana protected String toDebugString(long now) { 97826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return super.toDebugString(now) + ", confirmCredentials" 97926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", " + account; 98026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 98126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana }.bind(); 98226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 98326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 98426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 985603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 986603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 987a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void updateCredentials(IAccountManagerResponse response, final Account account, 988a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final String authTokenType, final boolean expectActivityLaunch, 989a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final Bundle loginOptions) { 990d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 99126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 99226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 993ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana new Session(response, account.type, expectActivityLaunch) { 99426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana public void run() throws RemoteException { 99526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions); 99626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 99726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana protected String toDebugString(long now) { 99826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (loginOptions != null) loginOptions.keySet(); 99926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return super.toDebugString(now) + ", updateCredentials" 100026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", " + account 100126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", authTokenType " + authTokenType 100226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", loginOptions " + loginOptions; 100326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 100426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana }.bind(); 100526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 100626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 100726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 1008603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1009603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1010a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void editProperties(IAccountManagerResponse response, final String accountType, 1011a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final boolean expectActivityLaunch) { 1012d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkManageAccountsPermission(); 101326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 101426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 101526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana new Session(response, accountType, expectActivityLaunch) { 101626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana public void run() throws RemoteException { 101726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana mAuthenticator.editProperties(this, mAccountType); 101826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 101926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana protected String toDebugString(long now) { 102026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana return super.toDebugString(now) + ", editProperties" 102126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana + ", accountType " + accountType; 102226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 102326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana }.bind(); 102426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 102526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 102626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 1027603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1028603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 10293326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana private class GetAccountsByTypeAndFeatureSession extends Session { 10303326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana private final String[] mFeatures; 10313326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana private volatile Account[] mAccountsOfType = null; 10323326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana private volatile ArrayList<Account> mAccountsWithFeatures = null; 10333326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana private volatile int mCurrentAccount = 0; 10343326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public GetAccountsByTypeAndFeatureSession(IAccountManagerResponse response, 10363326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana String type, String[] features) { 10373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana super(response, type, false /* expectActivityLaunch */); 10383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mFeatures = features; 10393326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10403326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10413326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void run() throws RemoteException { 10423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAccountsOfType = getAccountsByType(mAccountType); 10433326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana // check whether each account matches the requested features 10443326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length); 10453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mCurrentAccount = 0; 10463326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10473326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana checkAccount(); 10483326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10493326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10503326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void checkAccount() { 10513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (mCurrentAccount >= mAccountsOfType.length) { 10523326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana sendResult(); 10533326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return; 10543326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10553326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10563326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 10573326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAuthenticator.hasFeatures(this, mAccountsOfType[mCurrentAccount], mFeatures); 10583326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } catch (RemoteException e) { 1059f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception"); 1060a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1061603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1062603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 10633326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void onResult(Bundle result) { 10643326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mNumResults++; 10653326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (result == null) { 1066f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle"); 10673326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return; 10683326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1069f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) { 10703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mAccountsWithFeatures.add(mAccountsOfType[mCurrentAccount]); 10713326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10723326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana mCurrentAccount++; 10733326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana checkAccount(); 1074a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 10753326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10763326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public void sendResult() { 10773326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana IAccountManagerResponse response = getResponseAndClose(); 10783326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (response != null) { 10793326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 10803326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana Account[] accounts = new Account[mAccountsWithFeatures.size()]; 10813326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana for (int i = 0; i < accounts.length; i++) { 10823326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana accounts[i] = mAccountsWithFeatures.get(i); 10833326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10843326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana Bundle result = new Bundle(); 1085f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts); 10863326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana response.onResult(result); 10873326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } catch (RemoteException e) { 10883326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana // if the caller is dead then there is no one to care about remote exceptions 10893326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 10903326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana Log.v(TAG, "failure while notifying response", e); 10913326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10933326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10943326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 10953326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10963326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 10973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana protected String toDebugString(long now) { 10983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return super.toDebugString(now) + ", getAccountsByTypeAndFeatures" 10993326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null); 11003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11013326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 1102ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1103ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public Account[] getAccounts(String type) { 1104ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana checkReadAccountsPermission(); 1105ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana long identityToken = clearCallingIdentity(); 1106ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana try { 1107ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return getAccountsByType(type); 1108ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } finally { 1109ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana restoreCallingIdentity(identityToken); 1110ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1111ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 1112ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana 1113ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana public void getAccountsByFeatures(IAccountManagerResponse response, 11143326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana String type, String[] features) { 1115d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkReadAccountsPermission(); 1116ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (features != null && type == null) { 11173326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (response != null) { 11183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 1119f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "type is null"); 11203326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } catch (RemoteException e) { 11213326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana // ignore this 11223326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11233326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11243326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana return; 11253326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11263326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana long identityToken = clearCallingIdentity(); 11273326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana try { 1128ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana if (features == null || features.length == 0) { 1129ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana getAccountsByType(type); 1130ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return; 1131ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana } 11323326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana new GetAccountsByTypeAndFeatureSession(response, type, features).bind(); 11333326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } finally { 11343326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana restoreCallingIdentity(identityToken); 11353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11363326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana } 11373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana 1138603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private long getAccountId(SQLiteDatabase db, Account account) { 1139603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID}, 1140ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana "name=? AND type=?", new String[]{account.name, account.type}, null, null, null); 1141603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 1142603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (cursor.moveToNext()) { 1143603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return cursor.getLong(0); 1144603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1145603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return -1; 1146603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 1147603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana cursor.close(); 1148603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1149603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1150603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1151603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private long getExtrasId(SQLiteDatabase db, long accountId, String key) { 1152603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_ID}, 1153603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?", 1154603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana new String[]{key}, null, null, null); 1155603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 1156603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (cursor.moveToNext()) { 1157603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return cursor.getLong(0); 1158603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1159603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return -1; 1160603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 1161603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana cursor.close(); 1162603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1163603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1164603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1165a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private abstract class Session extends IAccountAuthenticatorResponse.Stub 1166b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana implements IBinder.DeathRecipient, ServiceConnection { 1167603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana IAccountManagerResponse mResponse; 1168603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana final String mAccountType; 1169a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final boolean mExpectActivityLaunch; 1170a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana final long mCreationTime; 1171a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 11723326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana public int mNumResults = 0; 1173a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private int mNumRequestContinued = 0; 1174a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private int mNumErrors = 0; 1175a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1176603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1177603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana IAccountAuthenticator mAuthenticator = null; 1178603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1179a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public Session(IAccountManagerResponse response, String accountType, 1180a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana boolean expectActivityLaunch) { 1181603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana super(); 1182a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (response == null) throw new IllegalArgumentException("response is null"); 11833326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana if (accountType == null) throw new IllegalArgumentException("accountType is null"); 1184603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mResponse = response; 1185603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mAccountType = accountType; 1186a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mExpectActivityLaunch = expectActivityLaunch; 1187a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mCreationTime = SystemClock.elapsedRealtime(); 1188a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana synchronized (mSessions) { 1189a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mSessions.put(toString(), this); 1190a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1191a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana try { 1192a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana response.asBinder().linkToDeath(this, 0 /* flags */); 1193a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (RemoteException e) { 1194a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mResponse = null; 1195a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana binderDied(); 1196a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1197603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1198603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1199a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana IAccountManagerResponse getResponseAndClose() { 1200603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (mResponse == null) { 1201603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana // this session has already been closed 1202603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return null; 1203603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1204a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana IAccountManagerResponse response = mResponse; 1205a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana close(); // this clears mResponse so we need to save the response before this call 1206a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return response; 1207a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1208a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1209a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana private void close() { 1210a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana synchronized (mSessions) { 1211a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (mSessions.remove(toString()) == null) { 1212a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // the session was already closed, so bail out now 1213a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return; 1214a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1215a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1216a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (mResponse != null) { 1217a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // stop listening for response deaths 1218a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mResponse.asBinder().unlinkToDeath(this, 0 /* flags */); 1219a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1220a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // clear this so that we don't accidentally send any further results 1221a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mResponse = null; 1222a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1223603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana cancelTimeout(); 1224603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana unbind(); 1225a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1226a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1227a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void binderDied() { 1228603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mResponse = null; 1229a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana close(); 1230a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1231a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1232a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana protected String toDebugString() { 1233a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return toDebugString(SystemClock.elapsedRealtime()); 1234a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1235a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1236a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana protected String toDebugString(long now) { 1237a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana return "Session: expectLaunch " + mExpectActivityLaunch 1238a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + ", connected " + (mAuthenticator != null) 1239a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + ", stats (" + mNumResults + "/" + mNumRequestContinued 1240a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + "/" + mNumErrors + ")" 1241a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + ", lifetime " + ((now - mCreationTime) / 1000.0); 1242603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1243603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1244603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana void bind() { 1245a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1246a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.v(TAG, "initiating bind to authenticator type " + mAccountType); 1247a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1248b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana if (!bindToAuthenticator(mAccountType)) { 1249a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.d(TAG, "bind attempt failed for " + toDebugString()); 1250f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure"); 1251603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1252603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1253603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1254603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private void unbind() { 1255603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (mAuthenticator != null) { 1256603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mAuthenticator = null; 1257b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana mContext.unbindService(this); 1258603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1259603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1260603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1261603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void scheduleTimeout() { 1262603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mMessageHandler.sendMessageDelayed( 1263603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mMessageHandler.obtainMessage(MESSAGE_TIMED_OUT, this), TIMEOUT_DELAY_MS); 1264603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1265603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1266603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void cancelTimeout() { 1267603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this); 1268603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1269603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1270b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana public void onServiceConnected(ComponentName name, IBinder service) { 1271603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mAuthenticator = IAccountAuthenticator.Stub.asInterface(service); 1272a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana try { 1273a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana run(); 1274a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (RemoteException e) { 1275f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, 1276a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana "remote exception"); 1277a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1278603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1279603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1280b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana public void onServiceDisconnected(ComponentName name) { 1281a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mAuthenticator = null; 1282a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana IAccountManagerResponse response = getResponseAndClose(); 1283603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (response != null) { 1284f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, 1285a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana "disconnected"); 1286603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1287603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1288603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1289b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana public abstract void run() throws RemoteException; 1290b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana 1291603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void onTimedOut() { 1292a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana IAccountManagerResponse response = getResponseAndClose(); 1293603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (response != null) { 1294f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, 1295a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana "timeout"); 1296603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1297603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1298603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1299a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void onResult(Bundle result) { 1300a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mNumResults++; 1301f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana if (result != null && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) { 1302f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME); 1303f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE); 1304d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) { 1305d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Account account = new Account(accountName, accountType); 1306d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana cancelNotification(getSigninRequiredNotificationId(account)); 1307d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1308603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1309a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana IAccountManagerResponse response; 1310a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (mExpectActivityLaunch && result != null 1311f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana && result.containsKey(AccountManager.KEY_INTENT)) { 1312a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana response = mResponse; 1313a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 1314a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana response = getResponseAndClose(); 1315603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1316603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (response != null) { 1317603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 1318a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (result == null) { 1319f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, 1320a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana "null bundle returned"); 1321a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 1322a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana response.onResult(result); 1323a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1324603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } catch (RemoteException e) { 1325a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana // if the caller is dead then there is no one to care about remote exceptions 1326a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1327a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.v(TAG, "failure while notifying response", e); 1328a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1329603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1330603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1331603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1332603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1333a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana public void onRequestContinued() { 1334a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mNumRequestContinued++; 1335603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1336603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1337603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void onError(int errorCode, String errorMessage) { 1338a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana mNumErrors++; 1339a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1340a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.v(TAG, "Session.onError: " + errorCode + ", " + errorMessage); 1341603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1342a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana IAccountManagerResponse response = getResponseAndClose(); 1343a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (response != null) { 1344a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1345a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.v(TAG, "Session.onError: responding"); 1346a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1347a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana try { 1348a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana response.onError(errorCode, errorMessage); 1349a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } catch (RemoteException e) { 1350a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1351a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.v(TAG, "Session.onError: caught RemoteException while responding", e); 1352a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1353a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1354a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } else { 1355a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1356a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.v(TAG, "Session.onError: already closed"); 1357a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1358603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1359603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1360b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana 1361b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana /** 1362b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana * find the component name for the authenticator and initiate a bind 1363b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana * if no authenticator or the bind fails then return false, otherwise return true 1364b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana */ 1365b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana private boolean bindToAuthenticator(String authenticatorType) { 1366b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo = 1367b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana mAuthenticatorCache.getServiceInfo( 1368b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana AuthenticatorDescription.newKey(authenticatorType)); 1369b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana if (authenticatorInfo == null) { 1370b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1371b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana Log.v(TAG, "there is no authenticator for " + authenticatorType 1372b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana + ", bailing out"); 1373b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana } 1374b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana return false; 1375b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana } 1376b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana 1377b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana Intent intent = new Intent(); 1378b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT); 1379b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana intent.setComponent(authenticatorInfo.componentName); 1380b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1381b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName); 1382b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana } 1383b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { 1384b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1385b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed"); 1386b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana } 1387b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana return false; 1388b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana } 1389b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana 1390b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana 1391b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana return true; 1392b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana } 1393603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1394603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1395603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private class MessageHandler extends Handler { 1396603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana MessageHandler(Looper looper) { 1397603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana super(looper); 1398603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 13993348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache 1400603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void handleMessage(Message msg) { 1401603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana switch (msg.what) { 1402603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana case MESSAGE_TIMED_OUT: 1403603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana Session session = (Session)msg.obj; 1404603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana session.onTimedOut(); 1405603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana break; 1406603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1407603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana default: 1408603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana throw new IllegalStateException("unhandled message: " + msg.what); 1409603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1410603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1411603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1412603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1413a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor private static String getDatabaseName() { 1414a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor if(Environment.isEncryptedFilesystemEnabled()) { 1415a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor // Hard-coded path in case of encrypted file system 1416a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor return Environment.getSystemSecureDirectory().getPath() + File.separator + DATABASE_NAME; 1417a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor } else { 1418a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor // Regular path in case of non-encrypted file system 1419a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor return DATABASE_NAME; 1420a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor } 1421a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor } 1422a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor 1423603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private class DatabaseHelper extends SQLiteOpenHelper { 1424a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor 1425603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public DatabaseHelper(Context context) { 1426a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor super(context, AccountManagerService.getDatabaseName(), null, DATABASE_VERSION); 1427603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1428603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1429603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana @Override 1430603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void onCreate(SQLiteDatabase db) { 1431603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.execSQL("CREATE TABLE " + TABLE_ACCOUNTS + " ( " 1432603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " 1433603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + ACCOUNTS_NAME + " TEXT NOT NULL, " 1434603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + ACCOUNTS_TYPE + " TEXT NOT NULL, " 1435603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + ACCOUNTS_PASSWORD + " TEXT, " 1436603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))"); 1437603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1438603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " ( " 1439603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + AUTHTOKENS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " 1440603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + AUTHTOKENS_ACCOUNTS_ID + " INTEGER NOT NULL, " 1441603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + AUTHTOKENS_TYPE + " TEXT NOT NULL, " 1442603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + AUTHTOKENS_AUTHTOKEN + " TEXT, " 1443603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + "UNIQUE (" + AUTHTOKENS_ACCOUNTS_ID + "," + AUTHTOKENS_TYPE + "))"); 1444603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1445d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana createGrantsTable(db); 1446d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1447603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.execSQL("CREATE TABLE " + TABLE_EXTRAS + " ( " 1448603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + EXTRAS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " 1449603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + EXTRAS_ACCOUNTS_ID + " INTEGER, " 1450603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + EXTRAS_KEY + " TEXT NOT NULL, " 1451603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + EXTRAS_VALUE + " TEXT, " 1452603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + "UNIQUE(" + EXTRAS_ACCOUNTS_ID + "," + EXTRAS_KEY + "))"); 1453603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1454603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.execSQL("CREATE TABLE " + TABLE_META + " ( " 1455603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + META_KEY + " TEXT PRIMARY KEY NOT NULL, " 1456603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana + META_VALUE + " TEXT)"); 1457a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1458d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana createAccountsDeletionTrigger(db); 1459d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1460d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1461d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void createAccountsDeletionTrigger(SQLiteDatabase db) { 1462a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana db.execSQL("" 1463a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS 1464a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " BEGIN" 1465a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " DELETE FROM " + TABLE_AUTHTOKENS 1466a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " WHERE " + AUTHTOKENS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;" 1467a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " DELETE FROM " + TABLE_EXTRAS 1468a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " WHERE " + EXTRAS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;" 1469d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " DELETE FROM " + TABLE_GRANTS 1470d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " WHERE " + GRANTS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;" 1471a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana + " END"); 1472603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1473603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1474d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void createGrantsTable(SQLiteDatabase db) { 1475d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.execSQL("CREATE TABLE " + TABLE_GRANTS + " ( " 1476d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + GRANTS_ACCOUNTS_ID + " INTEGER NOT NULL, " 1477d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + GRANTS_AUTH_TOKEN_TYPE + " STRING NOT NULL, " 1478d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + GRANTS_GRANTEE_UID + " INTEGER NOT NULL, " 1479d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + "UNIQUE (" + GRANTS_ACCOUNTS_ID + "," + GRANTS_AUTH_TOKEN_TYPE 1480d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + "," + GRANTS_GRANTEE_UID + "))"); 1481d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1482d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1483603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana @Override 1484603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 1485a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion); 1486603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1487a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana if (oldVersion == 1) { 1488d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // no longer need to do anything since the work is done 1489d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // when upgrading from version 2 1490d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana oldVersion++; 1491d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1492d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1493d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (oldVersion == 2) { 1494d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana createGrantsTable(db); 1495d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.execSQL("DROP TRIGGER " + TABLE_ACCOUNTS + "Delete"); 1496d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana createAccountsDeletionTrigger(db); 1497a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana oldVersion++; 1498a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 14993348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache 15003348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache if (oldVersion == 3) { 15013348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_TYPE + 15023348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache " = 'com.google' WHERE " + ACCOUNTS_TYPE + " == 'com.google.GAIA'"); 15033348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache oldVersion++; 15043348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache } 1505603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1506603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1507603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana @Override 1508603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void onOpen(SQLiteDatabase db) { 1509603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "opened database " + DATABASE_NAME); 1510603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1511603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1512603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1513603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private void setMetaValue(String key, String value) { 1514603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana ContentValues values = new ContentValues(); 1515603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana values.put(META_KEY, key); 1516603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana values.put(META_VALUE, value); 1517603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana mOpenHelper.getWritableDatabase().replace(TABLE_META, META_KEY, values); 1518603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1519603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1520603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private String getMetaValue(String key) { 1521603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana Cursor c = mOpenHelper.getReadableDatabase().query(TABLE_META, 1522603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana new String[]{META_VALUE}, META_KEY + "=?", new String[]{key}, null, null, null); 1523603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 1524603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (c.moveToNext()) { 1525603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return c.getString(0); 1526603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1527603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return null; 1528603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 1529603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana c.close(); 1530603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1531603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1532603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1533603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana private class SimWatcher extends BroadcastReceiver { 1534603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public SimWatcher(Context context) { 1535603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana // Re-scan the SIM card when the SIM state changes, and also if 1536603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana // the disk recovers from a full state (we may have failed to handle 1537603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana // things properly while the disk was full). 1538603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana final IntentFilter filter = new IntentFilter(); 1539603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 1540603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); 1541603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana context.registerReceiver(this, filter); 1542603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 15433348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache 1544603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana /** 1545603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Compare the IMSI to the one stored in the login service's 1546603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * database. If they differ, erase all passwords and 1547603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * authtokens (and store the new IMSI). 1548603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */ 1549603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana @Override 1550603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public void onReceive(Context context, Intent intent) { 1551885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // Check IMSI on every update; nothing happens if the IMSI 1552885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // is missing or unchanged. 1553885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker TelephonyManager telephonyManager = 1554885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 1555885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (telephonyManager == null) { 1556885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker Log.w(TAG, "failed to get TelephonyManager"); 1557885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker return; 1558885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1559885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker String imsi = telephonyManager.getSubscriberId(); 1560885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker 1561885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // If the subscriber ID is an empty string, don't do anything. 1562603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (TextUtils.isEmpty(imsi)) return; 1563603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1564885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // If the current IMSI matches what's stored, don't do anything. 1565603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana String storedImsi = getMetaValue("imsi"); 1566603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1567603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana Log.v(TAG, "current IMSI=" + imsi + "; stored IMSI=" + storedImsi); 1568603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1569885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (imsi.equals(storedImsi)) return; 1570885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker 1571885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // If a CDMA phone is unprovisioned, getSubscriberId() 1572885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // will return a different value, but we *don't* erase the 1573885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // passwords. We only erase them if it has a different 1574885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // subscriber ID once it's provisioned. 1575885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (telephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) { 1576885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker IBinder service = ServiceManager.checkService(Context.TELEPHONY_SERVICE); 1577885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (service == null) { 1578885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker Log.w(TAG, "call to checkService(TELEPHONY_SERVICE) failed"); 1579885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker return; 1580885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1581885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker ITelephony telephony = ITelephony.Stub.asInterface(service); 1582885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (telephony == null) { 1583885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker Log.w(TAG, "failed to get ITelephony interface"); 1584885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker return; 1585885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1586885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker boolean needsProvisioning; 1587885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker try { 1588885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker needsProvisioning = telephony.getCdmaNeedsProvisioning(); 1589885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } catch (RemoteException e) { 1590885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker Log.w(TAG, "exception while checking provisioning", e); 1591885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // default to NOT wiping out the passwords 1592885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker needsProvisioning = true; 1593885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1594885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (needsProvisioning) { 1595885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker // if the phone needs re-provisioning, don't do anything. 1596885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker if (Log.isLoggable(TAG, Log.VERBOSE)) { 1597885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker Log.v(TAG, "current IMSI=" + imsi + " (needs provisioning); stored IMSI=" + 1598885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker storedImsi); 1599885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1600885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker return; 1601885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1602885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongker } 1603603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 16045b462477a90cd08551149fc649ff3035b5331d2djsh if (!imsi.equals(storedImsi) && !TextUtils.isEmpty(storedImsi)) { 160527844c386e5567a91ab781265ae5ad40d0ab1e27Jim Miller Log.w(TAG, "wiping all passwords and authtokens because IMSI changed (" 160627844c386e5567a91ab781265ae5ad40d0ab1e27Jim Miller + "stored=" + storedImsi + ", current=" + imsi + ")"); 1607603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1608603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.beginTransaction(); 1609603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana try { 1610603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.execSQL("DELETE from " + TABLE_AUTHTOKENS); 1611603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_PASSWORD + " = ''"); 16123326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana sendAccountsChangedBroadcast(); 1613603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.setTransactionSuccessful(); 1614603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } finally { 1615603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana db.endTransaction(); 1616603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1617603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1618603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana setMetaValue("imsi", imsi); 1619603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1620603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1621603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana 1622603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana public IBinder onBind(Intent intent) { 1623603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana return asBinder(); 1624603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana } 1625a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 16261cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks /** 16271cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks * Searches array of arguments for the specified string 16281cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks * @param args array of argument strings 16291cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks * @param value value to search for 16301cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks * @return true if the value is contained in the array 16311cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks */ 16321cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks private static boolean scanArgs(String[] args, String value) { 16331cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks if (args != null) { 16341cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks for (String arg : args) { 16351cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks if (value.equals(arg)) { 16361cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks return true; 16371cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 1638a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1639a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 16401cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks return false; 16411cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 1642a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 16431cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { 16441cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c"); 16451cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks 16461cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks if (isCheckinRequest) { 16471cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks // This is a checkin request. *Only* upload the account types and the count of each. 16481cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1649a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 16501cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION, 16511cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks null, null, ACCOUNTS_TYPE, null, null); 16521cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks try { 16531cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks while (cursor.moveToNext()) { 16541cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks // print type,count 16551cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks fout.println(cursor.getString(0) + "," + cursor.getString(1)); 16561cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 16571cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } finally { 16581cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks if (cursor != null) { 16591cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks cursor.close(); 16601cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 16611cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 16621cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } else { 1663307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana Account[] accounts = getAccounts(null /* type */); 1664307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana fout.println("Accounts: " + accounts.length); 1665307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana for (Account account : accounts) { 1666307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana fout.println(" " + account); 1667307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana } 1668307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana 1669307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana fout.println(); 16701cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks synchronized (mSessions) { 16711cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks final long now = SystemClock.elapsedRealtime(); 1672307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana fout.println("Active Sessions: " + mSessions.size()); 16731cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks for (Session session : mSessions.values()) { 16741cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks fout.println(" " + session.toDebugString(now)); 16751cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 16761cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 16771cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks 16781cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks fout.println(); 16791cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks mAuthenticatorCache.dump(fd, fout, args); 16801cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks } 1681a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1682a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1683d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void doNotification(Account account, CharSequence message, Intent intent) { 168426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 168526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 168626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 168726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana Log.v(TAG, "doNotification: " + message + " intent:" + intent); 168826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 1689a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1690d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (intent.getComponent() != null && 1691d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana GrantCredentialsPermissionActivity.class.getName().equals( 1692d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana intent.getComponent().getClassName())) { 1693d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana createNoCredentialsPermissionNotification(account, intent); 1694d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } else { 169533f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana final Integer notificationId = getSigninRequiredNotificationId(account); 169633f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana intent.addCategory(String.valueOf(notificationId)); 1697d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Notification n = new Notification(android.R.drawable.stat_sys_warning, null, 1698d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 0 /* when */); 169933f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana final String notificationTitleFormat = 170033f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana mContext.getText(R.string.notification_title).toString(); 170133f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana n.setLatestEventInfo(mContext, 170233f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana String.format(notificationTitleFormat, account.name), 1703d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana message, PendingIntent.getActivity( 1704d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT)); 1705d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)) 170633f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana .notify(notificationId, n); 1707d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 170826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 170926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 171026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 1711a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1712a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana 1713d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void cancelNotification(int id) { 171426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana long identityToken = clearCallingIdentity(); 171526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana try { 171626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE)) 1717d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana .cancel(id); 171826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } finally { 171926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana restoreCallingIdentity(identityToken); 172026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana } 1721a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana } 1722d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1723d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void checkBinderPermission(String permission) { 1724d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final int uid = Binder.getCallingUid(); 1725d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (mContext.checkCallingOrSelfPermission(permission) != 1726d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana PackageManager.PERMISSION_GRANTED) { 1727d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String msg = "caller uid " + uid + " lacks " + permission; 1728d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Log.w(TAG, msg); 1729d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana throw new SecurityException(msg); 1730d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1731d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1732d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Log.v(TAG, "caller uid " + uid + " has " + permission); 1733d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1734d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1735d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 17367be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana private boolean inSystemImage(int callerUid) { 17377be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid); 17387be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana for (String name : packages) { 17397be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana try { 17407be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana PackageInfo packageInfo = 17417be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana mContext.getPackageManager().getPackageInfo(name, 0 /* flags */); 17427be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 17437be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana return true; 17447be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana } 17457be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana } catch (PackageManager.NameNotFoundException e) { 17467be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana return false; 17477be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana } 17487be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana } 17497be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana return false; 17507be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana } 17517be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana 1752d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) { 1753b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana final boolean inSystemImage = inSystemImage(callerUid); 175431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana final boolean fromAuthenticator = account != null 175531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana && hasAuthenticatorUid(account.type, callerUid); 175631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana final boolean hasExplicitGrants = account != null 175731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana && hasExplicitlyGrantedPermission(account, authTokenType); 1758d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1759d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid " 1760d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + callerUid + ", account " + account 1761d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + ": is authenticator? " + fromAuthenticator 1762d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + ", has explicit permission? " + hasExplicitGrants); 1763d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1764b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana return fromAuthenticator || hasExplicitGrants || inSystemImage; 1765d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1766d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 17671a23191bbde11505d6e0c25c04a60b41cb27fd31Fred Quintana private boolean hasAuthenticatorUid(String accountType, int callingUid) { 1768d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo : 1769d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana mAuthenticatorCache.getAllServices()) { 1770d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (serviceInfo.type.type.equals(accountType)) { 1771ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana return (serviceInfo.uid == callingUid) || 1772ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana (mContext.getPackageManager().checkSignatures(serviceInfo.uid, callingUid) 1773ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana == PackageManager.SIGNATURE_MATCH); 1774d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1775d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1776d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return false; 1777d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1778d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1779d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType) { 1780d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (Binder.getCallingUid() == android.os.Process.SYSTEM_UID) { 1781d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return true; 1782d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1783d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana SQLiteDatabase db = mOpenHelper.getReadableDatabase(); 1784d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String[] args = {String.valueOf(Binder.getCallingUid()), authTokenType, 1785ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana account.name, account.type}; 1786d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final boolean permissionGranted = 1787d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0; 1788d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (!permissionGranted && isDebuggableMonkeyBuild) { 1789d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // TODO: Skip this check when running automated tests. Replace this 1790d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana // with a more general solution. 1791751fdc09bb7ab0ce6feac7b7a823e38ed858feb0Fred Quintana Log.d(TAG, "no credentials permission for usage of " + account + ", " 1792d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + authTokenType + " by uid " + Binder.getCallingUid() 1793d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + " but ignoring since this is a monkey build"); 1794d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return true; 1795d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1796d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana return permissionGranted; 1797d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1798d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1799d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void checkCallingUidAgainstAuthenticator(Account account) { 1800d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana final int uid = Binder.getCallingUid(); 180131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null || !hasAuthenticatorUid(account.type, uid)) { 1802d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String msg = "caller uid " + uid + " is different than the authenticator's uid"; 1803d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Log.w(TAG, msg); 1804d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana throw new SecurityException(msg); 1805d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1806d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (Log.isLoggable(TAG, Log.VERBOSE)) { 1807d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid"); 1808d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1809d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1810d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1811d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void checkAuthenticateAccountsPermission(Account account) { 1812d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkBinderPermission(Manifest.permission.AUTHENTICATE_ACCOUNTS); 1813d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkCallingUidAgainstAuthenticator(account); 1814d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1815d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1816d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void checkReadAccountsPermission() { 1817d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkBinderPermission(Manifest.permission.GET_ACCOUNTS); 1818d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1819d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1820d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana private void checkManageAccountsPermission() { 1821d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS); 1822d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1823d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1824d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana /** 1825d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * Allow callers with the given uid permission to get credentials for account/authTokenType. 1826d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * <p> 1827d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * Although this is public it can only be accessed via the AccountManagerService object 1828d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * which is in the system. This means we don't need to protect it with permissions. 1829d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * @hide 1830d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana */ 1831d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana public void grantAppPermission(Account account, String authTokenType, int uid) { 183231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null || authTokenType == null) { 183331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return; 183431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 1835d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1836d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.beginTransaction(); 1837d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana try { 1838d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana long accountId = getAccountId(db, account); 1839d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (accountId >= 0) { 1840d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana ContentValues values = new ContentValues(); 1841d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana values.put(GRANTS_ACCOUNTS_ID, accountId); 1842d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType); 1843d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana values.put(GRANTS_GRANTEE_UID, uid); 1844d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values); 1845d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.setTransactionSuccessful(); 1846d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1847d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } finally { 1848d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.endTransaction(); 1849d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1850d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid)); 1851d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1852d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana 1853d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana /** 1854d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * Don't allow callers with the given uid permission to get credentials for 1855d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * account/authTokenType. 1856d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * <p> 1857d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * Although this is public it can only be accessed via the AccountManagerService object 1858d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * which is in the system. This means we don't need to protect it with permissions. 1859d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana * @hide 1860d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana */ 1861d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana public void revokeAppPermission(Account account, String authTokenType, int uid) { 186231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana if (account == null || authTokenType == null) { 186331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana return; 186431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana } 1865d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana SQLiteDatabase db = mOpenHelper.getWritableDatabase(); 1866d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.beginTransaction(); 1867d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana try { 1868d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana long accountId = getAccountId(db, account); 1869d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana if (accountId >= 0) { 1870d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.delete(TABLE_GRANTS, 1871d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND " 1872d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana + GRANTS_GRANTEE_UID + "=?", 1873d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana new String[]{String.valueOf(accountId), authTokenType, 1874d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana String.valueOf(uid)}); 1875d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.setTransactionSuccessful(); 1876d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1877d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } finally { 1878d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana db.endTransaction(); 1879d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1880d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid)); 1881d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana } 1882603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana} 1883