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
177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.accounts;
18603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
19885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.Manifest;
207a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.Account;
217a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AccountAndUser;
227a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AccountAuthenticatorResponse;
237a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AccountManager;
247a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AuthenticatorDescription;
2523c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasaniimport android.accounts.CantAddAccountActivity;
267a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.GrantCredentialsPermissionActivity;
277a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountAuthenticator;
287a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountAuthenticatorResponse;
297a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountManager;
307a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountManagerResponse;
313b4fcbc9f13bab6a2e9e5c37cc5e18fec7341c04Brett Chabotimport android.app.ActivityManager;
326ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.app.ActivityManagerNative;
333b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasaniimport android.app.AppGlobals;
34885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.Notification;
35885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.NotificationManager;
36885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.PendingIntent;
37a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.BroadcastReceiver;
38885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.ComponentName;
39a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.ContentValues;
40a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Context;
41a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Intent;
42a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.IntentFilter;
43b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintanaimport android.content.ServiceConnection;
44885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.ApplicationInfo;
45885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.PackageInfo;
46d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.PackageManager;
476ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
48d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.RegisteredServicesCache;
493ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanaimport android.content.pm.RegisteredServicesCacheListener;
505bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdiviaimport android.content.pm.ResolveInfo;
516eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport android.content.pm.UserInfo;
52603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.Cursor;
53603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.DatabaseUtils;
54a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteDatabase;
55a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteOpenHelper;
56885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.os.Binder;
57a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Bundle;
58a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport android.os.Environment;
59a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Handler;
60a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.IBinder;
61a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Looper;
62a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Message;
63164371fb759bad6854570af0fca60d9a01e17235Dianne Hackbornimport android.os.Parcel;
6427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasaniimport android.os.Process;
65a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.RemoteException;
66a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.SystemClock;
67f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
68258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasaniimport android.os.UserManager;
69a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.text.TextUtils;
70a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.util.Log;
71d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.util.Pair;
726eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport android.util.Slog;
7304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasaniimport android.util.SparseArray;
74603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
75b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolacheimport com.android.internal.R;
7667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasaniimport com.android.internal.util.ArrayUtils;
7704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasaniimport com.android.internal.util.IndentingPrintWriter;
788d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackbornimport com.android.server.FgThread;
796ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Lists;
806ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Sets;
81b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
82a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport java.io.File;
83a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.FileDescriptor;
84a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.PrintWriter;
85a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.ArrayList;
8656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaimport java.util.Arrays;
87a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.Collection;
88d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.HashMap;
896ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport java.util.HashSet;
9056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaimport java.util.LinkedHashMap;
916eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport java.util.List;
922f36229db823d152f3efd879e751e81a601a75b0Andy McFaddenimport java.util.Map;
93d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicInteger;
94d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicReference;
95603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
96603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/**
97603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * A system service that provides  account, password, and authtoken management for all
98603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * accounts on the device. Some of these calls are implemented with the help of the corresponding
99603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * {@link IAccountAuthenticator} services. This service is not accessed by users directly,
100603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * instead one uses an instance of {@link AccountManager}, which can be accessed as follows:
10146703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom *    AccountManager accountManager = AccountManager.get(context);
1023326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana * @hide
103603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */
1043ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanapublic class AccountManagerService
1053ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana        extends IAccountManager.Stub
1065ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana        implements RegisteredServicesCacheListener<AuthenticatorDescription> {
107603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TAG = "AccountManagerService";
108603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
109603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final int TIMEOUT_DELAY_MS = 1000 * 60;
110603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String DATABASE_NAME = "accounts.db";
11167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private static final int DATABASE_VERSION = 5;
112603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
113603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private final Context mContext;
114603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
11556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private final PackageManager mPackageManager;
116258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    private UserManager mUserManager;
11756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
118603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private final MessageHandler mMessageHandler;
119603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
120603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    // Messages that can be sent on mHandler
121603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final int MESSAGE_TIMED_OUT = 3;
1225be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    private static final int MESSAGE_COPY_SHARED_ACCOUNT = 4;
123603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
12456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private final IAccountAuthenticatorCache mAuthenticatorCache;
125603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_ACCOUNTS = "accounts";
127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_ID = "_id";
128603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_NAME = "name";
129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_TYPE = "type";
1301cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static final String ACCOUNTS_TYPE_COUNT = "count(type)";
131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_PASSWORD = "password";
132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_AUTHTOKENS = "authtokens";
134603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_ID = "_id";
135603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_ACCOUNTS_ID = "accounts_id";
136603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_TYPE = "type";
137603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_AUTHTOKEN = "authtoken";
138603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
139d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String TABLE_GRANTS = "grants";
140d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_ACCOUNTS_ID = "accounts_id";
141d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_AUTH_TOKEN_TYPE = "auth_token_type";
142d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_GRANTEE_UID = "uid";
143d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
144603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_EXTRAS = "extras";
145603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_ID = "_id";
146603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_ACCOUNTS_ID = "accounts_id";
147603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_KEY = "key";
148603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_VALUE = "value";
149603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
150603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_META = "meta";
151603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String META_KEY = "key";
152603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String META_VALUE = "value";
153603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
15467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private static final String TABLE_SHARED_ACCOUNTS = "shared_accounts";
15567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
1561cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION =
1571cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks            new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT};
1587be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    private static final Intent ACCOUNTS_CHANGED_INTENT;
159a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
160d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String COUNT_OF_MATCHING_GRANTS = ""
161d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS
162d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " WHERE " + GRANTS_ACCOUNTS_ID + "=" + ACCOUNTS_ID
163d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + GRANTS_GRANTEE_UID + "=?"
164d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + GRANTS_AUTH_TOKEN_TYPE + "=?"
165d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + ACCOUNTS_NAME + "=?"
166d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + ACCOUNTS_TYPE + "=?";
167d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
16856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String SELECTION_AUTHTOKENS_BY_ACCOUNT =
16956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
17056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN = {AUTHTOKENS_TYPE,
17156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            AUTHTOKENS_AUTHTOKEN};
17256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
17356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String SELECTION_USERDATA_BY_ACCOUNT =
17456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            EXTRAS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
17556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String[] COLUMNS_EXTRAS_KEY_AND_VALUE = {EXTRAS_KEY, EXTRAS_VALUE};
17656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
177a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
178d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private final AtomicInteger mNotificationIds = new AtomicInteger(1);
179d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
18004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    static class UserAccounts {
18104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final int userId;
18204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final DatabaseHelper openHelper;
18304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
18404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                credentialsPermissionNotificationIds =
18504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
18604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final HashMap<Account, Integer> signinRequiredNotificationIds =
18704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, Integer>();
18804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final Object cacheLock = new Object();
18904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
190b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani        private final HashMap<String, Account[]> accountCache =
191b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani                new LinkedHashMap<String, Account[]>();
19204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
19309e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        private final HashMap<Account, HashMap<String, String>> userDataCache =
19404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, HashMap<String, String>>();
19504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
19609e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        private final HashMap<Account, HashMap<String, String>> authTokenCache =
19704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, HashMap<String, String>>();
19804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
19904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts(Context context, int userId) {
20004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            this.userId = userId;
20104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (cacheLock) {
20204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                openHelper = new DatabaseHelper(context, userId);
20304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
20404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
20504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
20604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
20704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private final SparseArray<UserAccounts> mUsers = new SparseArray<UserAccounts>();
20804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
209d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static AtomicReference<AccountManagerService> sThis =
210d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            new AtomicReference<AccountManagerService>();
21131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana    private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
2127be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
2137be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    static {
214f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana        ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
2157be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2167be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    }
2177be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
21856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
219d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
220d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * This should only be called by system code. One should only call this after the service
221d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * has started.
222d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @return a reference to the AccountManagerService instance
223d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
224d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
225d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    public static AccountManagerService getSingleton() {
226d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return sThis.get();
227d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
228603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
22956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    public AccountManagerService(Context context) {
23056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        this(context, context.getPackageManager(), new AccountAuthenticatorCache(context));
231603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
232603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
23356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    public AccountManagerService(Context context, PackageManager packageManager,
23456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            IAccountAuthenticatorCache authenticatorCache) {
235603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mContext = context;
23656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mPackageManager = packageManager;
237603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2388d044e8bc287c1a567d82aedbe30085b011544c3Dianne Hackborn        mMessageHandler = new MessageHandler(FgThread.get().getLooper());
239603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
24056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mAuthenticatorCache = authenticatorCache;
2415ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana        mAuthenticatorCache.setListener(this, null /* Handler */);
242603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
243d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        sThis.set(this);
244afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana
245c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        IntentFilter intentFilter = new IntentFilter();
246c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
247c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        intentFilter.addDataScheme("package");
248c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        mContext.registerReceiver(new BroadcastReceiver() {
249c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            @Override
250c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            public void onReceive(Context context1, Intent intent) {
25104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrantsAll();
252c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            }
253c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        }, intentFilter);
254c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana
255135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        IntentFilter userFilter = new IntentFilter();
256135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        userFilter.addAction(Intent.ACTION_USER_REMOVED);
25767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userFilter.addAction(Intent.ACTION_USER_STARTED);
25867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        mContext.registerReceiverAsUser(new BroadcastReceiver() {
259135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            @Override
260135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            public void onReceive(Context context, Intent intent) {
26167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                String action = intent.getAction();
26267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                if (Intent.ACTION_USER_REMOVED.equals(action)) {
26367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    onUserRemoved(intent);
26467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } else if (Intent.ACTION_USER_STARTED.equals(action)) {
26567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    onUserStarted(intent);
26667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
267135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            }
26867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }, UserHandle.ALL, userFilter, null, null);
269afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana    }
270afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana
271164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn    @Override
272164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
273164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            throws RemoteException {
274164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn        try {
275164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            return super.onTransact(code, data, reply, flags);
276164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn        } catch (RuntimeException e) {
277164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            // The account manager only throws security exceptions, so let's
278164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            // log all others.
279164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            if (!(e instanceof SecurityException)) {
280164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Account Manager Crash", e);
281164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            }
282164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn            throw e;
283164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn        }
284164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn    }
285164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn
28626ff6626fc4ee0ae46f01ad309b366921da589feKenny Root    public void systemReady() {
28726ff6626fc4ee0ae46f01ad309b366921da589feKenny Root    }
28826ff6626fc4ee0ae46f01ad309b366921da589feKenny Root
289258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    private UserManager getUserManager() {
290258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        if (mUserManager == null) {
29127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            mUserManager = UserManager.get(mContext);
292258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        }
293258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        return mUserManager;
294258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    }
295258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani
2960c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani    /* Caller should lock mUsers */
2970c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani    private UserAccounts initUserLocked(int userId) {
2980c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani        UserAccounts accounts = mUsers.get(userId);
2990c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani        if (accounts == null) {
3000c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            accounts = new UserAccounts(mContext, userId);
3010c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            mUsers.append(userId, accounts);
3020c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            purgeOldGrants(accounts);
3030c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
30404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
3050c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani        return accounts;
30604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
30704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
30804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void purgeOldGrantsAll() {
30904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
31004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (int i = 0; i < mUsers.size(); i++) {
31104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrants(mUsers.valueAt(i));
31204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
31304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
31404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
31504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
31604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void purgeOldGrants(UserAccounts accounts) {
31704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
31804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
319c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            final Cursor cursor = db.query(TABLE_GRANTS,
320c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    new String[]{GRANTS_GRANTEE_UID},
321c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    null, null, GRANTS_GRANTEE_UID, null, null);
322c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            try {
323c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                while (cursor.moveToNext()) {
324c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    final int uid = cursor.getInt(0);
325c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
326c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    if (packageExists) {
327c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                        continue;
328c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    }
329c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    Log.d(TAG, "deleting grants for UID " + uid
330c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                            + " because its package is no longer installed");
331c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
332c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                            new String[]{Integer.toString(uid)});
333c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                }
334c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            } finally {
335c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                cursor.close();
336c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            }
337c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        }
338c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana    }
339c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana
3406eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /**
3416eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * Validate internal set of accounts against installed authenticators for
3426eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * given user. Clears cached authenticators before validating.
3436eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     */
3446eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    public void validateAccounts(int userId) {
3456eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final UserAccounts accounts = getUserAccounts(userId);
3466eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3476eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        // Invalidate user-specific cache to make sure we catch any
3486eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        // removed authenticators.
3496eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
3506eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
3516eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3526eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /**
3536eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * Validate internal set of accounts against installed authenticators for
3546eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * given user. Clear cached authenticators before validating when requested.
3556eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     */
3566eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    private void validateAccountsInternal(
3576eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            UserAccounts accounts, boolean invalidateAuthenticatorCache) {
3586eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        if (invalidateAuthenticatorCache) {
3596eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            mAuthenticatorCache.invalidateCache(accounts.userId);
3606eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        }
3616eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3626ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
3636ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
3646ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.getAllServices(accounts.userId)) {
3656ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            knownAuth.add(service.type);
3666ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
3676ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
36804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
36904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
370f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            boolean accountDeleted = false;
371f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Cursor cursor = db.query(TABLE_ACCOUNTS,
372f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
373f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    null, null, null, null, null);
374f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
37504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.clear();
37656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final HashMap<String, ArrayList<String>> accountNamesByType =
377b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani                        new LinkedHashMap<String, ArrayList<String>>();
37856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                while (cursor.moveToNext()) {
37956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final long accountId = cursor.getLong(0);
38056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountType = cursor.getString(1);
38156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountName = cursor.getString(2);
3826ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
3836ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
3846eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey                        Slog.w(TAG, "deleting account " + accountName + " because type "
38556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + accountType + " no longer has a registered authenticator");
38656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
38756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountDeleted = true;
38856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        final Account account = new Account(accountName, accountType);
38904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        accounts.userDataCache.remove(account);
39004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        accounts.authTokenCache.remove(account);
39156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    } else {
39256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        ArrayList<String> accountNames = accountNamesByType.get(accountType);
39356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (accountNames == null) {
39456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            accountNames = new ArrayList<String>();
39556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            accountNamesByType.put(accountType, accountNames);
39656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
39756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountNames.add(accountName);
39856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
39956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                }
4002f36229db823d152f3efd879e751e81a601a75b0Andy McFadden                for (Map.Entry<String, ArrayList<String>> cur
401f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        : accountNamesByType.entrySet()) {
40256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountType = cur.getKey();
40356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final ArrayList<String> accountNames = cur.getValue();
40456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final Account[] accountsForType = new Account[accountNames.size()];
40556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    int i = 0;
40656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    for (String accountName : accountNames) {
40756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountsForType[i] = new Account(accountName, accountType);
40856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        ++i;
40956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
41004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    accounts.accountCache.put(accountType, accountsForType);
411afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana                }
412f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
413f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                cursor.close();
414f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountDeleted) {
41504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    sendAccountsChangedBroadcast(accounts.userId);
416f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
417afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana            }
418afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana        }
4193ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana    }
4203ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana
42104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private UserAccounts getUserAccountsForCaller() {
422f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getUserAccounts(UserHandle.getCallingUserId());
42304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
42404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
42504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected UserAccounts getUserAccounts(int userId) {
42604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
42704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            UserAccounts accounts = mUsers.get(userId);
42804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            if (accounts == null) {
4290c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani                accounts = initUserLocked(userId);
43004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                mUsers.append(userId, accounts);
43104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
43204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return accounts;
43304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
43404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
43504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
436135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    private void onUserRemoved(Intent intent) {
4372a00329c6d55c6cd9166e01963d7410e95d80d21Amith Yamasani        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
438135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        if (userId < 1) return;
439135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
440135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        UserAccounts accounts;
441135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        synchronized (mUsers) {
442135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            accounts = mUsers.get(userId);
443135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            mUsers.remove(userId);
444135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
445135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        if (accounts == null) {
446135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            File dbFile = new File(getDatabaseName(userId));
447135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            dbFile.delete();
448135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            return;
449135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
450135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
451135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        synchronized (accounts.cacheLock) {
452135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            accounts.openHelper.close();
453135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            File dbFile = new File(getDatabaseName(userId));
454135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            dbFile.delete();
455135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
456135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    }
457135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
45867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private void onUserStarted(Intent intent) {
45967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
46067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (userId < 1) return;
46167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
46267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        // Check if there's a shared account that needs to be created as an account
46367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] sharedAccounts = getSharedAccountsAsUser(userId);
46467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (sharedAccounts == null || sharedAccounts.length == 0) return;
46567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] accounts = getAccountsAsUser(null, userId);
46667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        for (Account sa : sharedAccounts) {
46767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (ArrayUtils.contains(accounts, sa)) continue;
46867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Account doesn't exist. Copy it now.
46967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            copyAccountToUser(sa, UserHandle.USER_OWNER, userId);
47067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
47167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
47267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
4736ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    @Override
4746ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    public void onServiceChanged(AuthenticatorDescription desc, int userId, boolean removed) {
4756eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        validateAccountsInternal(getUserAccounts(userId), false /* invalidateAuthenticatorCache */);
476603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
477603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
47809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
479a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String getPassword(Account account) {
48056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
48156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getPassword: " + account
48256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
48356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
48456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
485382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
486d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
487d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
48804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
48926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
490603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
49104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readPasswordInternal(accounts, account);
492603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
49326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
494603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
495603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
496603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
49704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private String readPasswordInternal(UserAccounts accounts, Account account) {
49831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null) {
49931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return null;
50031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
50131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana
50204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
50304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
504f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
505f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
506f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{account.name, account.type}, null, null, null);
507f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
508f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (cursor.moveToNext()) {
509f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return cursor.getString(0);
510f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
511f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return null;
512f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
513f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                cursor.close();
514ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
515ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
516ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
517ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
51809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
519a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String getUserData(Account account, String key) {
52056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
52156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getUserData: " + account
52256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", key " + key
52356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
52456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
52556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
526382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
527382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (key == null) throw new IllegalArgumentException("key is null");
528d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
52904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
53026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
531603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
53204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readUserDataInternal(accounts, account, key);
533ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
534ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
535ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
536ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
537ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
53809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
5399788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana    public AuthenticatorDescription[] getAuthenticatorTypes() {
54056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
54156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAuthenticatorTypes: "
54256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + "caller's uid " + Binder.getCallingUid()
54356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
54456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
5456ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int userId = UserHandle.getCallingUserId();
5466ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final long identityToken = clearCallingIdentity();
54726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
5489788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
5496ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
5509788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            AuthenticatorDescription[] types =
5519788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana                    new AuthenticatorDescription[authenticatorCollection.size()];
55226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            int i = 0;
5539788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
554718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana                    : authenticatorCollection) {
555718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana                types[i] = authenticator.type;
55626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                i++;
55726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
55826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            return types;
55926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
56026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
561a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
562a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
563a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
5643df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia    @Override
56527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
56656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
56727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            Log.v(TAG, "addAccountExplicitly: " + account
56856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
56956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
57056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
571382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
572d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
5733df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia        /*
5743df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * Child users are not allowed to add accounts. Only the accounts that are
5753df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * shared by the parent profile can be added to child profile.
5763df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         *
5773df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * TODO: Only allow accounts that were shared to be added by
5783df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         *     a limited user.
5793df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         */
580d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
58104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
582603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        // fails if the account already exists
58326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
584603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
58567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return addAccountInternal(accounts, account, password, extras, false);
58667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
58767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            restoreCallingIdentity(identityToken);
58867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
58967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
59067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
59167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private boolean copyAccountToUser(final Account account, int userFrom, int userTo) {
59267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        final UserAccounts fromAccounts = getUserAccounts(userFrom);
59367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        final UserAccounts toAccounts = getUserAccounts(userTo);
59467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (fromAccounts == null || toAccounts == null) {
59567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return false;
59667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
59767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
59867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long identityToken = clearCallingIdentity();
59967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
60067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            new Session(fromAccounts, null, account.type, false,
60167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    false /* stripAuthTokenFromResult */) {
6025bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
60367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                protected String toDebugString(long now) {
60467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    return super.toDebugString(now) + ", getAccountCredentialsForClone"
60567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            + ", " + account.type;
60667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
60767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
6085bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
60967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void run() throws RemoteException {
61067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mAuthenticator.getAccountCredentialsForCloning(this, account);
61167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
61267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
6135bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
61467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onResult(Bundle result) {
61567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (result != null) {
61667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
61767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // Create a Session for the target user and pass in the bundle
61867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            completeCloningAccount(result, account, toAccounts);
61967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        }
62067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        return;
62167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    } else {
62267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        super.onResult(result);
62367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
62467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
62567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }.bind();
626ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
627ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
628ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
62967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return true;
63067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
63167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
63267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    void completeCloningAccount(final Bundle result, final Account account,
63367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            final UserAccounts targetUser) {
63467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long id = clearCallingIdentity();
63567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
63667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            new Session(targetUser, null, account.type, false,
63767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    false /* stripAuthTokenFromResult */) {
6385bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
63967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                protected String toDebugString(long now) {
64067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    return super.toDebugString(now) + ", getAccountCredentialsForClone"
64167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            + ", " + account.type;
64267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
64367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
6445bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
64567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void run() throws RemoteException {
6465be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    // Confirm that the owner's account still exists before this step.
6475be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
6485be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    synchronized (owner.cacheLock) {
6495be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        Account[] ownerAccounts = getAccounts(UserHandle.USER_OWNER);
6505be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        for (Account acc : ownerAccounts) {
6515be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                            if (acc.equals(account)) {
6525be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                mAuthenticator.addAccountFromCredentials(this, account, result);
6535be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                break;
6545be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                            }
6555be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        }
6565be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    }
65767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
65867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
6595bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
66067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onResult(Bundle result) {
66167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (result != null) {
66267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
66367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Anything?
66467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        } else {
66567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Show error notification
66667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Should we remove the shadow account to avoid retries?
66767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        }
66867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        return;
66967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    } else {
67067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        super.onResult(result);
67167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
67267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
67367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
6745bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
67567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onError(int errorCode, String errorMessage) {
67667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    super.onError(errorCode,  errorMessage);
67767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    // TODO: Show error notification to user
67867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    // TODO: Should we remove the shadow account so that it doesn't keep trying?
67967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
68067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
68167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }.bind();
68267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
68367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            restoreCallingIdentity(id);
68467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
685ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
686ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
68704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
68867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            Bundle extras, boolean restricted) {
689743dfad2a51e016ddb741c104317637089187753Fred Quintana        if (account == null) {
690743dfad2a51e016ddb741c104317637089187753Fred Quintana            return false;
691743dfad2a51e016ddb741c104317637089187753Fred Quintana        }
69204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
69304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
694f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
695f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
696f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long numMatches = DatabaseUtils.longForQuery(db,
697f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        "select count(*) from " + TABLE_ACCOUNTS
698f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
699f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        new String[]{account.name, account.type});
700f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (numMatches > 0) {
701f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    Log.w(TAG, "insertAccountIntoDatabase: " + account
702f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            + ", skipping since the account already exists");
703f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
704f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
705f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                ContentValues values = new ContentValues();
706f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_NAME, account.name);
707f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_TYPE, account.type);
708f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_PASSWORD, password);
709f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
710f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
711f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    Log.w(TAG, "insertAccountIntoDatabase: " + account
712f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            + ", skipping the DB insert failed");
713f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
714f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
715f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (extras != null) {
716f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    for (String key : extras.keySet()) {
717f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        final String value = extras.getString(key);
718f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        if (insertExtraLocked(db, accountId, key, value) < 0) {
719f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            Log.w(TAG, "insertAccountIntoDatabase: " + account
720f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    + ", skipping since insertExtra failed for key " + key);
721f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            return false;
722f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        }
723603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    }
724603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                }
725f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.setTransactionSuccessful();
72604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                insertAccountIntoCacheLocked(accounts, account);
727f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
728f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
729603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
73004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
7315be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        }
7325be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        if (accounts.userId == UserHandle.USER_OWNER) {
7335be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani            addAccountToLimitedUsers(account);
7345be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        }
7355be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        return true;
7365be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    }
7375be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani
7385be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    /**
7395be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     * Adds the account to all limited users as shared accounts. If the user is currently
7405be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     * running, then clone the account too.
7415be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     * @param account the account to share with limited users
7425be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     */
7435be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    private void addAccountToLimitedUsers(Account account) {
744f4c240e68a3da9f1ebf42267c88af40c19ff49daMita Yun        List<UserInfo> users = getUserManager().getUsers();
7455be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        for (UserInfo user : users) {
7465be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani            if (user.isRestricted()) {
7475be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                addSharedAccountAsUser(account, user.id);
7485be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                try {
7495be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    if (ActivityManagerNative.getDefault().isUserRunning(user.id, false)) {
7505be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
7515be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                MESSAGE_COPY_SHARED_ACCOUNT, UserHandle.USER_OWNER, user.id,
7525be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                account));
7535be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    }
7545be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                } catch (RemoteException re) {
7555be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    // Shouldn't happen
7565be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                }
7575be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani            }
758603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
759603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
760603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
761f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long insertExtraLocked(SQLiteDatabase db, long accountId, String key, String value) {
762603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        ContentValues values = new ContentValues();
763603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_KEY, key);
764603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_ACCOUNTS_ID, accountId);
765603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_VALUE, value);
766603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values);
767603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
768603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
76909e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
7703084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana    public void hasFeatures(IAccountManagerResponse response,
771bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            Account account, String[] features) {
77256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
77356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "hasFeatures: " + account
77456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
77556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", features " + stringArrayToString(features)
77656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
77756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
77856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
779382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
780382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
781382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (features == null) throw new IllegalArgumentException("features is null");
782bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        checkReadAccountsPermission();
78304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
784bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        long identityToken = clearCallingIdentity();
785bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        try {
78604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new TestFeaturesSession(accounts, response, account, features).bind();
787bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        } finally {
788bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            restoreCallingIdentity(identityToken);
789bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
790bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    }
791bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
792bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    private class TestFeaturesSession extends Session {
793bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        private final String[] mFeatures;
794bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        private final Account mAccount;
795bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
79604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public TestFeaturesSession(UserAccounts accounts, IAccountManagerResponse response,
797bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                Account account, String[] features) {
79804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, account.type, false /* expectActivityLaunch */,
7998570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
800bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            mFeatures = features;
801bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            mAccount = account;
802bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
803bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
8045bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
805bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        public void run() throws RemoteException {
806bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            try {
807bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                mAuthenticator.hasFeatures(this, mAccount, mFeatures);
808bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            } catch (RemoteException e) {
809bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
810bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            }
811bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
812bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
8135bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
814bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        public void onResult(Bundle result) {
815bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
816bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            if (response != null) {
817bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                try {
818bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    if (result == null) {
819166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
820bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                        return;
821bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    }
82256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
82356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
82456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
82556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
826bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    final Bundle newResult = new Bundle();
827bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    newResult.putBoolean(AccountManager.KEY_BOOLEAN_RESULT,
828bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                            result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false));
829bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    response.onResult(newResult);
830bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                } catch (RemoteException e) {
831bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
832bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
833bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
834bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    }
835bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                }
836bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            }
837bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
838bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
8395bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
840bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        protected String toDebugString(long now) {
8413084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana            return super.toDebugString(now) + ", hasFeatures"
842bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    + ", " + mAccount
843bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
844bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
845bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    }
846307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
84709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
848ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    public void removeAccount(IAccountManagerResponse response, Account account) {
84956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
85056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "removeAccount: " + account
85156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
85256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
85356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
85456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
855382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
856382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
857d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
85850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        UserHandle user = Binder.getCallingUserHandle();
85904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
860e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        if (!canUserModifyAccounts(Binder.getCallingUid())) {
861e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            try {
862e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
863e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                        "User cannot modify accounts");
864e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            } catch (RemoteException re) {
865e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            }
866e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        }
867e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani
86826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
869ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache
87050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
87104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized(accounts.credentialsPermissionNotificationIds) {
872ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache            for (Pair<Pair<Account, String>, Integer> pair:
87304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.credentialsPermissionNotificationIds.keySet()) {
874ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache                if (account.equals(pair.first.first)) {
87504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    int id = accounts.credentialsPermissionNotificationIds.get(pair);
87650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    cancelNotification(id, user);
877ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache                }
878ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache            }
879ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache        }
880ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache
88126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
88204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new RemoveAccountSession(accounts, response, account).bind();
88326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
88426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
885a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
886603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
887603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
888ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    private class RemoveAccountSession extends Session {
889ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        final Account mAccount;
89004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response,
89104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                Account account) {
89204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, account.type, false /* expectActivityLaunch */,
8938570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
894ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            mAccount = account;
895ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
896ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
8975bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
898ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        protected String toDebugString(long now) {
899ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            return super.toDebugString(now) + ", removeAccount"
900ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    + ", account " + mAccount;
901ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
902ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
9035bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
904ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        public void run() throws RemoteException {
905ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            mAuthenticator.getAccountRemovalAllowed(this, mAccount);
906ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
907ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
9085bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
909ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        public void onResult(Bundle result) {
910f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
911f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    && !result.containsKey(AccountManager.KEY_INTENT)) {
912f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
913ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                if (removalAllowed) {
91404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    removeAccountInternal(mAccounts, mAccount);
915ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                }
916ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                IAccountManagerResponse response = getResponseAndClose();
917ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                if (response != null) {
91856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
91956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
92056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
92156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
922ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    Bundle result2 = new Bundle();
923f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result2.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, removalAllowed);
924ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    try {
925ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                        response.onResult(result2);
926ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    } catch (RemoteException e) {
927ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                        // ignore
928ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    }
929ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                }
930ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
931ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            super.onResult(result);
932ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
933ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
934ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
93504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    /* For testing */
936f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected void removeAccountInternal(Account account) {
93704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        removeAccountInternal(getUserAccountsForCaller(), account);
93804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
93904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
94004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAccountInternal(UserAccounts accounts, Account account) {
94104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
94204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
943f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
944f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{account.name, account.type});
94504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            removeAccountFromCacheLocked(accounts, account);
94604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
947f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
94867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (accounts.userId == UserHandle.USER_OWNER) {
94967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Owner's account was removed, remove from any users that are sharing
95067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // this account.
95167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            long id = Binder.clearCallingIdentity();
95267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            try {
95367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                List<UserInfo> users = mUserManager.getUsers(true);
95467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                for (UserInfo user : users) {
95567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (!user.isPrimary() && user.isRestricted()) {
95667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        removeSharedAccountAsUser(account, user.id);
95767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
95867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
95967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            } finally {
96067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                Binder.restoreCallingIdentity(id);
96167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
96267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
963ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
964ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
965a12fccf57d5ec289793699d9b22ff45daccd3933Maggie Benthall    @Override
966a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void invalidateAuthToken(String accountType, String authToken) {
96756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
96856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "invalidateAuthToken: accountType " + accountType
96956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
97056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
97156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
972382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
973382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authToken == null) throw new IllegalArgumentException("authToken is null");
974b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        checkManageAccountsOrUseCredentialsPermissions();
97504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
97626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
977603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
97804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
97904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
980f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.beginTransaction();
981f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                try {
98204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    invalidateAuthTokenLocked(accounts, db, accountType, authToken);
983f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
984f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } finally {
985f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.endTransaction();
986f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
98726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
988603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
98926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
990603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
991603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
992603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
99304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db,
99404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String accountType, String authToken) {
995ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        if (authToken == null || accountType == null) {
996ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            return;
997ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
9983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        Cursor cursor = db.rawQuery(
9993326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                "SELECT " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID
10003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME
10013326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + ", " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_TYPE
10023326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " FROM " + TABLE_ACCOUNTS
10033326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " JOIN " + TABLE_AUTHTOKENS
10043326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " ON " + TABLE_ACCOUNTS + "." + ACCOUNTS_ID
10053326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " = " + AUTHTOKENS_ACCOUNTS_ID
10063326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " WHERE " + AUTHTOKENS_AUTHTOKEN + " = ? AND "
10073326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " = ?",
10083326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                new String[]{authToken, accountType});
10093326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        try {
10103326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            while (cursor.moveToNext()) {
10113326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                long authTokenId = cursor.getLong(0);
10123326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                String accountName = cursor.getString(1);
10133326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                String authTokenType = cursor.getString(2);
10143326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null);
101504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                writeAuthTokenIntoCacheLocked(accounts, db, new Account(accountName, accountType),
1016f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        authTokenType, null);
1017603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
10183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        } finally {
10193326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            cursor.close();
1020603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1021603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1022603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
102304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean saveAuthTokenToDatabase(UserAccounts accounts, Account account, String type,
102404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String authToken) {
102531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || type == null) {
102631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return false;
102731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
102850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        cancelNotification(getSigninRequiredNotificationId(accounts, account),
102950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                new UserHandle(accounts.userId));
103004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
103104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1032f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1033f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1034f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
1035f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
1036f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
1037f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
1038f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.delete(TABLE_AUTHTOKENS,
1039f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
1040f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        new String[]{type});
1041f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                ContentValues values = new ContentValues();
1042f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
1043f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_TYPE, type);
1044f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_AUTHTOKEN, authToken);
1045f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (db.insert(TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values) >= 0) {
1046f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
104704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    writeAuthTokenIntoCacheLocked(accounts, db, account, type, authToken);
1048f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return true;
1049f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
10503326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return false;
1051f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1052f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
10533326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
1054603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1055603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1056603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
105709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1058a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String peekAuthToken(Account account, String authTokenType) {
105956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
106056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "peekAuthToken: " + account
106156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
106256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
106356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
106456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1065382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1066382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1067d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
106804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
106926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
107026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
107104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readAuthTokenInternal(accounts, account, authTokenType);
107226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
107326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
1074603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1075603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1076603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
107709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1078a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setAuthToken(Account account, String authTokenType, String authToken) {
107956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
108056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setAuthToken: " + account
108156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
108256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
108356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
108456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1085382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1086382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1087d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
108804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
108926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
109026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
109104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            saveAuthTokenToDatabase(accounts, account, authTokenType, authToken);
109226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
109326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
109426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1095603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1096603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
109709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1098a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setPassword(Account account, String password) {
109956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
110056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setAuthToken: " + account
110156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
110256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
110356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1104382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1105d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
110604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
110726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
110826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
110904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setPasswordInternal(accounts, account, password);
111026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
111126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
111226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1113603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1114603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
111504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void setPasswordInternal(UserAccounts accounts, Account account, String password) {
111631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null) {
111731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
111831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
111904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
112004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1121f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1122f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1123f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                final ContentValues values = new ContentValues();
1124f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_PASSWORD, password);
1125f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                final long accountId = getAccountIdLocked(db, account);
1126f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
1127f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    final String[] argsAccountId = {String.valueOf(accountId)};
1128f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
1129f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
113004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    accounts.authTokenCache.remove(account);
1131f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
1132f5ffe89e736caee1419f0acb469565d5100b8fb8Costin Manolache                }
1133f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1134f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
1135d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana            }
113604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
1137d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana        }
11383ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana    }
11393ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana
114004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void sendAccountsChangedBroadcast(int userId) {
114156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Log.i(TAG, "the accounts changed, sending broadcast of "
114256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                + ACCOUNTS_CHANGED_INTENT.getAction());
114379af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
11443326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
11453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
114609e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1147a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void clearPassword(Account account) {
114856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
114956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "clearPassword: " + account
115056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
115156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
115256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1153382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1154d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
115504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
115626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
115726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
115804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setPasswordInternal(accounts, account, null);
115926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
116026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
116126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1162603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1163603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
116409e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1165a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setUserData(Account account, String key, String value) {
116656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
116756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setUserData: " + account
116856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", key " + key
116956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
117056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
117156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1172382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (key == null) throw new IllegalArgumentException("key is null");
1173382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1174d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
117504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
117626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
1177603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
117804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setUserdataInternal(accounts, account, key, value);
1179ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
1180ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
1181ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
1182ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
1183ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
118404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void setUserdataInternal(UserAccounts accounts, Account account, String key,
118504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String value) {
118631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || key == null) {
118731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
118831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
118904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
119004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1191f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1192f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1193f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
1194f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
1195ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    return;
119626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1197f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long extrasId = getExtrasIdLocked(db, accountId, key);
1198f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (extrasId < 0 ) {
1199f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    extrasId = insertExtraLocked(db, accountId, key, value);
1200f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (extrasId < 0) {
1201f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        return;
1202f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
1203f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } else {
1204f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ContentValues values = new ContentValues();
1205f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(EXTRAS_VALUE, value);
1206f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
1207f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        return;
1208f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
1209ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
1210f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
121104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                writeUserDataIntoCacheLocked(accounts, db, account, key, value);
1212f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.setTransactionSuccessful();
1213f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1214f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
1215603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1216603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1217603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1218603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1219d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void onResult(IAccountManagerResponse response, Bundle result) {
122056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (result == null) {
122156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.e(TAG, "the result is unexpectedly null", new Exception());
122256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
122356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
122456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
122556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + response);
122656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1227d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        try {
1228d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            response.onResult(result);
1229d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        } catch (RemoteException e) {
1230d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // if the caller is dead then there is no one to care about remote
1231d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // exceptions
1232d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1233d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                Log.v(TAG, "failure while notifying response", e);
1234d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1235d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1236d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1237d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
123809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1239d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType,
1240d9640ec712806508877868d08aafaa2d715ff441Fred Quintana                                  final String authTokenType)
1241d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throws RemoteException {
1242d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
12435f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
12445f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1245d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        final int callingUid = getCallingUid();
1246d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        clearCallingIdentity();
124727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callingUid != Process.SYSTEM_UID) {
1248d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throw new SecurityException("can only call from system");
1249d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
1250f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
12515f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        long identityToken = clearCallingIdentity();
12525f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        try {
1253d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            new Session(accounts, response, accountType, false,
12545f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    false /* stripAuthTokenFromResult */) {
12555bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
12565f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                protected String toDebugString(long now) {
12575f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    return super.toDebugString(now) + ", getAuthTokenLabel"
1258d9640ec712806508877868d08aafaa2d715ff441Fred Quintana                            + ", " + accountType
12595f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                            + ", authTokenType " + authTokenType;
12605f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
12615f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
12625bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
12635f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                public void run() throws RemoteException {
12645f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    mAuthenticator.getAuthTokenLabel(this, authTokenType);
12655f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
12665f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
12675bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
12685f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                public void onResult(Bundle result) {
12695f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    if (result != null) {
12705f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
12715f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        Bundle bundle = new Bundle();
12725f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, label);
12735f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        super.onResult(bundle);
12745f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        return;
12755f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    } else {
12765f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        super.onResult(result);
12775f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    }
12785f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
12795f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            }.bind();
12805f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        } finally {
12815f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            restoreCallingIdentity(identityToken);
12825f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        }
12835f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache    }
12845f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
128509e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1286a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void getAuthToken(IAccountManagerResponse response, final Account account,
1287a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final String authTokenType, final boolean notifyOnAuthFailure,
1288c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache            final boolean expectActivityLaunch, Bundle loginOptionsIn) {
128956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
129056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAuthToken: " + account
129156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
129256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
129356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", notifyOnAuthFailure " + notifyOnAuthFailure
129456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
129556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
129656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
129756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1298382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
129909e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        try {
130009e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia            if (account == null) {
130109e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                Slog.w(TAG, "getAuthToken called with null account");
130209e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "account is null");
130309e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                return;
130409e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia            }
130509e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia            if (authTokenType == null) {
130609e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                Slog.w(TAG, "getAuthToken called with null authTokenType");
130709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "authTokenType is null");
130809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                return;
130909e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia            }
131009e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        } catch (RemoteException e) {
131109e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia            Slog.w(TAG, "Failed to report error back to the client." + e);
131209e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia            return;
131309e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        }
131409e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia
1315d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
13164120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        final UserAccounts accounts = getUserAccountsForCaller();
13176ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
13186ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        authenticatorInfo = mAuthenticatorCache.getServiceInfo(
13196ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                AuthenticatorDescription.newKey(account.type), accounts.userId);
1320a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        final boolean customTokens =
1321a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            authenticatorInfo != null && authenticatorInfo.type.customTokens;
1322a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache
1323a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        // skip the check if customTokens
1324b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int callerUid = Binder.getCallingUid();
1325a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        final boolean permissionGranted = customTokens ||
1326a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            permissionIsGranted(account, authTokenType, callerUid);
1327a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache
1328c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache        final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
1329c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache            loginOptionsIn;
1330b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        // let authenticator know the identity of the caller
1331b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
1332b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
1333b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        if (notifyOnAuthFailure) {
1334b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache            loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
1335a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        }
13366ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
133726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
133826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
1339d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // if the caller has permission, do the peek. otherwise go the more expensive
1340d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // route of starting a Session
1341a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            if (!customTokens && permissionGranted) {
134204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                String authToken = readAuthTokenInternal(accounts, account, authTokenType);
1343d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                if (authToken != null) {
134426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    Bundle result = new Bundle();
1345f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
1346f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
1347f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
1348d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    onResult(response, result);
1349d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    return;
1350a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
1351a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1352603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
135304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
13548570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    false /* stripAuthTokenFromResult */) {
13555bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
135626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
135726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (loginOptions != null) loginOptions.keySet();
135826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", getAuthToken"
135926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account
136026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", authTokenType " + authTokenType
136126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", loginOptions " + loginOptions
136226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", notifyOnAuthFailure " + notifyOnAuthFailure;
136326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1364a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
13655bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
136626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
1367d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    // If the caller doesn't have permission then create and return the
1368d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    // "grant permission" intent instead of the "getAuthToken" intent.
1369d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    if (!permissionGranted) {
1370d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        mAuthenticator.getAuthTokenLabel(this, authTokenType);
1371d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    } else {
1372d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
1373d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    }
137426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1375a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
13765bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
137726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void onResult(Bundle result) {
137826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (result != null) {
1379f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
1380d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            Intent intent = newGrantCredentialsPermissionIntent(account, callerUid,
1381d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                                    new AccountAuthenticatorResponse(this),
1382d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                                    authTokenType,
1383f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                    result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
1384d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            Bundle bundle = new Bundle();
1385f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            bundle.putParcelable(AccountManager.KEY_INTENT, intent);
1386d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            onResult(bundle);
1387d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            return;
1388d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        }
1389f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
139026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                        if (authToken != null) {
1391f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
1392f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
139326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
1394f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
139526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                                        "the type and name should not be empty");
139626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                                return;
139726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            }
1398a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                            if (!customTokens) {
139904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                                saveAuthTokenToDatabase(mAccounts, new Account(name, type),
1400a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                                        authTokenType, authToken);
1401a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                            }
1402a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        }
1403603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1404f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
1405d606045070dcf6a011e49a7711d2f17d8f2de8c1Costin Manolache                        if (intent != null && notifyOnAuthFailure && !customTokens) {
140604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                            doNotification(mAccounts,
1407f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                    account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
14084120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                                    intent, accounts.userId);
140926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                        }
1410a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
141126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    super.onResult(result);
1412a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
141326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
141426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
141526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
141626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1417603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1418603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
14194120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    private void createNoCredentialsPermissionNotification(Account account, Intent intent,
14204120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            int userId) {
1421d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        int uid = intent.getIntExtra(
1422d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
1423d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        String authTokenType = intent.getStringExtra(
1424d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE);
1425d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        String authTokenLabel = intent.getStringExtra(
1426d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
1427d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1428d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
1429d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                0 /* when */);
1430ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer        final String titleAndSubtitle =
1431ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer                mContext.getString(R.string.permission_request_notification_with_subtitle,
1432ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer                account.name);
1433ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer        final int index = titleAndSubtitle.indexOf('\n');
143485e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        String title = titleAndSubtitle;
143585e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        String subtitle = "";
143685e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        if (index > 0) {
143785e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache            title = titleAndSubtitle.substring(0, index);
1438a12fccf57d5ec289793699d9b22ff45daccd3933Maggie Benthall            subtitle = titleAndSubtitle.substring(index + 1);
143985e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        }
144050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        UserHandle user = new UserHandle(userId);
14414120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        n.setLatestEventInfo(mContext, title, subtitle,
14424120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                PendingIntent.getActivityAsUser(mContext, 0, intent,
144350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                        PendingIntent.FLAG_CANCEL_CURRENT, null, user));
144450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        installNotification(getCredentialPermissionNotificationId(
144550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                account, authTokenType, uid), n, user);
1446d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1447d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
14485f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
14495f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
1450d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1451d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
145246703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom        // See FLAG_ACTIVITY_NEW_TASK docs for limitations and benefits of the flag.
14539ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        // Since it was set in Eclair+ we can't change it without breaking apps using
14549ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        // the intent from a non-Activity context.
14559ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1456d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.addCategory(
1457d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid)));
14585f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1459d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
1460d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
1461d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
1462d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid);
14635f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1464d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return intent;
1465d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1466d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1467d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
1468d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            int uid) {
1469d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Integer id;
1470f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
147104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.credentialsPermissionNotificationIds) {
1472d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            final Pair<Pair<Account, String>, Integer> key =
1473d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    new Pair<Pair<Account, String>, Integer>(
1474d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            new Pair<Account, String>(account, authTokenType), uid);
147504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            id = accounts.credentialsPermissionNotificationIds.get(key);
1476d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (id == null) {
1477d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                id = mNotificationIds.incrementAndGet();
147804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.credentialsPermissionNotificationIds.put(key, id);
1479d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1480d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1481d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return id;
1482d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1483d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
148404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private Integer getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
1485d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Integer id;
148604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.signinRequiredNotificationIds) {
148704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            id = accounts.signinRequiredNotificationIds.get(account);
1488d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (id == null) {
1489d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                id = mNotificationIds.incrementAndGet();
149004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.signinRequiredNotificationIds.put(account, id);
1491d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1492d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1493d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return id;
1494d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1495d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
149609e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
149727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    public void addAccount(final IAccountManagerResponse response, final String accountType,
14983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            final String authTokenType, final String[] requiredFeatures,
1499b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache            final boolean expectActivityLaunch, final Bundle optionsIn) {
150056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
150156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "addAccount: accountType " + accountType
150256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
150356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
150456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", requiredFeatures " + stringArrayToString(requiredFeatures)
150556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
150656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
150756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
150856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1509382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1510382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
1511d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
1512b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
151371e6c697e54a43d357cc25d87a446d140f17396aAmith Yamasani        // Is user disallowed from modifying accounts?
151427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (!canUserModifyAccounts(Binder.getCallingUid())) {
1515df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            try {
1516df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
1517df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        "User is not allowed to add an account!");
1518df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            } catch (RemoteException re) {
1519df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
152023c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            Intent cantAddAccount = new Intent(mContext, CantAddAccountActivity.class);
152123c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            cantAddAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
152223c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            long identityToken = clearCallingIdentity();
152323c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            try {
152423c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani                mContext.startActivityAsUser(cantAddAccount, UserHandle.CURRENT);
152523c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            } finally {
152623c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani                restoreCallingIdentity(identityToken);
152723c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            }
1528df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return;
1529df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
1530df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani
153104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
1532b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int pid = Binder.getCallingPid();
1533b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int uid = Binder.getCallingUid();
1534b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
1535b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        options.putInt(AccountManager.KEY_CALLER_UID, uid);
1536b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        options.putInt(AccountManager.KEY_CALLER_PID, pid);
1537b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
153826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
153926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
154004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, accountType, expectActivityLaunch,
15418570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
15425bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
154326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
15443348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
15453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            options);
154626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1547a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
15485bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
154926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
155026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", addAccount"
15513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + ", accountType " + accountType
15523326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + ", requiredFeatures "
15533326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + (requiredFeatures != null
15543326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                              ? TextUtils.join(",", requiredFeatures)
15553326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                              : null);
155626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
155726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
155826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
155926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
156026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1561603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1562603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
15632c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
15642c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public void confirmCredentialsAsUser(IAccountManagerResponse response,
15652c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            final Account account, final Bundle options, final boolean expectActivityLaunch,
15662c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            int userId) {
15672c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        // Only allow the system process to read accounts of other users
15682c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        if (userId != UserHandle.getCallingUserId()
1569bb49e8573e22cb6325dc31bf007a500fb7c136ebAmith Yamasani                && Binder.getCallingUid() != Process.myUid()
1570464f530978b0b2517295fe3ade1dfa562a07487bJim Miller                && mContext.checkCallingOrSelfPermission(
1571464f530978b0b2517295fe3ade1dfa562a07487bJim Miller                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1572464f530978b0b2517295fe3ade1dfa562a07487bJim Miller                    != PackageManager.PERMISSION_GRANTED) {
15732c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            throw new SecurityException("User " + UserHandle.getCallingUserId()
15742c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    + " trying to confirm account credentials for " + userId);
15752c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        }
15762c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
157756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
157856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "confirmCredentials: " + account
157956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
158056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
158156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
158256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
158356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1584382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1585382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1586d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
15872c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
158826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
158926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
159004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
15918570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
15925bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
159326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
1594f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    mAuthenticator.confirmCredentials(this, account, options);
159526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
15965bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
159726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
159826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", confirmCredentials"
159926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account;
160026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
160126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
160226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
160326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
160426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1605603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1606603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
160709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1608a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void updateCredentials(IAccountManagerResponse response, final Account account,
1609a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final String authTokenType, final boolean expectActivityLaunch,
1610a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final Bundle loginOptions) {
161156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
161256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "updateCredentials: " + account
161356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
161456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
161556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
161656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
161756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
161856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1619382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1620382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1621382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1622d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
162304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
162426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
162526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
162604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
16278570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
16285bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
162926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
163026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
163126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
16325bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
163326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
163426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (loginOptions != null) loginOptions.keySet();
163526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", updateCredentials"
163626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account
163726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", authTokenType " + authTokenType
163826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", loginOptions " + loginOptions;
163926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
164026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
164126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
164226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
164326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1644603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1645603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
164609e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1647a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void editProperties(IAccountManagerResponse response, final String accountType,
1648a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final boolean expectActivityLaunch) {
164956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
165056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "editProperties: accountType " + accountType
165156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
165256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
165356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
165456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
165556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1656382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1657382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
1658d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
165904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
166026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
166126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
166204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, accountType, expectActivityLaunch,
16638570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
16645bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
166526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
166626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    mAuthenticator.editProperties(this, mAccountType);
166726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
16685bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                @Override
166926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
167026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", editProperties"
167126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", accountType " + accountType;
167226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
167326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
167426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
167526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
167626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1677603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1678603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
16793326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    private class GetAccountsByTypeAndFeatureSession extends Session {
16803326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private final String[] mFeatures;
16813326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile Account[] mAccountsOfType = null;
16823326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile ArrayList<Account> mAccountsWithFeatures = null;
16833326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile int mCurrentAccount = 0;
168409e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        private final int mCallingUid;
16853326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
168604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public GetAccountsByTypeAndFeatureSession(UserAccounts accounts,
1687df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                IAccountManagerResponse response, String type, String[] features, int callingUid) {
168804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, type, false /* expectActivityLaunch */,
16898570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
1690df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            mCallingUid = callingUid;
16913326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mFeatures = features;
16923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
16933326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16945bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
16953326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void run() throws RemoteException {
169604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (mAccounts.cacheLock) {
169727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid,
169827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        null);
1699f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
17003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            // check whether each account matches the requested features
17013326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length);
17023326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mCurrentAccount = 0;
17033326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
17043326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            checkAccount();
17053326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
17063326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
17073326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void checkAccount() {
17083326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (mCurrentAccount >= mAccountsOfType.length) {
17093326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                sendResult();
17103326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return;
17113326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
17123326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
171329e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            final IAccountAuthenticator accountAuthenticator = mAuthenticator;
171429e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            if (accountAuthenticator == null) {
171529e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // It is possible that the authenticator has died, which is indicated by
171629e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // mAuthenticator being set to null. If this happens then just abort.
171729e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // There is no need to send back a result or error in this case since
171829e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // that already happened when mAuthenticator was cleared.
171929e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
172029e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                    Log.v(TAG, "checkAccount: aborting session since we are no longer"
172129e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                            + " connected to the authenticator, " + toDebugString());
172229e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                }
172329e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                return;
172429e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            }
17253326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            try {
172629e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                accountAuthenticator.hasFeatures(this, mAccountsOfType[mCurrentAccount], mFeatures);
17273326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            } catch (RemoteException e) {
1728f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
1729a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1730603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1731603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
17325bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
17333326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void onResult(Bundle result) {
17343326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mNumResults++;
17353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (result == null) {
1736f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
17373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return;
17383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
1739f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
17403326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                mAccountsWithFeatures.add(mAccountsOfType[mCurrentAccount]);
17413326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
17423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mCurrentAccount++;
17433326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            checkAccount();
1744a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
17453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
17463326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void sendResult() {
17473326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
17483326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (response != null) {
17493326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                try {
17503326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    Account[] accounts = new Account[mAccountsWithFeatures.size()];
17513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    for (int i = 0; i < accounts.length; i++) {
17523326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        accounts[i] = mAccountsWithFeatures.get(i);
17533326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    }
175456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
175556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
175656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
175756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
17583326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    Bundle result = new Bundle();
1759f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
17603326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    response.onResult(result);
17613326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                } catch (RemoteException e) {
17623326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
17633326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
17643326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
17653326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    }
17663326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                }
17673326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
17683326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
17693326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
17703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
17715bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
17723326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        protected String toDebugString(long now) {
17733326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            return super.toDebugString(now) + ", getAccountsByTypeAndFeatures"
17743326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
17753326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
17763326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
1777ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
177804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    /**
177904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     * Returns the accounts for a specific user
178004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     * @hide
178104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     */
178204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public Account[] getAccounts(int userId) {
178304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        checkReadAccountsPermission();
178404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
1785df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        int callingUid = Binder.getCallingUid();
178604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        long identityToken = clearCallingIdentity();
178704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        try {
178804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
178927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                return getAccountsFromCacheLocked(accounts, null, callingUid, null);
179004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
179104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        } finally {
179204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            restoreCallingIdentity(identityToken);
179304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
179404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
179504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
1796f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani    /**
17976ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey     * Returns accounts for all running users.
17986ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey     *
1799f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani     * @hide
1800f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani     */
18016ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    public AccountAndUser[] getRunningAccounts() {
18026ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int[] runningUserIds;
18036ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        try {
18046ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            runningUserIds = ActivityManagerNative.getDefault().getRunningUserIds();
18056ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        } catch (RemoteException e) {
18066ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            // Running in system_server; should never happen
18076ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            throw new RuntimeException(e);
18086ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
18096eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        return getAccounts(runningUserIds);
18106eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
18116eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
18126eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /** {@hide} */
18136eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    public AccountAndUser[] getAllAccounts() {
18146eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final List<UserInfo> users = getUserManager().getUsers();
18156eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final int[] userIds = new int[users.size()];
18166eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        for (int i = 0; i < userIds.length; i++) {
18176eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            userIds[i] = users.get(i).id;
18186eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        }
18196eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        return getAccounts(userIds);
18206eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
18216ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
18226eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    private AccountAndUser[] getAccounts(int[] userIds) {
18236ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList();
18240c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani        for (int userId : userIds) {
18250c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            UserAccounts userAccounts = getUserAccounts(userId);
18260c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            if (userAccounts == null) continue;
18270c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani            synchronized (userAccounts.cacheLock) {
18280c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani                Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
18290c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani                        Binder.getCallingUid(), null);
18300c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani                for (int a = 0; a < accounts.length; a++) {
18310c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani                    runningAccounts.add(new AccountAndUser(accounts[a], userId));
1832f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                }
1833f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani            }
1834f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani        }
18356ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
18366ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        AccountAndUser[] accountsArray = new AccountAndUser[runningAccounts.size()];
18376ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        return runningAccounts.toArray(accountsArray);
1838f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani    }
1839f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani
18402c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
18412c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public Account[] getAccountsAsUser(String type, int userId) {
184227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        return getAccountsAsUser(type, userId, null, -1);
184327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    }
184427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani
184527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    private Account[] getAccountsAsUser(String type, int userId, String callingPackage,
184627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            int packageUid) {
184727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        int callingUid = Binder.getCallingUid();
18482c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        // Only allow the system process to read accounts of other users
18492c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        if (userId != UserHandle.getCallingUserId()
1850bb49e8573e22cb6325dc31bf007a500fb7c136ebAmith Yamasani                && callingUid != Process.myUid()
1851464f530978b0b2517295fe3ade1dfa562a07487bJim Miller                && mContext.checkCallingOrSelfPermission(
1852464f530978b0b2517295fe3ade1dfa562a07487bJim Miller                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1853464f530978b0b2517295fe3ade1dfa562a07487bJim Miller                    != PackageManager.PERMISSION_GRANTED) {
18542c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            throw new SecurityException("User " + UserHandle.getCallingUserId()
18552c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    + " trying to get account for " + userId);
18562c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        }
18572c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
185856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
185956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAccounts: accountType " + type
186056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
186156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
186256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
186327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        // If the original calling app was using the framework account chooser activity, we'll
186427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        // be passed in the original caller's uid here, which is what should be used for filtering.
186527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) {
186627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            callingUid = packageUid;
186727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        }
1868ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        checkReadAccountsPermission();
18692c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
1870ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        long identityToken = clearCallingIdentity();
1871ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        try {
187204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
187327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage);
1874f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
1875ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
1876ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
1877ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
1878ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
1879ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
18802c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
188167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public boolean addSharedAccountAsUser(Account account, int userId) {
188267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
188367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        SQLiteDatabase db = getUserAccounts(userId).openHelper.getWritableDatabase();
188467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        ContentValues values = new ContentValues();
188567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        values.put(ACCOUNTS_NAME, account.name);
188667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        values.put(ACCOUNTS_TYPE, account.type);
188767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
188867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                new String[] {account.name, account.type});
188967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long accountId = db.insert(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME, values);
189067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (accountId < 0) {
189167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            Log.w(TAG, "insertAccountIntoDatabase: " + account
189267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ", skipping the DB insert failed");
189367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return false;
189467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
189567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return true;
189667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
189767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
189867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
189967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public boolean removeSharedAccountAsUser(Account account, int userId) {
190067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
190167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        UserAccounts accounts = getUserAccounts(userId);
190267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
190367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        int r = db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
190467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                new String[] {account.name, account.type});
190567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (r > 0) {
190667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            removeAccountInternal(accounts, account);
190767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
190867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return r > 0;
190967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
191067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
191167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
191267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public Account[] getSharedAccountsAsUser(int userId) {
191367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
191467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        UserAccounts accounts = getUserAccounts(userId);
191567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        ArrayList<Account> accountList = new ArrayList<Account>();
191667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Cursor cursor = null;
191767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
191867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            cursor = accounts.openHelper.getReadableDatabase()
191967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    .query(TABLE_SHARED_ACCOUNTS, new String[]{ACCOUNTS_NAME, ACCOUNTS_TYPE},
192067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    null, null, null, null, null);
192167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (cursor != null && cursor.moveToFirst()) {
192267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                int nameIndex = cursor.getColumnIndex(ACCOUNTS_NAME);
192367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                int typeIndex = cursor.getColumnIndex(ACCOUNTS_TYPE);
192467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                do {
192567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    accountList.add(new Account(cursor.getString(nameIndex),
192667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            cursor.getString(typeIndex)));
192767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } while (cursor.moveToNext());
192867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
192967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
193067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (cursor != null) {
193167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                cursor.close();
193267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
193367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
193467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] accountArray = new Account[accountList.size()];
193567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        accountList.toArray(accountArray);
193667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return accountArray;
193767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
193867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
193967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
19402c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public Account[] getAccounts(String type) {
19412c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        return getAccountsAsUser(type, UserHandle.getCallingUserId());
19422c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    }
19432c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
194427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    @Override
194527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    public Account[] getAccountsForPackage(String packageName, int uid) {
194627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        int callingUid = Binder.getCallingUid();
194727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
194827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
194927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    + callingUid + " with uid=" + uid);
195027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        }
195127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid);
195227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    }
195327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani
19543b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani    @Override
19553b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani    public Account[] getAccountsByTypeForPackage(String type, String packageName) {
19563b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani        checkBinderPermission(android.Manifest.permission.INTERACT_ACROSS_USERS);
19573b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani        int packageUid = -1;
19583b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani        try {
19593b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani            packageUid = AppGlobals.getPackageManager().getPackageUid(
19603b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani                    packageName, UserHandle.getCallingUserId());
19613b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani        } catch (RemoteException re) {
19623b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani            Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re);
19633b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani            return new Account[0];
19643b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani        }
19653b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani        return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName, packageUid);
19663b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani    }
19673b458ad9ee5f2d6b7cf28a13bc29123cdf540763Amith Yamasani
196809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
1969ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    public void getAccountsByFeatures(IAccountManagerResponse response,
19703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            String type, String[] features) {
197156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
197256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAccounts: accountType " + type
197356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
197456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", features " + stringArrayToString(features)
197556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
197656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
197756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1978382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1979382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (type == null) throw new IllegalArgumentException("accountType is null");
1980d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkReadAccountsPermission();
198104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts userAccounts = getUserAccountsForCaller();
1982df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        int callingUid = Binder.getCallingUid();
19833326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        long identityToken = clearCallingIdentity();
19843326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        try {
1985ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            if (features == null || features.length == 0) {
1986f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Account[] accounts;
198704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                synchronized (userAccounts.cacheLock) {
198827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null);
1989f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
1990d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                Bundle result = new Bundle();
1991d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
1992d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                onResult(response, result);
1993ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                return;
1994ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
1995df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            new GetAccountsByTypeAndFeatureSession(userAccounts, response, type, features,
1996df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    callingUid).bind();
19973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        } finally {
19983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            restoreCallingIdentity(identityToken);
19993326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
20003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
20013326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
2002f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long getAccountIdLocked(SQLiteDatabase db, Account account) {
2003603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
2004ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
2005603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
2006603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (cursor.moveToNext()) {
2007603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return cursor.getLong(0);
2008603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2009603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            return -1;
2010603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
2011603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cursor.close();
2012603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2013603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2014603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2015f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long getExtrasIdLocked(SQLiteDatabase db, long accountId, String key) {
2016603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_ID},
2017603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
2018603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                new String[]{key}, null, null, null);
2019603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
2020603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (cursor.moveToNext()) {
2021603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return cursor.getLong(0);
2022603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2023603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            return -1;
2024603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
2025603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cursor.close();
2026603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2027603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2028603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2029a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    private abstract class Session extends IAccountAuthenticatorResponse.Stub
2030b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            implements IBinder.DeathRecipient, ServiceConnection {
2031603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        IAccountManagerResponse mResponse;
2032603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        final String mAccountType;
2033a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        final boolean mExpectActivityLaunch;
2034a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        final long mCreationTime;
2035a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
20363326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public int mNumResults = 0;
2037a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private int mNumRequestContinued = 0;
2038a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private int mNumErrors = 0;
2039a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2040603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        IAccountAuthenticator mAuthenticator = null;
2041603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
20428570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana        private final boolean mStripAuthTokenFromResult;
204304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        protected final UserAccounts mAccounts;
20448570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana
204504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public Session(UserAccounts accounts, IAccountManagerResponse response, String accountType,
20468570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
2047603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            super();
204867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            //if (response == null) throw new IllegalArgumentException("response is null");
20493326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (accountType == null) throw new IllegalArgumentException("accountType is null");
205004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            mAccounts = accounts;
20518570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana            mStripAuthTokenFromResult = stripAuthTokenFromResult;
2052603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mResponse = response;
2053603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mAccountType = accountType;
2054a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mExpectActivityLaunch = expectActivityLaunch;
2055a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mCreationTime = SystemClock.elapsedRealtime();
2056a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            synchronized (mSessions) {
2057a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mSessions.put(toString(), this);
2058a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
205967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (response != null) {
206067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                try {
206167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    response.asBinder().linkToDeath(this, 0 /* flags */);
206267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } catch (RemoteException e) {
206367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mResponse = null;
206467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    binderDied();
206567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
2066a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2067603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2068603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2069a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        IAccountManagerResponse getResponseAndClose() {
2070603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (mResponse == null) {
2071603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                // this session has already been closed
2072603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return null;
2073603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2074a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = mResponse;
2075a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            close(); // this clears mResponse so we need to save the response before this call
2076a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return response;
2077a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2078a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2079a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private void close() {
2080a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            synchronized (mSessions) {
2081a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (mSessions.remove(toString()) == null) {
2082a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    // the session was already closed, so bail out now
2083a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    return;
2084a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2085a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2086a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (mResponse != null) {
2087a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                // stop listening for response deaths
2088a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mResponse.asBinder().unlinkToDeath(this, 0 /* flags */);
2089a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2090a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                // clear this so that we don't accidentally send any further results
2091a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mResponse = null;
2092a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2093603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cancelTimeout();
2094603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            unbind();
2095a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2096a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
209709e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        @Override
2098a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void binderDied() {
2099603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mResponse = null;
2100a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            close();
2101a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2102a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2103a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        protected String toDebugString() {
2104a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return toDebugString(SystemClock.elapsedRealtime());
2105a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2106a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2107a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        protected String toDebugString(long now) {
2108a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return "Session: expectLaunch " + mExpectActivityLaunch
2109a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", connected " + (mAuthenticator != null)
2110a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", stats (" + mNumResults + "/" + mNumRequestContinued
2111a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "/" + mNumErrors + ")"
2112a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", lifetime " + ((now - mCreationTime) / 1000.0);
2113603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2114603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2115603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        void bind() {
2116a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
2117a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                Log.v(TAG, "initiating bind to authenticator type " + mAccountType);
2118a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2119b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (!bindToAuthenticator(mAccountType)) {
2120a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                Log.d(TAG, "bind attempt failed for " + toDebugString());
2121f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
2122603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2123603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2124603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2125603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        private void unbind() {
2126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (mAuthenticator != null) {
2127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                mAuthenticator = null;
2128b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                mContext.unbindService(this);
2129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2130603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void scheduleTimeout() {
2133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mMessageHandler.sendMessageDelayed(
2134603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    mMessageHandler.obtainMessage(MESSAGE_TIMED_OUT, this), TIMEOUT_DELAY_MS);
2135603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2136603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2137603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void cancelTimeout() {
2138603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this);
2139603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2140603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
214109e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        @Override
2142b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public void onServiceConnected(ComponentName name, IBinder service) {
2143603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
2144a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            try {
2145a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                run();
2146a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } catch (RemoteException e) {
2147f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2148a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        "remote exception");
2149a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2150603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2151603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
215209e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        @Override
2153b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public void onServiceDisconnected(ComponentName name) {
2154a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mAuthenticator = null;
2155a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2156603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2157166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                try {
2158166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2159166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                            "disconnected");
2160166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                } catch (RemoteException e) {
2161166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2162166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        Log.v(TAG, "Session.onServiceDisconnected: "
2163166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                                + "caught RemoteException while responding", e);
2164166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    }
2165166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                }
2166603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2167603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2168603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2169b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public abstract void run() throws RemoteException;
2170b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2171603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onTimedOut() {
2172a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2173603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2174166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                try {
2175166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2176166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                            "timeout");
2177166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                } catch (RemoteException e) {
2178166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2179166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        Log.v(TAG, "Session.onTimedOut: caught RemoteException while responding",
2180166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                                e);
2181166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    }
2182166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                }
2183603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2184603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2185603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
21865bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
2187a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void onResult(Bundle result) {
2188a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumResults++;
21895bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia            Intent intent = null;
21905bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia            if (result != null
21915bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                    && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
21925bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                /*
21935bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                 * The Authenticator API allows third party authenticators to
21945bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                 * supply arbitrary intents to other apps that they can run,
21955bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                 * this can be very bad when those apps are in the system like
21965bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                 * the System Settings.
21975bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                 */
21985bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                int authenticatorUid = Binder.getCallingUid();
2199416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                long bid = Binder.clearCallingIdentity();
2200416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                try {
2201416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                    PackageManager pm = mContext.getPackageManager();
2202416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                    ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
2203416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                    int targetUid = resolveInfo.activityInfo.applicationInfo.uid;
2204416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                    if (PackageManager.SIGNATURE_MATCH !=
2205416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                            pm.checkSignatures(authenticatorUid, targetUid)) {
2206416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                        throw new SecurityException(
2207416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                                "Activity to be started with KEY_INTENT must " +
2208416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                               "share Authenticator's signatures");
2209416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                    }
2210416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                } finally {
2211416747aea11351c4327ac74c3a8d7bf338cde946Carlos Valdivia                    Binder.restoreCallingIdentity(bid);
22125bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                }
22135bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia            }
22145bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia            if (result != null
22155bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia                    && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {
2216f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
2217f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
2218d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
2219d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    Account account = new Account(accountName, accountType);
222050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    cancelNotification(getSigninRequiredNotificationId(mAccounts, account),
222150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            new UserHandle(mAccounts.userId));
2222d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                }
2223603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2224a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response;
2225a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (mExpectActivityLaunch && result != null
2226f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    && result.containsKey(AccountManager.KEY_INTENT)) {
2227a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                response = mResponse;
2228a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } else {
2229a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                response = getResponseAndClose();
2230603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2231603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2232603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                try {
2233a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (result == null) {
223456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
223556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            Log.v(TAG, getClass().getSimpleName()
223656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                    + " calling onError() on response " + response);
223756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
2238f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
2239a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                                "null bundle returned");
2240a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    } else {
22418570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                        if (mStripAuthTokenFromResult) {
22428570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                            result.remove(AccountManager.KEY_AUTHTOKEN);
22438570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                        }
224456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
224556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            Log.v(TAG, getClass().getSimpleName()
224656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                    + " calling onResult() on response " + response);
224756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
224809e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                        if ((result.getInt(AccountManager.KEY_ERROR_CODE, -1) > 0) &&
224909e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                                (intent == null)) {
225009e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                            // All AccountManager error codes are greater than 0
225109e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                            response.onError(result.getInt(AccountManager.KEY_ERROR_CODE),
225209e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                                    result.getString(AccountManager.KEY_ERROR_MESSAGE));
225309e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                        } else {
225409e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                            response.onResult(result);
225509e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia                        }
2256a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2257603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                } catch (RemoteException e) {
2258a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
2259a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2260a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
2261a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2262603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                }
2263603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2264603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2265603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
226609e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        @Override
2267a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void onRequestContinued() {
2268a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumRequestContinued++;
2269603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2270603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
227109e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia        @Override
2272603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onError(int errorCode, String errorMessage) {
2273a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumErrors++;
2274a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2275a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (response != null) {
2276a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
227756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    Log.v(TAG, getClass().getSimpleName()
227856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            + " calling onError() on response " + response);
2279a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2280a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                try {
2281a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    response.onError(errorCode, errorMessage);
2282a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                } catch (RemoteException e) {
2283a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2284a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        Log.v(TAG, "Session.onError: caught RemoteException while responding", e);
2285a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2286a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2287a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } else {
2288a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2289a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    Log.v(TAG, "Session.onError: already closed");
2290a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2291603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2292603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2293b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2294b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        /**
2295b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         * find the component name for the authenticator and initiate a bind
2296b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         * if no authenticator or the bind fails then return false, otherwise return true
2297b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         */
2298b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        private boolean bindToAuthenticator(String authenticatorType) {
22996ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            final AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
23006ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            authenticatorInfo = mAuthenticatorCache.getServiceInfo(
23016ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    AuthenticatorDescription.newKey(authenticatorType), mAccounts.userId);
2302b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (authenticatorInfo == null) {
2303b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2304b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                    Log.v(TAG, "there is no authenticator for " + authenticatorType
2305b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                            + ", bailing out");
2306b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                }
2307b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                return false;
2308b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
2309b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2310b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            Intent intent = new Intent();
2311b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
2312b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            intent.setComponent(authenticatorInfo.componentName);
2313b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
2314b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
2315b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
231627b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani            if (!mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
231727b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    new UserHandle(mAccounts.userId))) {
2318b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2319b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
2320b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                }
2321b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                return false;
2322b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
2323b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2324b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2325b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            return true;
2326b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        }
2327603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2328603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2329603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private class MessageHandler extends Handler {
2330603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        MessageHandler(Looper looper) {
2331603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            super(looper);
2332603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
23333348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache
23345bab9daf3cf66f4de19f8757e386030e8bef23ceCarlos Valdivia        @Override
2335603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void handleMessage(Message msg) {
2336603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            switch (msg.what) {
2337603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                case MESSAGE_TIMED_OUT:
2338603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    Session session = (Session)msg.obj;
2339603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    session.onTimedOut();
2340603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    break;
2341603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
23425be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                case MESSAGE_COPY_SHARED_ACCOUNT:
23435be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    copyAccountToUser((Account) msg.obj, msg.arg1, msg.arg2);
23445be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    break;
23455be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani
2346603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                default:
2347603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    throw new IllegalStateException("unhandled message: " + msg.what);
2348603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2349603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2350603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2351603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
235204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static String getDatabaseName(int userId) {
235304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        File systemDir = Environment.getSystemSecureDirectory();
235461f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani        File databaseFile = new File(Environment.getUserSystemDirectory(userId), DATABASE_NAME);
235504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        if (userId == 0) {
2356a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // Migrate old file, if it exists, to the new location.
2357a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // Make sure the new file doesn't already exist. A dummy file could have been
2358a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // accidentally created in the old location, causing the new one to become corrupted
2359a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // as well.
236004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            File oldFile = new File(systemDir, DATABASE_NAME);
2361a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            if (oldFile.exists() && !databaseFile.exists()) {
2362c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                // Check for use directory; create if it doesn't exist, else renameTo will fail
236361f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani                File userDir = Environment.getUserSystemDirectory(userId);
2364c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                if (!userDir.exists()) {
2365c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    if (!userDir.mkdirs()) {
2366c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                        throw new IllegalStateException("User dir cannot be created: " + userDir);
2367c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    }
2368c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                }
2369c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                if (!oldFile.renameTo(databaseFile)) {
2370c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    throw new IllegalStateException("User dir cannot be migrated: " + databaseFile);
2371c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                }
237204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
2373a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor        }
237404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        return databaseFile.getPath();
2375a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor    }
2376a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor
237704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    static class DatabaseHelper extends SQLiteOpenHelper {
2378a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor
237904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public DatabaseHelper(Context context, int userId) {
238004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(context, AccountManagerService.getDatabaseName(userId), null, DATABASE_VERSION);
2381603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2382603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2383f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        /**
2384f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * This call needs to be made while the mCacheLock is held. The way to
2385f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * ensure this is to get the lock any time a method is called ont the DatabaseHelper
2386f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * @param db The database.
2387f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         */
2388603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2389603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onCreate(SQLiteDatabase db) {
2390603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_ACCOUNTS + " ( "
2391603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
2392603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_NAME + " TEXT NOT NULL, "
2393603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_TYPE + " TEXT NOT NULL, "
2394603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_PASSWORD + " TEXT, "
2395603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
2396603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2397603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " (  "
2398603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,  "
2399603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_ACCOUNTS_ID + " INTEGER NOT NULL, "
2400603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_TYPE + " TEXT NOT NULL,  "
2401603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_AUTHTOKEN + " TEXT,  "
2402603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE (" + AUTHTOKENS_ACCOUNTS_ID + "," + AUTHTOKENS_TYPE + "))");
2403603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2404d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            createGrantsTable(db);
2405d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2406603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_EXTRAS + " ( "
2407603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
2408603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_ACCOUNTS_ID + " INTEGER, "
2409603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_KEY + " TEXT NOT NULL, "
2410603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_VALUE + " TEXT, "
2411603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE(" + EXTRAS_ACCOUNTS_ID + "," + EXTRAS_KEY + "))");
2412603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2413603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_META + " ( "
2414603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + META_KEY + " TEXT PRIMARY KEY NOT NULL, "
2415603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + META_VALUE + " TEXT)");
2416a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
241767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            createSharedAccountsTable(db);
241867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2419d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            createAccountsDeletionTrigger(db);
2420d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2421d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
242267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        private void createSharedAccountsTable(SQLiteDatabase db) {
242367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            db.execSQL("CREATE TABLE " + TABLE_SHARED_ACCOUNTS + " ( "
242467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
242567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_NAME + " TEXT NOT NULL, "
242667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_TYPE + " TEXT NOT NULL, "
242767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
242867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
242967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2430d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        private void createAccountsDeletionTrigger(SQLiteDatabase db) {
2431a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            db.execSQL(""
2432a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
2433a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " BEGIN"
2434a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "   DELETE FROM " + TABLE_AUTHTOKENS
2435a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "     WHERE " + AUTHTOKENS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2436a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "   DELETE FROM " + TABLE_EXTRAS
2437a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "     WHERE " + EXTRAS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2438d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "   DELETE FROM " + TABLE_GRANTS
2439d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "     WHERE " + GRANTS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2440a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " END");
2441603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2442603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2443d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        private void createGrantsTable(SQLiteDatabase db) {
2444d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            db.execSQL("CREATE TABLE " + TABLE_GRANTS + " (  "
2445d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_ACCOUNTS_ID + " INTEGER NOT NULL, "
2446d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_AUTH_TOKEN_TYPE + " STRING NOT NULL,  "
2447d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_GRANTEE_UID + " INTEGER NOT NULL,  "
2448d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "UNIQUE (" + GRANTS_ACCOUNTS_ID + "," + GRANTS_AUTH_TOKEN_TYPE
2449d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    +   "," + GRANTS_GRANTEE_UID + "))");
2450d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2451d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2452603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2453603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
2454a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
2455603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2456a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (oldVersion == 1) {
2457d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                // no longer need to do anything since the work is done
2458d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                // when upgrading from version 2
2459d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                oldVersion++;
2460d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
2461d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2462d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (oldVersion == 2) {
2463d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                createGrantsTable(db);
2464d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                db.execSQL("DROP TRIGGER " + TABLE_ACCOUNTS + "Delete");
2465d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                createAccountsDeletionTrigger(db);
2466a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                oldVersion++;
2467a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
24683348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache
24693348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache            if (oldVersion == 3) {
24703348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_TYPE +
24713348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                        " = 'com.google' WHERE " + ACCOUNTS_TYPE + " == 'com.google.GAIA'");
24723348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                oldVersion++;
24733348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache            }
247467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
247567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (oldVersion == 4) {
247667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                createSharedAccountsTable(db);
247767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                oldVersion++;
247867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
247967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
248067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (oldVersion != newVersion) {
248167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
248267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
2483603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2484603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2485603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2486603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onOpen(SQLiteDatabase db) {
2487603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "opened database " + DATABASE_NAME);
2488603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2489603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2490603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2491603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    public IBinder onBind(Intent intent) {
2492603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        return asBinder();
2493603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2494a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
24951cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    /**
24961cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * Searches array of arguments for the specified string
24971cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @param args array of argument strings
24981cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @param value value to search for
24991cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @return true if the value is contained in the array
25001cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     */
25011cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static boolean scanArgs(String[] args, String value) {
25021cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        if (args != null) {
25031cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks            for (String arg : args) {
25041cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                if (value.equals(arg)) {
25051cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                    return true;
25061cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2507a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2508a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
25091cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        return false;
25101cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    }
2511a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
25126eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    @Override
25131cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
25143abd75ba3a981850cac43a401d0014a836559cb0Kenny Root        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
25153abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                != PackageManager.PERMISSION_GRANTED) {
25163abd75ba3a981850cac43a401d0014a836559cb0Kenny Root            fout.println("Permission Denial: can't dump AccountsManager from from pid="
25173abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
25183abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                    + " without permission " + android.Manifest.permission.DUMP);
25193abd75ba3a981850cac43a401d0014a836559cb0Kenny Root            return;
25203abd75ba3a981850cac43a401d0014a836559cb0Kenny Root        }
252104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
25226eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final IndentingPrintWriter ipw = new IndentingPrintWriter(fout, "  ");
25236eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
25246eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final List<UserInfo> users = getUserManager().getUsers();
25256eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        for (UserInfo user : users) {
25266eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.println("User " + user + ":");
25276eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.increaseIndent();
25286eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            dumpUser(getUserAccounts(user.id), fd, ipw, args, isCheckinRequest);
25296eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.println();
25306eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.decreaseIndent();
253104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
253204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
25331cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks
253404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void dumpUser(UserAccounts userAccounts, FileDescriptor fd, PrintWriter fout,
253504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String[] args, boolean isCheckinRequest) {
253604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (userAccounts.cacheLock) {
253704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = userAccounts.openHelper.getReadableDatabase();
2538a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2539f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (isCheckinRequest) {
2540f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // This is a checkin request. *Only* upload the account types and the count of each.
2541f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
2542f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        null, null, ACCOUNTS_TYPE, null, null);
2543f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                try {
2544f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    while (cursor.moveToNext()) {
2545f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        // print type,count
2546f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        fout.println(cursor.getString(0) + "," + cursor.getString(1));
2547f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
2548f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } finally {
2549f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (cursor != null) {
2550f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        cursor.close();
2551f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
25521cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2553f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } else {
2554df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
255527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        Process.myUid(), null);
2556f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println("Accounts: " + accounts.length);
2557f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                for (Account account : accounts) {
2558f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    fout.println("  " + account);
25591cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2560307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
2561f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println();
2562f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                synchronized (mSessions) {
2563f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    final long now = SystemClock.elapsedRealtime();
2564f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    fout.println("Active Sessions: " + mSessions.size());
2565f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    for (Session session : mSessions.values()) {
2566f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        fout.println("  " + session.toDebugString(now));
2567f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
25681cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
25691cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks
2570f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println();
25716ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
2572f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
25731cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        }
2574a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2575a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
257604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void doNotification(UserAccounts accounts, Account account, CharSequence message,
25774120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            Intent intent, int userId) {
257826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
257926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
258026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
258126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                Log.v(TAG, "doNotification: " + message + " intent:" + intent);
258226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
2583a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2584d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (intent.getComponent() != null &&
2585d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    GrantCredentialsPermissionActivity.class.getName().equals(
2586d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            intent.getComponent().getClassName())) {
25874120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                createNoCredentialsPermissionNotification(account, intent, userId);
2588d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            } else {
258904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
259033f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                intent.addCategory(String.valueOf(notificationId));
2591d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
2592d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        0 /* when */);
259350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                UserHandle user = new UserHandle(userId);
259433f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                final String notificationTitleFormat =
259533f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                        mContext.getText(R.string.notification_title).toString();
259633f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                n.setLatestEventInfo(mContext,
259733f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                        String.format(notificationTitleFormat, account.name),
25984120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        message, PendingIntent.getActivityAsUser(
25994120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
260050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                        null, user));
260150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                installNotification(notificationId, n, user);
2602d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
260326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
260426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
260526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
2606a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2607a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
260850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    protected void installNotification(final int notificationId, final Notification n,
260950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            UserHandle user) {
261056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
261150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                .notifyAsUser(null, notificationId, n, user);
261256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
261356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
261450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    protected void cancelNotification(int id, UserHandle user) {
261526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
261626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
261726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
261850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                .cancelAsUser(null, id, user);
261926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
262026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
262126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
2622a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2623d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2624b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    /** Succeeds if any of the specified permissions are granted. */
2625b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    private void checkBinderPermission(String... permissions) {
2626d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        final int uid = Binder.getCallingUid();
2627b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2628b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        for (String perm : permissions) {
2629b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana            if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
2630b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
263156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    Log.v(TAG, "  caller uid " + uid + " has " + perm);
2632b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                }
2633b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                return;
2634b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana            }
2635d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2636b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2637b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions);
263856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Log.w(TAG, "  " + msg);
2639b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        throw new SecurityException(msg);
2640d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2641d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
264267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private int handleIncomingUser(int userId) {
264367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
264467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return ActivityManagerNative.getDefault().handleIncomingUser(
264567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, true, "", null);
264667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } catch (RemoteException re) {
264767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Shouldn't happen, local.
264867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
264967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return userId;
265067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
265167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2652ccbf84f44c9e6a5ed3c08673614826bb237afc54Christopher Tate    private boolean isPrivileged(int callingUid) {
26536ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int callingUserId = UserHandle.getUserId(callingUid);
26546ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
26556ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final PackageManager userPackageManager;
26566ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        try {
26576ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            userPackageManager = mContext.createPackageContextAsUser(
26586ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    "android", 0, new UserHandle(callingUserId)).getPackageManager();
26596ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        } catch (NameNotFoundException e) {
26606ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            return false;
26616ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
26626ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
26636ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        String[] packages = userPackageManager.getPackagesForUid(callingUid);
26647be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        for (String name : packages) {
26657be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            try {
26666ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
266756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                if (packageInfo != null
2668ccbf84f44c9e6a5ed3c08673614826bb237afc54Christopher Tate                        && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
26697be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                    return true;
26707be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                }
26717be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            } catch (PackageManager.NameNotFoundException e) {
26727be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                return false;
26737be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            }
26747be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        }
26757be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        return false;
26767be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    }
26777be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
2678d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
2679ccbf84f44c9e6a5ed3c08673614826bb237afc54Christopher Tate        final boolean isPrivileged = isPrivileged(callerUid);
268031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        final boolean fromAuthenticator = account != null
268131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana                && hasAuthenticatorUid(account.type, callerUid);
268231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        final boolean hasExplicitGrants = account != null
268304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                && hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
2684d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
2685d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
268656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + callerUid + ", " + account
2687d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + ": is authenticator? " + fromAuthenticator
2688d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + ", has explicit permission? " + hasExplicitGrants);
2689d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2690ccbf84f44c9e6a5ed3c08673614826bb237afc54Christopher Tate        return fromAuthenticator || hasExplicitGrants || isPrivileged;
2691d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2692d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
26931a23191bbde11505d6e0c25c04a60b41cb27fd31Fred Quintana    private boolean hasAuthenticatorUid(String accountType, int callingUid) {
26946ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int callingUserId = UserHandle.getUserId(callingUid);
2695d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
26966ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.getAllServices(callingUserId)) {
2697d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (serviceInfo.type.type.equals(accountType)) {
2698ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                return (serviceInfo.uid == callingUid) ||
269956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        (mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
2700ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                                == PackageManager.SIGNATURE_MATCH);
2701d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
2702d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2703d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return false;
2704d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2705d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
270604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
270704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            int callerUid) {
270827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callerUid == Process.SYSTEM_UID) {
2709d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            return true;
2710d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
271104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
271204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
271304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
271404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String[] args = { String.valueOf(callerUid), authTokenType,
2715f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    account.name, account.type};
2716f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final boolean permissionGranted =
2717f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
2718f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
2719f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // TODO: Skip this check when running automated tests. Replace this
2720f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // with a more general solution.
2721f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Log.d(TAG, "no credentials permission for usage of " + account + ", "
272204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        + authTokenType + " by uid " + callerUid
2723f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        + " but ignoring since device is in test harness.");
2724f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return true;
2725f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2726f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            return permissionGranted;
2727d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2728d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2729d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2730d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkCallingUidAgainstAuthenticator(Account account) {
2731d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        final int uid = Binder.getCallingUid();
273231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || !hasAuthenticatorUid(account.type, uid)) {
2733d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            String msg = "caller uid " + uid + " is different than the authenticator's uid";
2734d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.w(TAG, msg);
2735d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            throw new SecurityException(msg);
2736d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2737d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
2738d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid");
2739d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2740d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2741d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2742d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkAuthenticateAccountsPermission(Account account) {
2743d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.AUTHENTICATE_ACCOUNTS);
2744d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkCallingUidAgainstAuthenticator(account);
2745d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2746d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2747d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkReadAccountsPermission() {
2748d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
2749d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2750d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2751d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkManageAccountsPermission() {
2752d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS);
2753d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2754d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2755b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    private void checkManageAccountsOrUseCredentialsPermissions() {
2756b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS,
2757b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                Manifest.permission.USE_CREDENTIALS);
2758b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    }
2759b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2760e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani    private boolean canUserModifyAccounts(int callingUid) {
276127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callingUid != Process.myUid()) {
276227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            if (getUserManager().getUserRestrictions(
276327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    new UserHandle(UserHandle.getUserId(callingUid)))
276427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
2765e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                return false;
2766e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            }
2767e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        }
2768e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        return true;
2769e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani    }
2770e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani
277109e7e0ef8bcd8b7b78b79fb570de2032871f0c97Jatin Lodhia    @Override
2772d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
2773d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throws RemoteException {
2774d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        final int callingUid = getCallingUid();
2775d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
277627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callingUid != Process.SYSTEM_UID) {
2777d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throw new SecurityException();
2778d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
2779d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2780d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (value) {
2781d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            grantAppPermission(account, authTokenType, uid);
2782d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        } else {
2783d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            revokeAppPermission(account, authTokenType, uid);
2784d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
2785d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    }
2786d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2787d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
2788d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Allow callers with the given uid permission to get credentials for account/authTokenType.
2789d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * <p>
2790d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Although this is public it can only be accessed via the AccountManagerService object
2791d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * which is in the system. This means we don't need to protect it with permissions.
2792d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
2793d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
2794d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    private void grantAppPermission(Account account, String authTokenType, int uid) {
2795382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null || authTokenType == null) {
2796382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana            Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
279731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
279831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
2799f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
280004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
280104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
2802f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
2803f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
2804f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
2805f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
2806f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ContentValues values = new ContentValues();
2807f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_ACCOUNTS_ID, accountId);
2808f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
2809f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_GRANTEE_UID, uid);
2810f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
2811f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
2812f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
2813f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
2814f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
2815d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
281650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
281750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    new UserHandle(accounts.userId));
2818d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2819d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2820d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2821d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
2822d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Don't allow callers with the given uid permission to get credentials for
2823d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * account/authTokenType.
2824d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * <p>
2825d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Although this is public it can only be accessed via the AccountManagerService object
2826d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * which is in the system. This means we don't need to protect it with permissions.
2827d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
2828d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
2829d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    private void revokeAppPermission(Account account, String authTokenType, int uid) {
2830382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null || authTokenType == null) {
2831382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana            Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
283231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
283331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
2834f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
283504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
283604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
2837f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
2838f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
2839f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
2840f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
2841f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.delete(TABLE_GRANTS,
2842f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND "
2843f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    + GRANTS_GRANTEE_UID + "=?",
2844f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            new String[]{String.valueOf(accountId), authTokenType,
2845f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    String.valueOf(uid)});
2846f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
2847f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
2848f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
2849f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
2850d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
285150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
285250cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    new UserHandle(accounts.userId));
2853d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2854d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
285556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
285656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    static final private String stringArrayToString(String[] value) {
285756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return value != null ? ("[" + TextUtils.join(",", value) + "]") : null;
285856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
285956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
286004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAccountFromCacheLocked(UserAccounts accounts, Account account) {
286104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final Account[] oldAccountsForType = accounts.accountCache.get(account.type);
2862f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (oldAccountsForType != null) {
2863f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            ArrayList<Account> newAccountsList = new ArrayList<Account>();
2864f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            for (Account curAccount : oldAccountsForType) {
2865f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (!curAccount.equals(account)) {
2866f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    newAccountsList.add(curAccount);
286756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                }
286856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
2869f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (newAccountsList.isEmpty()) {
287004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.remove(account.type);
2871f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } else {
2872f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Account[] newAccountsForType = new Account[newAccountsList.size()];
2873f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                newAccountsForType = newAccountsList.toArray(newAccountsForType);
287404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.put(account.type, newAccountsForType);
2875f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
287656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
287704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.userDataCache.remove(account);
287804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.authTokenCache.remove(account);
287956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
288056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
288156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    /**
288256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana     * This assumes that the caller has already checked that the account is not already present.
288356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana     */
288404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void insertAccountIntoCacheLocked(UserAccounts accounts, Account account) {
288504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        Account[] accountsForType = accounts.accountCache.get(account.type);
2886f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        int oldLength = (accountsForType != null) ? accountsForType.length : 0;
2887f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        Account[] newAccountsForType = new Account[oldLength + 1];
2888f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (accountsForType != null) {
2889f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
2890f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2891f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        newAccountsForType[oldLength] = account;
289204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.accountCache.put(account.type, newAccountsForType);
2893f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    }
2894f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana
2895df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered,
289627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            int callingUid, String callingPackage) {
2897df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
289827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                || callingUid == Process.myUid()) {
2899df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return unfiltered;
2900df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
29010c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani        UserInfo user = mUserManager.getUserInfo(userAccounts.userId);
29020c19bf524493f2feedf442d390c878fd1ca66d7bAmith Yamasani        if (user != null && user.isRestricted()) {
2903df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            String[] packages = mPackageManager.getPackagesForUid(callingUid);
29040ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            // If any of the packages is a white listed package, return the full set,
2905df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // otherwise return non-shared accounts only.
2906df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // This might be a temporary way to specify a whitelist
2907df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            String whiteList = mContext.getResources().getString(
2908df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    com.android.internal.R.string.config_appsAuthorizedForSharedAccounts);
2909df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            for (String packageName : packages) {
2910df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                if (whiteList.contains(";" + packageName + ";")) {
2911df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    return unfiltered;
2912df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2913df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
2914df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            ArrayList<Account> allowed = new ArrayList<Account>();
2915df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId);
2916df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered;
29170ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            String requiredAccountType = "";
29180ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            try {
2919e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                // If there's an explicit callingPackage specified, check if that package
2920e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                // opted in to see restricted accounts.
2921e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                if (callingPackage != null) {
2922e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                    PackageInfo pi = mPackageManager.getPackageInfo(callingPackage, 0);
29230ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    if (pi != null && pi.restrictedAccountType != null) {
29240ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        requiredAccountType = pi.restrictedAccountType;
2925e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                    }
2926e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                } else {
2927e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                    // Otherwise check if the callingUid has a package that has opted in
2928e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                    for (String packageName : packages) {
2929e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                        PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
2930e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                        if (pi != null && pi.restrictedAccountType != null) {
2931e3423097044e504c51c68ff88cb91baa1ca68ca9Amith Yamasani                            requiredAccountType = pi.restrictedAccountType;
293227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                            break;
293327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        }
2934df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    }
2935df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
29360ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            } catch (NameNotFoundException nnfe) {
29370ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            }
29380ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            for (Account account : unfiltered) {
29390ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                if (account.type.equals(requiredAccountType)) {
2940df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    allowed.add(account);
29410ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                } else {
29420ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    boolean found = false;
29430ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    for (Account shared : sharedAccounts) {
29440ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        if (shared.equals(account)) {
29450ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                            found = true;
29460ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                            break;
29470ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        }
29480ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    }
29490ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    if (!found) {
29500ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        allowed.add(account);
29510ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    }
2952df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2953df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
2954df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            Account[] filtered = new Account[allowed.size()];
2955df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            allowed.toArray(filtered);
2956df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return filtered;
2957df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        } else {
2958df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return unfiltered;
2959df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
2960df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    }
2961df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani
296227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    /*
296327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani     * packageName can be null. If not null, it should be used to filter out restricted accounts
296427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani     * that the package is not allowed to access.
296527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani     */
2966df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
296727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            int callingUid, String callingPackage) {
2968f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (accountType != null) {
296904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final Account[] accounts = userAccounts.accountCache.get(accountType);
2970f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (accounts == null) {
2971f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return EMPTY_ACCOUNT_ARRAY;
297256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            } else {
2973df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
297427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        callingUid, callingPackage);
2975f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2976f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2977f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            int totalLength = 0;
297804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (Account[] accounts : userAccounts.accountCache.values()) {
2979f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                totalLength += accounts.length;
2980f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2981f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (totalLength == 0) {
2982f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return EMPTY_ACCOUNT_ARRAY;
2983f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2984f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Account[] accounts = new Account[totalLength];
2985f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            totalLength = 0;
298604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (Account[] accountsOfType : userAccounts.accountCache.values()) {
2987f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                System.arraycopy(accountsOfType, 0, accounts, totalLength,
2988f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        accountsOfType.length);
2989f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                totalLength += accountsOfType.length;
299056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
299127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage);
299256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
299356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
299456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
299504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void writeUserDataIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
299604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Account account, String key, String value) {
299704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
2998f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (userDataForAccount == null) {
2999f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
300004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            accounts.userDataCache.put(account, userDataForAccount);
3001f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
3002f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (value == null) {
3003f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount.remove(key);
3004f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
3005f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount.put(key, value);
300656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
300756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
300856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
300904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
301004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Account account, String key, String value) {
301104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
3012f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (authTokensForAccount == null) {
3013f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
301404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            accounts.authTokenCache.put(account, authTokensForAccount);
3015f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
3016f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (value == null) {
3017f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount.remove(key);
3018f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
3019f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount.put(key, value);
302056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
302156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
302256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
302304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected String readAuthTokenInternal(UserAccounts accounts, Account account,
302404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String authTokenType) {
302504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
302604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
302756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            if (authTokensForAccount == null) {
302856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                // need to populate the cache for this account
302904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
3030f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
303104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.authTokenCache.put(account, authTokensForAccount);
303256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
303356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            return authTokensForAccount.get(authTokenType);
303456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
303556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
303656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
303704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected String readUserDataInternal(UserAccounts accounts, Account account, String key) {
303804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
303904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
304056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            if (userDataForAccount == null) {
304156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                // need to populate the cache for this account
304204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
3043f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
304404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.userDataCache.put(account, userDataForAccount);
304556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
304656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            return userDataForAccount.get(key);
304756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
304856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
304956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
3050f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected HashMap<String, String> readUserDataForAccountFromDatabaseLocked(
3051f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final SQLiteDatabase db, Account account) {
305256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        HashMap<String, String> userDataForAccount = new HashMap<String, String>();
305356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Cursor cursor = db.query(TABLE_EXTRAS,
305456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                COLUMNS_EXTRAS_KEY_AND_VALUE,
305556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                SELECTION_USERDATA_BY_ACCOUNT,
305656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                new String[]{account.name, account.type},
305756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                null, null, null);
305856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        try {
305956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            while (cursor.moveToNext()) {
306056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String tmpkey = cursor.getString(0);
306156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String value = cursor.getString(1);
306256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                userDataForAccount.put(tmpkey, value);
306356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
306456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        } finally {
306556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            cursor.close();
306656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
306756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return userDataForAccount;
306856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
306956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
3070f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected HashMap<String, String> readAuthTokensForAccountFromDatabaseLocked(
3071f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final SQLiteDatabase db, Account account) {
307256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        HashMap<String, String> authTokensForAccount = new HashMap<String, String>();
307356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Cursor cursor = db.query(TABLE_AUTHTOKENS,
307456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
307556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                SELECTION_AUTHTOKENS_BY_ACCOUNT,
307656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                new String[]{account.name, account.type},
307756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                null, null, null);
307856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        try {
307956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            while (cursor.moveToNext()) {
308056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String type = cursor.getString(0);
308156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String authToken = cursor.getString(1);
308256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                authTokensForAccount.put(type, authToken);
308356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
308456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        } finally {
308556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            cursor.close();
308656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
308756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return authTokensForAccount;
308856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
3089603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana}
3090