AccountManagerService.java revision 3df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8
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;
257a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.GrantCredentialsPermissionActivity;
267a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountAuthenticator;
277a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountAuthenticatorResponse;
287a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountManager;
297a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountManagerResponse;
303b4fcbc9f13bab6a2e9e5c37cc5e18fec7341c04Brett Chabotimport android.app.ActivityManager;
316ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.app.ActivityManagerNative;
32885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.Notification;
33885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.NotificationManager;
34885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.PendingIntent;
35a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.BroadcastReceiver;
36885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.ComponentName;
37a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.ContentValues;
38a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Context;
39a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Intent;
40a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.IntentFilter;
41b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintanaimport android.content.ServiceConnection;
42885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.ApplicationInfo;
43885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.PackageInfo;
44d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.PackageManager;
456ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
46d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.RegisteredServicesCache;
473ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanaimport android.content.pm.RegisteredServicesCacheListener;
486eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport android.content.pm.UserInfo;
49603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.Cursor;
50603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.DatabaseUtils;
51a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteDatabase;
52a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteOpenHelper;
53885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.os.Binder;
54a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Bundle;
55a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport android.os.Environment;
56a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Handler;
57a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.HandlerThread;
58a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.IBinder;
59a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Looper;
60a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Message;
61a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.RemoteException;
62a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.SystemClock;
63f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
64258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasaniimport android.os.UserManager;
65a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.text.TextUtils;
66a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.util.Log;
67d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.util.Pair;
686eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport android.util.Slog;
6904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasaniimport android.util.SparseArray;
70603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
71b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolacheimport com.android.internal.R;
7267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasaniimport com.android.internal.util.ArrayUtils;
7304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasaniimport com.android.internal.util.IndentingPrintWriter;
746ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Lists;
756ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Sets;
76b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
77a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport java.io.File;
78a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.FileDescriptor;
79a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.PrintWriter;
80a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.ArrayList;
8156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaimport java.util.Arrays;
82a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.Collection;
83d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.HashMap;
846ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport java.util.HashSet;
8556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaimport java.util.LinkedHashMap;
866eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport java.util.List;
872f36229db823d152f3efd879e751e81a601a75b0Andy McFaddenimport java.util.Map;
88d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicInteger;
89d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicReference;
90603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
91603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/**
92603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * A system service that provides  account, password, and authtoken management for all
93603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * accounts on the device. Some of these calls are implemented with the help of the corresponding
94603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * {@link IAccountAuthenticator} services. This service is not accessed by users directly,
95603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * instead one uses an instance of {@link AccountManager}, which can be accessed as follows:
9646703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom *    AccountManager accountManager = AccountManager.get(context);
973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana * @hide
98603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */
993ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanapublic class AccountManagerService
1003ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana        extends IAccountManager.Stub
1015ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana        implements RegisteredServicesCacheListener<AuthenticatorDescription> {
102603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TAG = "AccountManagerService";
103603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
104603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final int TIMEOUT_DELAY_MS = 1000 * 60;
105603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String DATABASE_NAME = "accounts.db";
10667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private static final int DATABASE_VERSION = 5;
107603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
108603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private final Context mContext;
109603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
11056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private final PackageManager mPackageManager;
111258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    private UserManager mUserManager;
11256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
113603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private HandlerThread mMessageThread;
114603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private final MessageHandler mMessageHandler;
115603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
116603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    // Messages that can be sent on mHandler
117603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final int MESSAGE_TIMED_OUT = 3;
118603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
11956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private final IAccountAuthenticatorCache mAuthenticatorCache;
120603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
121603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_ACCOUNTS = "accounts";
122603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_ID = "_id";
123603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_NAME = "name";
124603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_TYPE = "type";
1251cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static final String ACCOUNTS_TYPE_COUNT = "count(type)";
126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_PASSWORD = "password";
127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
128603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_AUTHTOKENS = "authtokens";
129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_ID = "_id";
130603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_ACCOUNTS_ID = "accounts_id";
131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_TYPE = "type";
132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_AUTHTOKEN = "authtoken";
133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
134d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String TABLE_GRANTS = "grants";
135d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_ACCOUNTS_ID = "accounts_id";
136d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_AUTH_TOKEN_TYPE = "auth_token_type";
137d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_GRANTEE_UID = "uid";
138d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
139603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_EXTRAS = "extras";
140603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_ID = "_id";
141603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_ACCOUNTS_ID = "accounts_id";
142603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_KEY = "key";
143603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_VALUE = "value";
144603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
145603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_META = "meta";
146603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String META_KEY = "key";
147603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String META_VALUE = "value";
148603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
14967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private static final String TABLE_SHARED_ACCOUNTS = "shared_accounts";
15067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
1511cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION =
1521cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks            new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT};
1537be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    private static final Intent ACCOUNTS_CHANGED_INTENT;
154a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
155d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String COUNT_OF_MATCHING_GRANTS = ""
156d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS
157d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " WHERE " + GRANTS_ACCOUNTS_ID + "=" + ACCOUNTS_ID
158d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + GRANTS_GRANTEE_UID + "=?"
159d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + GRANTS_AUTH_TOKEN_TYPE + "=?"
160d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + ACCOUNTS_NAME + "=?"
161d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + ACCOUNTS_TYPE + "=?";
162d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
16356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String SELECTION_AUTHTOKENS_BY_ACCOUNT =
16456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
16556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN = {AUTHTOKENS_TYPE,
16656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            AUTHTOKENS_AUTHTOKEN};
16756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
16856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String SELECTION_USERDATA_BY_ACCOUNT =
16956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            EXTRAS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
17056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String[] COLUMNS_EXTRAS_KEY_AND_VALUE = {EXTRAS_KEY, EXTRAS_VALUE};
17156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
172a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
173d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private final AtomicInteger mNotificationIds = new AtomicInteger(1);
174d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
17504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    static class UserAccounts {
17604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final int userId;
17704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final DatabaseHelper openHelper;
17804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
17904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                credentialsPermissionNotificationIds =
18004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
18104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final HashMap<Account, Integer> signinRequiredNotificationIds =
18204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, Integer>();
18304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final Object cacheLock = new Object();
18404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
185b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani        private final HashMap<String, Account[]> accountCache =
186b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani                new LinkedHashMap<String, Account[]>();
18704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
18804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private HashMap<Account, HashMap<String, String>> userDataCache =
18904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, HashMap<String, String>>();
19004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
19104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private HashMap<Account, HashMap<String, String>> authTokenCache =
19204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, HashMap<String, String>>();
19304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
19404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts(Context context, int userId) {
19504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            this.userId = userId;
19604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (cacheLock) {
19704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                openHelper = new DatabaseHelper(context, userId);
19804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
19904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
20004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
20104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
20204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private final SparseArray<UserAccounts> mUsers = new SparseArray<UserAccounts>();
20304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
204d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static AtomicReference<AccountManagerService> sThis =
205d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            new AtomicReference<AccountManagerService>();
20631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana    private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
2077be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
2087be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    static {
209f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana        ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
2107be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2117be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    }
2127be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
21356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
214d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
215d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * This should only be called by system code. One should only call this after the service
216d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * has started.
217d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @return a reference to the AccountManagerService instance
218d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
219d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
220d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    public static AccountManagerService getSingleton() {
221d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return sThis.get();
222d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
223603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
22456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    public AccountManagerService(Context context) {
22556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        this(context, context.getPackageManager(), new AccountAuthenticatorCache(context));
226603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
227603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
22856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    public AccountManagerService(Context context, PackageManager packageManager,
22956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            IAccountAuthenticatorCache authenticatorCache) {
230603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mContext = context;
23156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mPackageManager = packageManager;
232603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
233603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mMessageThread = new HandlerThread("AccountManagerService");
234603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mMessageThread.start();
235603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mMessageHandler = new MessageHandler(mMessageThread.getLooper());
236603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
23756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mAuthenticatorCache = authenticatorCache;
2385ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana        mAuthenticatorCache.setListener(this, null /* Handler */);
239603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
240d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        sThis.set(this);
241afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana
242c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        IntentFilter intentFilter = new IntentFilter();
243c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
244c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        intentFilter.addDataScheme("package");
245c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        mContext.registerReceiver(new BroadcastReceiver() {
246c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            @Override
247c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            public void onReceive(Context context1, Intent intent) {
24804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrantsAll();
249c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            }
250c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        }, intentFilter);
251c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana
252135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        IntentFilter userFilter = new IntentFilter();
253135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        userFilter.addAction(Intent.ACTION_USER_REMOVED);
25467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userFilter.addAction(Intent.ACTION_USER_STARTED);
25567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        mContext.registerReceiverAsUser(new BroadcastReceiver() {
256135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            @Override
257135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            public void onReceive(Context context, Intent intent) {
25867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                String action = intent.getAction();
25967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                if (Intent.ACTION_USER_REMOVED.equals(action)) {
26067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    onUserRemoved(intent);
26167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } else if (Intent.ACTION_USER_STARTED.equals(action)) {
26267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    onUserStarted(intent);
26367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
264135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            }
26567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }, UserHandle.ALL, userFilter, null, null);
266afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana    }
267afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana
26826ff6626fc4ee0ae46f01ad309b366921da589feKenny Root    public void systemReady() {
26926ff6626fc4ee0ae46f01ad309b366921da589feKenny Root    }
27026ff6626fc4ee0ae46f01ad309b366921da589feKenny Root
271258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    private UserManager getUserManager() {
272258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        if (mUserManager == null) {
273258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani            mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
274258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        }
275258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        return mUserManager;
276258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    }
277258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani
27804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private UserAccounts initUser(int userId) {
27904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
28004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            UserAccounts accounts = mUsers.get(userId);
28104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            if (accounts == null) {
28204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts = new UserAccounts(mContext, userId);
28304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                mUsers.append(userId, accounts);
28404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrants(accounts);
2856eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey                validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
28604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
28704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return accounts;
28804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
28904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
29004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
29104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void purgeOldGrantsAll() {
29204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
29304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (int i = 0; i < mUsers.size(); i++) {
29404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrants(mUsers.valueAt(i));
29504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
29604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
29704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
29804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
29904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void purgeOldGrants(UserAccounts accounts) {
30004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
30104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
302c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            final Cursor cursor = db.query(TABLE_GRANTS,
303c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    new String[]{GRANTS_GRANTEE_UID},
304c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    null, null, GRANTS_GRANTEE_UID, null, null);
305c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            try {
306c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                while (cursor.moveToNext()) {
307c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    final int uid = cursor.getInt(0);
308c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
309c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    if (packageExists) {
310c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                        continue;
311c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    }
312c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    Log.d(TAG, "deleting grants for UID " + uid
313c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                            + " because its package is no longer installed");
314c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
315c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                            new String[]{Integer.toString(uid)});
316c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                }
317c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            } finally {
318c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                cursor.close();
319c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            }
320c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        }
321c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana    }
322c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana
3236eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /**
3246eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * Validate internal set of accounts against installed authenticators for
3256eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * given user. Clears cached authenticators before validating.
3266eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     */
3276eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    public void validateAccounts(int userId) {
3286eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final UserAccounts accounts = getUserAccounts(userId);
3296eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3306eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        // Invalidate user-specific cache to make sure we catch any
3316eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        // removed authenticators.
3326eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
3336eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
3346eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3356eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /**
3366eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * Validate internal set of accounts against installed authenticators for
3376eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * given user. Clear cached authenticators before validating when requested.
3386eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     */
3396eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    private void validateAccountsInternal(
3406eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            UserAccounts accounts, boolean invalidateAuthenticatorCache) {
3416eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        if (invalidateAuthenticatorCache) {
3426eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            mAuthenticatorCache.invalidateCache(accounts.userId);
3436eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        }
3446eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3456ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
3466ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
3476ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.getAllServices(accounts.userId)) {
3486ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            knownAuth.add(service.type);
3496ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
3506ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
35104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
35204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
353f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            boolean accountDeleted = false;
354f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Cursor cursor = db.query(TABLE_ACCOUNTS,
355f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
356f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    null, null, null, null, null);
357f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
35804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.clear();
35956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final HashMap<String, ArrayList<String>> accountNamesByType =
360b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani                        new LinkedHashMap<String, ArrayList<String>>();
36156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                while (cursor.moveToNext()) {
36256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final long accountId = cursor.getLong(0);
36356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountType = cursor.getString(1);
36456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountName = cursor.getString(2);
3656ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
3666ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
3676eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey                        Slog.w(TAG, "deleting account " + accountName + " because type "
36856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + accountType + " no longer has a registered authenticator");
36956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
37056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountDeleted = true;
37156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        final Account account = new Account(accountName, accountType);
37204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        accounts.userDataCache.remove(account);
37304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        accounts.authTokenCache.remove(account);
37456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    } else {
37556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        ArrayList<String> accountNames = accountNamesByType.get(accountType);
37656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (accountNames == null) {
37756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            accountNames = new ArrayList<String>();
37856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            accountNamesByType.put(accountType, accountNames);
37956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
38056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountNames.add(accountName);
38156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
38256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                }
3832f36229db823d152f3efd879e751e81a601a75b0Andy McFadden                for (Map.Entry<String, ArrayList<String>> cur
384f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        : accountNamesByType.entrySet()) {
38556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountType = cur.getKey();
38656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final ArrayList<String> accountNames = cur.getValue();
38756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final Account[] accountsForType = new Account[accountNames.size()];
38856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    int i = 0;
38956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    for (String accountName : accountNames) {
39056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountsForType[i] = new Account(accountName, accountType);
39156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        ++i;
39256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
39304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    accounts.accountCache.put(accountType, accountsForType);
394afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana                }
395f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
396f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                cursor.close();
397f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountDeleted) {
39804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    sendAccountsChangedBroadcast(accounts.userId);
399f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
400afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana            }
401afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana        }
4023ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana    }
4033ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana
40404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private UserAccounts getUserAccountsForCaller() {
405f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getUserAccounts(UserHandle.getCallingUserId());
40604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
40704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
40804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected UserAccounts getUserAccounts(int userId) {
40904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
41004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            UserAccounts accounts = mUsers.get(userId);
41104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            if (accounts == null) {
41204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts = initUser(userId);
41304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                mUsers.append(userId, accounts);
41404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
41504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return accounts;
41604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
41704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
41804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
419135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    private void onUserRemoved(Intent intent) {
4202a00329c6d55c6cd9166e01963d7410e95d80d21Amith Yamasani        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
421135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        if (userId < 1) return;
422135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
423135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        UserAccounts accounts;
424135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        synchronized (mUsers) {
425135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            accounts = mUsers.get(userId);
426135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            mUsers.remove(userId);
427135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
428135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        if (accounts == null) {
429135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            File dbFile = new File(getDatabaseName(userId));
430135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            dbFile.delete();
431135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            return;
432135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
433135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
434135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        synchronized (accounts.cacheLock) {
435135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            accounts.openHelper.close();
436135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            File dbFile = new File(getDatabaseName(userId));
437135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            dbFile.delete();
438135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
439135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    }
440135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
44167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private void onUserStarted(Intent intent) {
44267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
44367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (userId < 1) return;
44467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
44567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        // Check if there's a shared account that needs to be created as an account
44667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] sharedAccounts = getSharedAccountsAsUser(userId);
44767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (sharedAccounts == null || sharedAccounts.length == 0) return;
44867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] accounts = getAccountsAsUser(null, userId);
44967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        for (Account sa : sharedAccounts) {
45067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (ArrayUtils.contains(accounts, sa)) continue;
45167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Account doesn't exist. Copy it now.
45267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            copyAccountToUser(sa, UserHandle.USER_OWNER, userId);
45367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
45467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
45567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
4566ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    @Override
4576ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    public void onServiceChanged(AuthenticatorDescription desc, int userId, boolean removed) {
4586eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        validateAccountsInternal(getUserAccounts(userId), false /* invalidateAuthenticatorCache */);
459603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
460603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
461a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String getPassword(Account account) {
46256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
46356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getPassword: " + account
46456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
46556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
46656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
467382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
468d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
469d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
47004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
47126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
472603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
47304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readPasswordInternal(accounts, account);
474603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
47526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
476603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
477603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
478603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
47904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private String readPasswordInternal(UserAccounts accounts, Account account) {
48031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null) {
48131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return null;
48231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
48331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana
48404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
48504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
486f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
487f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
488f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{account.name, account.type}, null, null, null);
489f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
490f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (cursor.moveToNext()) {
491f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return cursor.getString(0);
492f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
493f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return null;
494f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
495f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                cursor.close();
496ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
497ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
498ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
499ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
500a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String getUserData(Account account, String key) {
50156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
50256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getUserData: " + account
50356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", key " + key
50456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
50556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
50656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
507382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
508382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (key == null) throw new IllegalArgumentException("key is null");
509d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
51004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
51126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
512603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
51304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readUserDataInternal(accounts, account, key);
514ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
515ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
516ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
517ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
518ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
5199788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana    public AuthenticatorDescription[] getAuthenticatorTypes() {
52056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
52156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAuthenticatorTypes: "
52256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + "caller's uid " + Binder.getCallingUid()
52356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
52456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
5256ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int userId = UserHandle.getCallingUserId();
5266ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final long identityToken = clearCallingIdentity();
52726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
5289788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
5296ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
5309788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            AuthenticatorDescription[] types =
5319788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana                    new AuthenticatorDescription[authenticatorCollection.size()];
53226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            int i = 0;
5339788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
534718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana                    : authenticatorCollection) {
535718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana                types[i] = authenticator.type;
53626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                i++;
53726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
53826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            return types;
53926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
54026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
541a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
542a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
543a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
5443df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia    @Override
545a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public boolean addAccount(Account account, String password, Bundle extras) {
54656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
54756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "addAccount: " + account
54856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
54956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
55056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
551382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
552d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
5533df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia        /*
5543df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * Child users are not allowed to add accounts. Only the accounts that are
5553df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * shared by the parent profile can be added to child profile.
5563df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         *
5573df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * TODO: Only allow accounts that were shared to be added by
5583df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         *     a limited user.
5593df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         */
560d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
56104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
562603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        // fails if the account already exists
56326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
564603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
56567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return addAccountInternal(accounts, account, password, extras, false);
56667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
56767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            restoreCallingIdentity(identityToken);
56867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
56967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
57067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
57167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private boolean copyAccountToUser(final Account account, int userFrom, int userTo) {
57267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        final UserAccounts fromAccounts = getUserAccounts(userFrom);
57367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        final UserAccounts toAccounts = getUserAccounts(userTo);
57467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (fromAccounts == null || toAccounts == null) {
57567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return false;
57667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
57767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
57867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long identityToken = clearCallingIdentity();
57967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
58067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            new Session(fromAccounts, null, account.type, false,
58167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    false /* stripAuthTokenFromResult */) {
58267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                protected String toDebugString(long now) {
58367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    return super.toDebugString(now) + ", getAccountCredentialsForClone"
58467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            + ", " + account.type;
58567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
58667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
58767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void run() throws RemoteException {
58867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mAuthenticator.getAccountCredentialsForCloning(this, account);
58967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
59067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
59167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onResult(Bundle result) {
59267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (result != null) {
59367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
59467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // Create a Session for the target user and pass in the bundle
59567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            completeCloningAccount(result, account, toAccounts);
59667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        }
59767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        return;
59867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    } else {
59967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        super.onResult(result);
60067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
60167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
60267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }.bind();
603ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
604ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
605ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
60667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return true;
60767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
60867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
60967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    void completeCloningAccount(final Bundle result, final Account account,
61067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            final UserAccounts targetUser) {
61167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long id = clearCallingIdentity();
61267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
61367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            new Session(targetUser, null, account.type, false,
61467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    false /* stripAuthTokenFromResult */) {
61567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                protected String toDebugString(long now) {
61667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    return super.toDebugString(now) + ", getAccountCredentialsForClone"
61767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            + ", " + account.type;
61867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
61967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
62067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void run() throws RemoteException {
62167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mAuthenticator.addAccountFromCredentials(this, account, result);
62267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
62367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
62467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onResult(Bundle result) {
62567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (result != null) {
62667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
62767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Anything?
62867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        } else {
62967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Show error notification
63067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Should we remove the shadow account to avoid retries?
63167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        }
63267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        return;
63367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    } else {
63467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        super.onResult(result);
63567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
63667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
63767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
63867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onError(int errorCode, String errorMessage) {
63967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    super.onError(errorCode,  errorMessage);
64067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    // TODO: Show error notification to user
64167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    // TODO: Should we remove the shadow account so that it doesn't keep trying?
64267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
64367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
64467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }.bind();
64567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
64667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            restoreCallingIdentity(id);
64767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
648ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
649ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
65004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
65167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            Bundle extras, boolean restricted) {
652743dfad2a51e016ddb741c104317637089187753Fred Quintana        if (account == null) {
653743dfad2a51e016ddb741c104317637089187753Fred Quintana            return false;
654743dfad2a51e016ddb741c104317637089187753Fred Quintana        }
65504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
65604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
657f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
658f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
659f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long numMatches = DatabaseUtils.longForQuery(db,
660f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        "select count(*) from " + TABLE_ACCOUNTS
661f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
662f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        new String[]{account.name, account.type});
663f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (numMatches > 0) {
664f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    Log.w(TAG, "insertAccountIntoDatabase: " + account
665f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            + ", skipping since the account already exists");
666f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
667f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
668f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                ContentValues values = new ContentValues();
669f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_NAME, account.name);
670f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_TYPE, account.type);
671f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_PASSWORD, password);
672f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
673f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
674f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    Log.w(TAG, "insertAccountIntoDatabase: " + account
675f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            + ", skipping the DB insert failed");
676f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
677f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
678f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (extras != null) {
679f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    for (String key : extras.keySet()) {
680f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        final String value = extras.getString(key);
681f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        if (insertExtraLocked(db, accountId, key, value) < 0) {
682f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            Log.w(TAG, "insertAccountIntoDatabase: " + account
683f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    + ", skipping since insertExtra failed for key " + key);
684f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            return false;
685f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        }
686603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    }
687603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                }
688f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.setTransactionSuccessful();
68904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                insertAccountIntoCacheLocked(accounts, account);
690f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
691f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
692603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
69304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
694f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            return true;
695603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
696603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
697603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
698f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long insertExtraLocked(SQLiteDatabase db, long accountId, String key, String value) {
699603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        ContentValues values = new ContentValues();
700603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_KEY, key);
701603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_ACCOUNTS_ID, accountId);
702603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_VALUE, value);
703603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values);
704603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
705603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
7063084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana    public void hasFeatures(IAccountManagerResponse response,
707bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            Account account, String[] features) {
70856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
70956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "hasFeatures: " + account
71056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
71156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", features " + stringArrayToString(features)
71256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
71356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
71456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
715382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
716382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
717382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (features == null) throw new IllegalArgumentException("features is null");
718bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        checkReadAccountsPermission();
71904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
720bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        long identityToken = clearCallingIdentity();
721bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        try {
72204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new TestFeaturesSession(accounts, response, account, features).bind();
723bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        } finally {
724bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            restoreCallingIdentity(identityToken);
725bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
726bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    }
727bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
728bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    private class TestFeaturesSession extends Session {
729bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        private final String[] mFeatures;
730bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        private final Account mAccount;
731bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
73204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public TestFeaturesSession(UserAccounts accounts, IAccountManagerResponse response,
733bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                Account account, String[] features) {
73404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, account.type, false /* expectActivityLaunch */,
7358570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
736bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            mFeatures = features;
737bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            mAccount = account;
738bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
739bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
740bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        public void run() throws RemoteException {
741bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            try {
742bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                mAuthenticator.hasFeatures(this, mAccount, mFeatures);
743bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            } catch (RemoteException e) {
744bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
745bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            }
746bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
747bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
748bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        public void onResult(Bundle result) {
749bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
750bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            if (response != null) {
751bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                try {
752bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    if (result == null) {
753166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
754bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                        return;
755bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    }
75656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
75756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
75856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
75956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
760bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    final Bundle newResult = new Bundle();
761bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    newResult.putBoolean(AccountManager.KEY_BOOLEAN_RESULT,
762bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                            result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false));
763bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    response.onResult(newResult);
764bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                } catch (RemoteException e) {
765bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
766bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
767bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
768bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    }
769bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                }
770bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            }
771bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
772bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
773bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        protected String toDebugString(long now) {
7743084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana            return super.toDebugString(now) + ", hasFeatures"
775bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    + ", " + mAccount
776bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
777bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
778bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    }
779307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
780ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    public void removeAccount(IAccountManagerResponse response, Account account) {
78156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
78256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "removeAccount: " + account
78356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
78456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
78556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
78656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
787382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
788382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
789d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
79050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        UserHandle user = Binder.getCallingUserHandle();
79104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
792e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        if (!canUserModifyAccounts(Binder.getCallingUid())) {
793e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            try {
794e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
795e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                        "User cannot modify accounts");
796e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            } catch (RemoteException re) {
797e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            }
798e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        }
799e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani
80026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
801ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache
80250cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
80304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized(accounts.credentialsPermissionNotificationIds) {
804ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache            for (Pair<Pair<Account, String>, Integer> pair:
80504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.credentialsPermissionNotificationIds.keySet()) {
806ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache                if (account.equals(pair.first.first)) {
80704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    int id = accounts.credentialsPermissionNotificationIds.get(pair);
80850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    cancelNotification(id, user);
809ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache                }
810ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache            }
811ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache        }
812ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache
81326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
81404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new RemoveAccountSession(accounts, response, account).bind();
81526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
81626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
817a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
818603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
819603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
820ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    private class RemoveAccountSession extends Session {
821ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        final Account mAccount;
82204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response,
82304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                Account account) {
82404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, account.type, false /* expectActivityLaunch */,
8258570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
826ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            mAccount = account;
827ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
828ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
829ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        protected String toDebugString(long now) {
830ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            return super.toDebugString(now) + ", removeAccount"
831ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    + ", account " + mAccount;
832ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
833ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
834ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        public void run() throws RemoteException {
835ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            mAuthenticator.getAccountRemovalAllowed(this, mAccount);
836ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
837ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
838ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        public void onResult(Bundle result) {
839f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
840f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    && !result.containsKey(AccountManager.KEY_INTENT)) {
841f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
842ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                if (removalAllowed) {
84304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    removeAccountInternal(mAccounts, mAccount);
844ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                }
845ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                IAccountManagerResponse response = getResponseAndClose();
846ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                if (response != null) {
84756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
84856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
84956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
85056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
851ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    Bundle result2 = new Bundle();
852f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result2.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, removalAllowed);
853ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    try {
854ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                        response.onResult(result2);
855ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    } catch (RemoteException e) {
856ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                        // ignore
857ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    }
858ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                }
859ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
860ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            super.onResult(result);
861ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
862ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
863ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
86404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    /* For testing */
865f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected void removeAccountInternal(Account account) {
86604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        removeAccountInternal(getUserAccountsForCaller(), account);
86704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
86804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
86904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAccountInternal(UserAccounts accounts, Account account) {
87004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
87104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
872f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
873f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{account.name, account.type});
87404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            removeAccountFromCacheLocked(accounts, account);
87504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
876f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
87767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (accounts.userId == UserHandle.USER_OWNER) {
87867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Owner's account was removed, remove from any users that are sharing
87967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // this account.
88067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            long id = Binder.clearCallingIdentity();
88167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            try {
88267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                List<UserInfo> users = mUserManager.getUsers(true);
88367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                for (UserInfo user : users) {
88467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (!user.isPrimary() && user.isRestricted()) {
88567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        removeSharedAccountAsUser(account, user.id);
88667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
88767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
88867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            } finally {
88967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                Binder.restoreCallingIdentity(id);
89067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
89167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
892ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
893ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
894a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void invalidateAuthToken(String accountType, String authToken) {
89556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
89656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "invalidateAuthToken: accountType " + accountType
89756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
89856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
89956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
900382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
901382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authToken == null) throw new IllegalArgumentException("authToken is null");
902b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        checkManageAccountsOrUseCredentialsPermissions();
90304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
90426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
905603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
90604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
90704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
908f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.beginTransaction();
909f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                try {
91004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    invalidateAuthTokenLocked(accounts, db, accountType, authToken);
911f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
912f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } finally {
913f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.endTransaction();
914f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
91526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
916603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
91726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
918603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
919603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
920603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
92104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db,
92204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String accountType, String authToken) {
923ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        if (authToken == null || accountType == null) {
924ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            return;
925ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
9263326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        Cursor cursor = db.rawQuery(
9273326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                "SELECT " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID
9283326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME
9293326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + ", " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_TYPE
9303326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " FROM " + TABLE_ACCOUNTS
9313326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " JOIN " + TABLE_AUTHTOKENS
9323326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " ON " + TABLE_ACCOUNTS + "." + ACCOUNTS_ID
9333326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " = " + AUTHTOKENS_ACCOUNTS_ID
9343326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " WHERE " + AUTHTOKENS_AUTHTOKEN + " = ? AND "
9353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " = ?",
9363326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                new String[]{authToken, accountType});
9373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        try {
9383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            while (cursor.moveToNext()) {
9393326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                long authTokenId = cursor.getLong(0);
9403326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                String accountName = cursor.getString(1);
9413326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                String authTokenType = cursor.getString(2);
9423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null);
94304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                writeAuthTokenIntoCacheLocked(accounts, db, new Account(accountName, accountType),
944f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        authTokenType, null);
945603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
9463326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        } finally {
9473326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            cursor.close();
948603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
949603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
950603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
95104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean saveAuthTokenToDatabase(UserAccounts accounts, Account account, String type,
95204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String authToken) {
95331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || type == null) {
95431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return false;
95531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
95650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        cancelNotification(getSigninRequiredNotificationId(accounts, account),
95750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                new UserHandle(accounts.userId));
95804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
95904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
960f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
961f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
962f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
963f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
964f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
965f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
966f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.delete(TABLE_AUTHTOKENS,
967f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
968f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        new String[]{type});
969f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                ContentValues values = new ContentValues();
970f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
971f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_TYPE, type);
972f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_AUTHTOKEN, authToken);
973f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (db.insert(TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values) >= 0) {
974f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
97504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    writeAuthTokenIntoCacheLocked(accounts, db, account, type, authToken);
976f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return true;
977f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
9783326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return false;
979f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
980f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
9813326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
982603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
983603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
984603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
985a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String peekAuthToken(Account account, String authTokenType) {
98656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
98756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "peekAuthToken: " + account
98856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
98956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
99056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
99156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
992382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
993382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
994d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
99504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
99626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
99726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
99804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readAuthTokenInternal(accounts, account, authTokenType);
99926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
100026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
1001603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1002603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1003603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1004a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setAuthToken(Account account, String authTokenType, String authToken) {
100556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
100656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setAuthToken: " + account
100756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
100856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
100956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
101056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1011382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1012382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1013d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
101404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
101526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
101626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
101704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            saveAuthTokenToDatabase(accounts, account, authTokenType, authToken);
101826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
101926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
102026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1021603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1022603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1023a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setPassword(Account account, String password) {
102456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
102556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setAuthToken: " + account
102656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
102756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
102856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1029382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1030d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
103104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
103226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
103326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
103404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setPasswordInternal(accounts, account, password);
103526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
103626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
103726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1038603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1039603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
104004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void setPasswordInternal(UserAccounts accounts, Account account, String password) {
104131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null) {
104231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
104331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
104404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
104504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1046f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1047f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1048f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                final ContentValues values = new ContentValues();
1049f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_PASSWORD, password);
1050f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                final long accountId = getAccountIdLocked(db, account);
1051f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
1052f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    final String[] argsAccountId = {String.valueOf(accountId)};
1053f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
1054f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
105504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    accounts.authTokenCache.remove(account);
1056f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
1057f5ffe89e736caee1419f0acb469565d5100b8fb8Costin Manolache                }
1058f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1059f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
1060d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana            }
106104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
1062d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana        }
10633ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana    }
10643ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana
106504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void sendAccountsChangedBroadcast(int userId) {
106656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Log.i(TAG, "the accounts changed, sending broadcast of "
106756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                + ACCOUNTS_CHANGED_INTENT.getAction());
106879af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
10693326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
10703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
1071a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void clearPassword(Account account) {
107256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
107356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "clearPassword: " + account
107456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
107556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
107656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1077382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1078d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
107904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
108026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
108126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
108204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setPasswordInternal(accounts, account, null);
108326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
108426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
108526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1086603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1087603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1088a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setUserData(Account account, String key, String value) {
108956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
109056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setUserData: " + account
109156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", key " + key
109256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
109356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
109456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1095382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (key == null) throw new IllegalArgumentException("key is null");
1096382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1097d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
109804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
109926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
1100603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
110104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setUserdataInternal(accounts, account, key, value);
1102ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
1103ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
1104ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
1105ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
1106ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
110704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void setUserdataInternal(UserAccounts accounts, Account account, String key,
110804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String value) {
110931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || key == null) {
111031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
111131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
111204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
111304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1114f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1115f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1116f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
1117f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
1118ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    return;
111926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1120f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long extrasId = getExtrasIdLocked(db, accountId, key);
1121f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (extrasId < 0 ) {
1122f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    extrasId = insertExtraLocked(db, accountId, key, value);
1123f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (extrasId < 0) {
1124f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        return;
1125f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
1126f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } else {
1127f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ContentValues values = new ContentValues();
1128f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(EXTRAS_VALUE, value);
1129f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
1130f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        return;
1131f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
1132ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
1133f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
113404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                writeUserDataIntoCacheLocked(accounts, db, account, key, value);
1135f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.setTransactionSuccessful();
1136f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1137f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
1138603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1139603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1140603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1141603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1142d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void onResult(IAccountManagerResponse response, Bundle result) {
114356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (result == null) {
114456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.e(TAG, "the result is unexpectedly null", new Exception());
114556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
114656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
114756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
114856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + response);
114956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1150d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        try {
1151d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            response.onResult(result);
1152d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        } catch (RemoteException e) {
1153d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // if the caller is dead then there is no one to care about remote
1154d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // exceptions
1155d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1156d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                Log.v(TAG, "failure while notifying response", e);
1157d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1158d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1159d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1160d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1161d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType,
1162d9640ec712806508877868d08aafaa2d715ff441Fred Quintana                                  final String authTokenType)
1163d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throws RemoteException {
1164d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
11655f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
11665f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1167d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        final int callingUid = getCallingUid();
1168d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        clearCallingIdentity();
1169d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (callingUid != android.os.Process.SYSTEM_UID) {
1170d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throw new SecurityException("can only call from system");
1171d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
1172f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
11735f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        long identityToken = clearCallingIdentity();
11745f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        try {
1175d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            new Session(accounts, response, accountType, false,
11765f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    false /* stripAuthTokenFromResult */) {
11775f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                protected String toDebugString(long now) {
11785f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    return super.toDebugString(now) + ", getAuthTokenLabel"
1179d9640ec712806508877868d08aafaa2d715ff441Fred Quintana                            + ", " + accountType
11805f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                            + ", authTokenType " + authTokenType;
11815f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
11825f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
11835f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                public void run() throws RemoteException {
11845f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    mAuthenticator.getAuthTokenLabel(this, authTokenType);
11855f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
11865f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
11875f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                public void onResult(Bundle result) {
11885f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    if (result != null) {
11895f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
11905f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        Bundle bundle = new Bundle();
11915f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, label);
11925f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        super.onResult(bundle);
11935f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        return;
11945f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    } else {
11955f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        super.onResult(result);
11965f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    }
11975f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
11985f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            }.bind();
11995f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        } finally {
12005f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            restoreCallingIdentity(identityToken);
12015f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        }
12025f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache    }
12035f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1204a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void getAuthToken(IAccountManagerResponse response, final Account account,
1205a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final String authTokenType, final boolean notifyOnAuthFailure,
1206c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache            final boolean expectActivityLaunch, Bundle loginOptionsIn) {
120756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
120856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAuthToken: " + account
120956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
121056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
121156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", notifyOnAuthFailure " + notifyOnAuthFailure
121256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
121356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
121456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
121556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1216382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1217382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1218382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1219d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
12204120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        final UserAccounts accounts = getUserAccountsForCaller();
12216ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
12226ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        authenticatorInfo = mAuthenticatorCache.getServiceInfo(
12236ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                AuthenticatorDescription.newKey(account.type), accounts.userId);
1224a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        final boolean customTokens =
1225a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            authenticatorInfo != null && authenticatorInfo.type.customTokens;
1226a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache
1227a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        // skip the check if customTokens
1228b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int callerUid = Binder.getCallingUid();
1229a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        final boolean permissionGranted = customTokens ||
1230a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            permissionIsGranted(account, authTokenType, callerUid);
1231a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache
1232c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache        final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
1233c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache            loginOptionsIn;
1234b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        // let authenticator know the identity of the caller
1235b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
1236b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
1237b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        if (notifyOnAuthFailure) {
1238b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache            loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
1239a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        }
12406ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
124126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
124226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
1243d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // if the caller has permission, do the peek. otherwise go the more expensive
1244d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // route of starting a Session
1245a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            if (!customTokens && permissionGranted) {
124604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                String authToken = readAuthTokenInternal(accounts, account, authTokenType);
1247d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                if (authToken != null) {
124826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    Bundle result = new Bundle();
1249f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
1250f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
1251f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
1252d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    onResult(response, result);
1253d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    return;
1254a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
1255a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1256603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
125704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
12588570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    false /* stripAuthTokenFromResult */) {
125926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
126026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (loginOptions != null) loginOptions.keySet();
126126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", getAuthToken"
126226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account
126326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", authTokenType " + authTokenType
126426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", loginOptions " + loginOptions
126526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", notifyOnAuthFailure " + notifyOnAuthFailure;
126626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1267a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
126826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
1269d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    // If the caller doesn't have permission then create and return the
1270d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    // "grant permission" intent instead of the "getAuthToken" intent.
1271d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    if (!permissionGranted) {
1272d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        mAuthenticator.getAuthTokenLabel(this, authTokenType);
1273d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    } else {
1274d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
1275d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    }
127626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1277a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
127826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void onResult(Bundle result) {
127926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (result != null) {
1280f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
1281d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            Intent intent = newGrantCredentialsPermissionIntent(account, callerUid,
1282d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                                    new AccountAuthenticatorResponse(this),
1283d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                                    authTokenType,
1284f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                    result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
1285d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            Bundle bundle = new Bundle();
1286f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            bundle.putParcelable(AccountManager.KEY_INTENT, intent);
1287d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            onResult(bundle);
1288d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            return;
1289d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        }
1290f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
129126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                        if (authToken != null) {
1292f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
1293f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
129426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
1295f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
129626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                                        "the type and name should not be empty");
129726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                                return;
129826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            }
1299a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                            if (!customTokens) {
130004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                                saveAuthTokenToDatabase(mAccounts, new Account(name, type),
1301a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                                        authTokenType, authToken);
1302a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                            }
1303a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        }
1304603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1305f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
1306d606045070dcf6a011e49a7711d2f17d8f2de8c1Costin Manolache                        if (intent != null && notifyOnAuthFailure && !customTokens) {
130704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                            doNotification(mAccounts,
1308f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                    account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
13094120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                                    intent, accounts.userId);
131026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                        }
1311a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
131226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    super.onResult(result);
1313a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
131426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
131526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
131626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
131726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1318603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1319603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
13204120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    private void createNoCredentialsPermissionNotification(Account account, Intent intent,
13214120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            int userId) {
1322d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        int uid = intent.getIntExtra(
1323d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
1324d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        String authTokenType = intent.getStringExtra(
1325d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE);
1326d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        String authTokenLabel = intent.getStringExtra(
1327d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
1328d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1329d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
1330d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                0 /* when */);
1331ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer        final String titleAndSubtitle =
1332ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer                mContext.getString(R.string.permission_request_notification_with_subtitle,
1333ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer                account.name);
1334ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer        final int index = titleAndSubtitle.indexOf('\n');
133585e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        String title = titleAndSubtitle;
133685e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        String subtitle = "";
133785e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        if (index > 0) {
133885e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache            title = titleAndSubtitle.substring(0, index);
13393df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia            subtitle = titleAndSubtitle.substring(index + 1);
134085e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        }
134150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        UserHandle user = new UserHandle(userId);
13424120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        n.setLatestEventInfo(mContext, title, subtitle,
13434120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                PendingIntent.getActivityAsUser(mContext, 0, intent,
134450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                        PendingIntent.FLAG_CANCEL_CURRENT, null, user));
134550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        installNotification(getCredentialPermissionNotificationId(
134650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                account, authTokenType, uid), n, user);
1347d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1348d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
13495f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
13505f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
1351d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1352d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
135346703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom        // See FLAG_ACTIVITY_NEW_TASK docs for limitations and benefits of the flag.
13549ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        // Since it was set in Eclair+ we can't change it without breaking apps using
13559ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        // the intent from a non-Activity context.
13569ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1357d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.addCategory(
1358d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid)));
13595f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1360d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
1361d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
1362d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
1363d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid);
13645f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1365d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return intent;
1366d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1367d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1368d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
1369d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            int uid) {
1370d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Integer id;
1371f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
137204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.credentialsPermissionNotificationIds) {
1373d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            final Pair<Pair<Account, String>, Integer> key =
1374d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    new Pair<Pair<Account, String>, Integer>(
1375d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            new Pair<Account, String>(account, authTokenType), uid);
137604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            id = accounts.credentialsPermissionNotificationIds.get(key);
1377d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (id == null) {
1378d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                id = mNotificationIds.incrementAndGet();
137904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.credentialsPermissionNotificationIds.put(key, id);
1380d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1381d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1382d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return id;
1383d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1384d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
138504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private Integer getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
1386d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Integer id;
138704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.signinRequiredNotificationIds) {
138804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            id = accounts.signinRequiredNotificationIds.get(account);
1389d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (id == null) {
1390d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                id = mNotificationIds.incrementAndGet();
139104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.signinRequiredNotificationIds.put(account, id);
1392d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1393d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1394d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return id;
1395d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1396d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
13973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    public void addAcount(final IAccountManagerResponse response, final String accountType,
13983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            final String authTokenType, final String[] requiredFeatures,
1399b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache            final boolean expectActivityLaunch, final Bundle optionsIn) {
140056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
140156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "addAccount: accountType " + accountType
140256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
140356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
140456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", requiredFeatures " + stringArrayToString(requiredFeatures)
140556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
140656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
140756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
140856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1409382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1410382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
1411d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
1412b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
141371e6c697e54a43d357cc25d87a446d140f17396aAmith Yamasani        // Is user disallowed from modifying accounts?
141471e6c697e54a43d357cc25d87a446d140f17396aAmith Yamasani        if (getUserManager().getUserRestrictions(Binder.getCallingUserHandle())
141571e6c697e54a43d357cc25d87a446d140f17396aAmith Yamasani                .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
1416df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            try {
1417df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
1418df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        "User is not allowed to add an account!");
1419df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            } catch (RemoteException re) {
1420df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
1421df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return;
1422df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
1423df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani
142404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
1425b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int pid = Binder.getCallingPid();
1426b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int uid = Binder.getCallingUid();
1427b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
1428b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        options.putInt(AccountManager.KEY_CALLER_UID, uid);
1429b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        options.putInt(AccountManager.KEY_CALLER_PID, pid);
1430b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
143126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
143226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
143304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, accountType, expectActivityLaunch,
14348570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
143526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
14363348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
14373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            options);
143826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1439a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
144026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
144126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", addAccount"
14423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + ", accountType " + accountType
14433326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + ", requiredFeatures "
14443326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + (requiredFeatures != null
14453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                              ? TextUtils.join(",", requiredFeatures)
14463326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                              : null);
144726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
144826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
144926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
145026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
145126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1452603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1453603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
14542c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
14552c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public void confirmCredentialsAsUser(IAccountManagerResponse response,
14562c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            final Account account, final Bundle options, final boolean expectActivityLaunch,
14572c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            int userId) {
14582c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        // Only allow the system process to read accounts of other users
14592c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        if (userId != UserHandle.getCallingUserId()
14602c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                && Binder.getCallingUid() != android.os.Process.myUid()) {
14612c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            throw new SecurityException("User " + UserHandle.getCallingUserId()
14622c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    + " trying to confirm account credentials for " + userId);
14632c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        }
14642c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
146556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
146656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "confirmCredentials: " + account
146756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
146856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
146956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
147056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
147156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1472382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1473382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1474d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
14752c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
147626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
147726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
147804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
14798570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
148026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
1481f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    mAuthenticator.confirmCredentials(this, account, options);
148226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
148326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
148426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", confirmCredentials"
148526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account;
148626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
148726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
148826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
148926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
149026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1491603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1492603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1493a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void updateCredentials(IAccountManagerResponse response, final Account account,
1494a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final String authTokenType, final boolean expectActivityLaunch,
1495a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final Bundle loginOptions) {
149656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
149756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "updateCredentials: " + account
149856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
149956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
150056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
150156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
150256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
150356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1504382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1505382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1506382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1507d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
150804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
150926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
151026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
151104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
15128570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
151326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
151426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
151526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
151626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
151726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (loginOptions != null) loginOptions.keySet();
151826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", updateCredentials"
151926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account
152026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", authTokenType " + authTokenType
152126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", loginOptions " + loginOptions;
152226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
152326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
152426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
152526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
152626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1527603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1528603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1529a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void editProperties(IAccountManagerResponse response, final String accountType,
1530a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final boolean expectActivityLaunch) {
153156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
153256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "editProperties: accountType " + accountType
153356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
153456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
153556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
153656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
153756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1538382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1539382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
1540d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
154104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
154226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
154326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
154404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, accountType, expectActivityLaunch,
15458570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
154626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
154726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    mAuthenticator.editProperties(this, mAccountType);
154826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
154926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
155026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", editProperties"
155126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", accountType " + accountType;
155226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
155326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
155426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
155526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
155626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1557603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1558603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
15593326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    private class GetAccountsByTypeAndFeatureSession extends Session {
15603326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private final String[] mFeatures;
15613326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile Account[] mAccountsOfType = null;
15623326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile ArrayList<Account> mAccountsWithFeatures = null;
15633326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile int mCurrentAccount = 0;
1564df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        private int mCallingUid;
15653326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
156604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public GetAccountsByTypeAndFeatureSession(UserAccounts accounts,
1567df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                IAccountManagerResponse response, String type, String[] features, int callingUid) {
156804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, type, false /* expectActivityLaunch */,
15698570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
1570df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            mCallingUid = callingUid;
15713326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mFeatures = features;
15723326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
15733326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
15743326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void run() throws RemoteException {
157504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (mAccounts.cacheLock) {
1576df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid);
1577f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
15783326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            // check whether each account matches the requested features
15793326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length);
15803326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mCurrentAccount = 0;
15813326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
15823326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            checkAccount();
15833326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
15843326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
15853326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void checkAccount() {
15863326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (mCurrentAccount >= mAccountsOfType.length) {
15873326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                sendResult();
15883326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return;
15893326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
15903326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
159129e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            final IAccountAuthenticator accountAuthenticator = mAuthenticator;
159229e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            if (accountAuthenticator == null) {
159329e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // It is possible that the authenticator has died, which is indicated by
159429e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // mAuthenticator being set to null. If this happens then just abort.
159529e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // There is no need to send back a result or error in this case since
159629e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // that already happened when mAuthenticator was cleared.
159729e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
159829e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                    Log.v(TAG, "checkAccount: aborting session since we are no longer"
159929e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                            + " connected to the authenticator, " + toDebugString());
160029e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                }
160129e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                return;
160229e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            }
16033326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            try {
160429e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                accountAuthenticator.hasFeatures(this, mAccountsOfType[mCurrentAccount], mFeatures);
16053326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            } catch (RemoteException e) {
1606f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
1607a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1608603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1609603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
16103326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void onResult(Bundle result) {
16113326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mNumResults++;
16123326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (result == null) {
1613f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
16143326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return;
16153326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
1616f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
16173326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                mAccountsWithFeatures.add(mAccountsOfType[mCurrentAccount]);
16183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
16193326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mCurrentAccount++;
16203326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            checkAccount();
1621a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
16223326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16233326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void sendResult() {
16243326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
16253326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (response != null) {
16263326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                try {
16273326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    Account[] accounts = new Account[mAccountsWithFeatures.size()];
16283326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    for (int i = 0; i < accounts.length; i++) {
16293326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        accounts[i] = mAccountsWithFeatures.get(i);
16303326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    }
163156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
163256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
163356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
163456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
16353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    Bundle result = new Bundle();
1636f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
16373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    response.onResult(result);
16383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                } catch (RemoteException e) {
16393326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
16403326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
16413326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
16423326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    }
16433326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                }
16443326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
16453326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
16463326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16473326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16483326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        protected String toDebugString(long now) {
16493326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            return super.toDebugString(now) + ", getAccountsByTypeAndFeatures"
16503326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
16513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
16523326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
1653ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
165404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    /**
165504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     * Returns the accounts for a specific user
165604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     * @hide
165704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     */
165804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public Account[] getAccounts(int userId) {
165904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        checkReadAccountsPermission();
166004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
1661df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        int callingUid = Binder.getCallingUid();
166204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        long identityToken = clearCallingIdentity();
166304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        try {
166404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
1665df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                return getAccountsFromCacheLocked(accounts, null, callingUid);
166604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
166704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        } finally {
166804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            restoreCallingIdentity(identityToken);
166904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
167004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
167104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
1672f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani    /**
16736ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey     * Returns accounts for all running users.
16746ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey     *
1675f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani     * @hide
1676f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani     */
16776ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    public AccountAndUser[] getRunningAccounts() {
16786ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int[] runningUserIds;
16796ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        try {
16806ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            runningUserIds = ActivityManagerNative.getDefault().getRunningUserIds();
16816ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        } catch (RemoteException e) {
16826ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            // Running in system_server; should never happen
16836ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            throw new RuntimeException(e);
16846ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
16856eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        return getAccounts(runningUserIds);
16866eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
16876eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
16886eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /** {@hide} */
16896eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    public AccountAndUser[] getAllAccounts() {
16906eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final List<UserInfo> users = getUserManager().getUsers();
16916eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final int[] userIds = new int[users.size()];
16926eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        for (int i = 0; i < userIds.length; i++) {
16936eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            userIds[i] = users.get(i).id;
16946eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        }
16956eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        return getAccounts(userIds);
16966eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
16976ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
16986eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    private AccountAndUser[] getAccounts(int[] userIds) {
16996ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList();
17006ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        synchronized (mUsers) {
17016eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            for (int userId : userIds) {
17026ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                UserAccounts userAccounts = getUserAccounts(userId);
1703f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                if (userAccounts == null) continue;
1704f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                synchronized (userAccounts.cacheLock) {
1705df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
1706df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                            Binder.getCallingUid());
1707f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                    for (int a = 0; a < accounts.length; a++) {
17086ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                        runningAccounts.add(new AccountAndUser(accounts[a], userId));
1709f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                    }
1710f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                }
1711f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani            }
1712f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani        }
17136ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
17146ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        AccountAndUser[] accountsArray = new AccountAndUser[runningAccounts.size()];
17156ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        return runningAccounts.toArray(accountsArray);
1716f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani    }
1717f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani
17182c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
17192c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public Account[] getAccountsAsUser(String type, int userId) {
1720df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        final int callingUid = Binder.getCallingUid();
17212c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        // Only allow the system process to read accounts of other users
17222c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        if (userId != UserHandle.getCallingUserId()
1723df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                && callingUid != android.os.Process.myUid()) {
17242c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            throw new SecurityException("User " + UserHandle.getCallingUserId()
17252c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    + " trying to get account for " + userId);
17262c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        }
17272c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
172856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
172956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAccounts: accountType " + type
173056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
173156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
173256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1733ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        checkReadAccountsPermission();
17342c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
1735ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        long identityToken = clearCallingIdentity();
1736ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        try {
173704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
1738df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                return getAccountsFromCacheLocked(accounts, type, callingUid);
1739f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
1740ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
1741ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
1742ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
1743ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
1744ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
17452c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
174667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public boolean addSharedAccountAsUser(Account account, int userId) {
174767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
174867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        SQLiteDatabase db = getUserAccounts(userId).openHelper.getWritableDatabase();
174967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        ContentValues values = new ContentValues();
175067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        values.put(ACCOUNTS_NAME, account.name);
175167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        values.put(ACCOUNTS_TYPE, account.type);
175267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
175367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                new String[] {account.name, account.type});
175467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long accountId = db.insert(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME, values);
175567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (accountId < 0) {
175667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            Log.w(TAG, "insertAccountIntoDatabase: " + account
175767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ", skipping the DB insert failed");
175867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return false;
175967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
176067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return true;
176167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
176267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
176367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
176467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public boolean removeSharedAccountAsUser(Account account, int userId) {
176567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
176667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        UserAccounts accounts = getUserAccounts(userId);
176767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
176867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        int r = db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
176967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                new String[] {account.name, account.type});
177067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (r > 0) {
177167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            removeAccountInternal(accounts, account);
177267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
177367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return r > 0;
177467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
177567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
177667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
177767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public Account[] getSharedAccountsAsUser(int userId) {
177867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
177967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        UserAccounts accounts = getUserAccounts(userId);
178067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        ArrayList<Account> accountList = new ArrayList<Account>();
178167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Cursor cursor = null;
178267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
178367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            cursor = accounts.openHelper.getReadableDatabase()
178467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    .query(TABLE_SHARED_ACCOUNTS, new String[]{ACCOUNTS_NAME, ACCOUNTS_TYPE},
178567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    null, null, null, null, null);
178667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (cursor != null && cursor.moveToFirst()) {
178767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                int nameIndex = cursor.getColumnIndex(ACCOUNTS_NAME);
178867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                int typeIndex = cursor.getColumnIndex(ACCOUNTS_TYPE);
178967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                do {
179067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    accountList.add(new Account(cursor.getString(nameIndex),
179167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            cursor.getString(typeIndex)));
179267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } while (cursor.moveToNext());
179367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
179467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
179567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (cursor != null) {
179667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                cursor.close();
179767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
179867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
179967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] accountArray = new Account[accountList.size()];
180067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        accountList.toArray(accountArray);
180167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return accountArray;
180267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
180367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
180467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
18052c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public Account[] getAccounts(String type) {
18062c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        return getAccountsAsUser(type, UserHandle.getCallingUserId());
18072c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    }
18082c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
1809ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    public void getAccountsByFeatures(IAccountManagerResponse response,
18103326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            String type, String[] features) {
181156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
181256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAccounts: accountType " + type
181356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
181456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", features " + stringArrayToString(features)
181556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
181656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
181756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1818382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1819382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (type == null) throw new IllegalArgumentException("accountType is null");
1820d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkReadAccountsPermission();
182104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts userAccounts = getUserAccountsForCaller();
1822df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        int callingUid = Binder.getCallingUid();
18233326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        long identityToken = clearCallingIdentity();
18243326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        try {
1825ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            if (features == null || features.length == 0) {
1826f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Account[] accounts;
182704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                synchronized (userAccounts.cacheLock) {
1828df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid);
1829f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
1830d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                Bundle result = new Bundle();
1831d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
1832d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                onResult(response, result);
1833ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                return;
1834ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
1835df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            new GetAccountsByTypeAndFeatureSession(userAccounts, response, type, features,
1836df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    callingUid).bind();
18373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        } finally {
18383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            restoreCallingIdentity(identityToken);
18393326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
18403326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
18413326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
1842f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long getAccountIdLocked(SQLiteDatabase db, Account account) {
1843603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
1844ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
1845603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
1846603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (cursor.moveToNext()) {
1847603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return cursor.getLong(0);
1848603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1849603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            return -1;
1850603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
1851603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cursor.close();
1852603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1853603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1854603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1855f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long getExtrasIdLocked(SQLiteDatabase db, long accountId, String key) {
1856603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_ID},
1857603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
1858603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                new String[]{key}, null, null, null);
1859603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
1860603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (cursor.moveToNext()) {
1861603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return cursor.getLong(0);
1862603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1863603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            return -1;
1864603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
1865603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cursor.close();
1866603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1867603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1868603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1869a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    private abstract class Session extends IAccountAuthenticatorResponse.Stub
1870b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            implements IBinder.DeathRecipient, ServiceConnection {
1871603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        IAccountManagerResponse mResponse;
1872603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        final String mAccountType;
1873a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        final boolean mExpectActivityLaunch;
1874a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        final long mCreationTime;
1875a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
18763326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public int mNumResults = 0;
1877a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private int mNumRequestContinued = 0;
1878a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private int mNumErrors = 0;
1879a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1880603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        IAccountAuthenticator mAuthenticator = null;
1881603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
18828570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana        private final boolean mStripAuthTokenFromResult;
188304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        protected final UserAccounts mAccounts;
18848570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana
188504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public Session(UserAccounts accounts, IAccountManagerResponse response, String accountType,
18868570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
1887603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            super();
188867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            //if (response == null) throw new IllegalArgumentException("response is null");
18893326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (accountType == null) throw new IllegalArgumentException("accountType is null");
189004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            mAccounts = accounts;
18918570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana            mStripAuthTokenFromResult = stripAuthTokenFromResult;
1892603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mResponse = response;
1893603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mAccountType = accountType;
1894a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mExpectActivityLaunch = expectActivityLaunch;
1895a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mCreationTime = SystemClock.elapsedRealtime();
1896a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            synchronized (mSessions) {
1897a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mSessions.put(toString(), this);
1898a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
189967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (response != null) {
190067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                try {
190167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    response.asBinder().linkToDeath(this, 0 /* flags */);
190267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } catch (RemoteException e) {
190367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mResponse = null;
190467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    binderDied();
190567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
1906a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1907603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1908603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1909a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        IAccountManagerResponse getResponseAndClose() {
1910603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (mResponse == null) {
1911603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                // this session has already been closed
1912603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return null;
1913603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1914a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = mResponse;
1915a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            close(); // this clears mResponse so we need to save the response before this call
1916a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return response;
1917a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
1918a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1919a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private void close() {
1920a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            synchronized (mSessions) {
1921a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (mSessions.remove(toString()) == null) {
1922a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    // the session was already closed, so bail out now
1923a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    return;
1924a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
1925a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1926a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (mResponse != null) {
1927a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                // stop listening for response deaths
1928a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mResponse.asBinder().unlinkToDeath(this, 0 /* flags */);
1929a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1930a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                // clear this so that we don't accidentally send any further results
1931a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mResponse = null;
1932a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1933603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cancelTimeout();
1934603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            unbind();
1935a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
1936a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1937a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void binderDied() {
1938603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mResponse = null;
1939a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            close();
1940a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
1941a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1942a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        protected String toDebugString() {
1943a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return toDebugString(SystemClock.elapsedRealtime());
1944a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
1945a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1946a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        protected String toDebugString(long now) {
1947a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return "Session: expectLaunch " + mExpectActivityLaunch
1948a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", connected " + (mAuthenticator != null)
1949a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", stats (" + mNumResults + "/" + mNumRequestContinued
1950a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "/" + mNumErrors + ")"
1951a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", lifetime " + ((now - mCreationTime) / 1000.0);
1952603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1953603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1954603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        void bind() {
1955a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1956a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                Log.v(TAG, "initiating bind to authenticator type " + mAccountType);
1957a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1958b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (!bindToAuthenticator(mAccountType)) {
1959a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                Log.d(TAG, "bind attempt failed for " + toDebugString());
1960f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
1961603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1962603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1963603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1964603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        private void unbind() {
1965603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (mAuthenticator != null) {
1966603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                mAuthenticator = null;
1967b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                mContext.unbindService(this);
1968603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1969603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1970603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1971603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void scheduleTimeout() {
1972603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mMessageHandler.sendMessageDelayed(
1973603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    mMessageHandler.obtainMessage(MESSAGE_TIMED_OUT, this), TIMEOUT_DELAY_MS);
1974603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1975603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1976603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void cancelTimeout() {
1977603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this);
1978603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1979603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1980b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public void onServiceConnected(ComponentName name, IBinder service) {
1981603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
1982a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            try {
1983a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                run();
1984a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } catch (RemoteException e) {
1985f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
1986a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        "remote exception");
1987a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1988603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1989603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1990b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public void onServiceDisconnected(ComponentName name) {
1991a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mAuthenticator = null;
1992a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
1993603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
1994166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                try {
1995166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
1996166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                            "disconnected");
1997166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                } catch (RemoteException e) {
1998166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
1999166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        Log.v(TAG, "Session.onServiceDisconnected: "
2000166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                                + "caught RemoteException while responding", e);
2001166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    }
2002166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                }
2003603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2004603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2005603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2006b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public abstract void run() throws RemoteException;
2007b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2008603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onTimedOut() {
2009a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2010603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2011166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                try {
2012166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2013166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                            "timeout");
2014166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                } catch (RemoteException e) {
2015166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2016166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        Log.v(TAG, "Session.onTimedOut: caught RemoteException while responding",
2017166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                                e);
2018166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    }
2019166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                }
2020603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2021603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2022603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2023a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void onResult(Bundle result) {
2024a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumResults++;
2025f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result != null && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {
2026f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
2027f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
2028d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
2029d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    Account account = new Account(accountName, accountType);
203050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    cancelNotification(getSigninRequiredNotificationId(mAccounts, account),
203150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            new UserHandle(mAccounts.userId));
2032d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                }
2033603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2034a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response;
2035a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (mExpectActivityLaunch && result != null
2036f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    && result.containsKey(AccountManager.KEY_INTENT)) {
2037a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                response = mResponse;
2038a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } else {
2039a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                response = getResponseAndClose();
2040603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2041603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2042603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                try {
2043a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (result == null) {
204456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
204556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            Log.v(TAG, getClass().getSimpleName()
204656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                    + " calling onError() on response " + response);
204756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
2048f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
2049a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                                "null bundle returned");
2050a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    } else {
20518570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                        if (mStripAuthTokenFromResult) {
20528570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                            result.remove(AccountManager.KEY_AUTHTOKEN);
20538570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                        }
205456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
205556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            Log.v(TAG, getClass().getSimpleName()
205656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                    + " calling onResult() on response " + response);
205756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
2058a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        response.onResult(result);
2059a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2060603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                } catch (RemoteException e) {
2061a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
2062a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2063a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
2064a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2065603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                }
2066603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2067603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2068603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2069a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void onRequestContinued() {
2070a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumRequestContinued++;
2071603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2072603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2073603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onError(int errorCode, String errorMessage) {
2074a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumErrors++;
2075a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2076a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (response != null) {
2077a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
207856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    Log.v(TAG, getClass().getSimpleName()
207956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            + " calling onError() on response " + response);
2080a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2081a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                try {
2082a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    response.onError(errorCode, errorMessage);
2083a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                } catch (RemoteException e) {
2084a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2085a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        Log.v(TAG, "Session.onError: caught RemoteException while responding", e);
2086a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2087a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2088a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } else {
2089a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2090a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    Log.v(TAG, "Session.onError: already closed");
2091a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2092603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2093603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2094b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2095b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        /**
2096b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         * find the component name for the authenticator and initiate a bind
2097b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         * if no authenticator or the bind fails then return false, otherwise return true
2098b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         */
2099b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        private boolean bindToAuthenticator(String authenticatorType) {
21006ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            final AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
21016ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            authenticatorInfo = mAuthenticatorCache.getServiceInfo(
21026ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    AuthenticatorDescription.newKey(authenticatorType), mAccounts.userId);
2103b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (authenticatorInfo == null) {
2104b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2105b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                    Log.v(TAG, "there is no authenticator for " + authenticatorType
2106b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                            + ", bailing out");
2107b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                }
2108b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                return false;
2109b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
2110b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2111b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            Intent intent = new Intent();
2112b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
2113b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            intent.setComponent(authenticatorInfo.componentName);
2114b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
2115b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
2116b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
211727b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani            if (!mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
211827b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    new UserHandle(mAccounts.userId))) {
2119b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2120b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
2121b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                }
2122b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                return false;
2123b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
2124b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2125b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2126b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            return true;
2127b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        }
2128603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2130603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private class MessageHandler extends Handler {
2131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        MessageHandler(Looper looper) {
2132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            super(looper);
2133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
21343348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache
2135603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void handleMessage(Message msg) {
2136603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            switch (msg.what) {
2137603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                case MESSAGE_TIMED_OUT:
2138603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    Session session = (Session)msg.obj;
2139603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    session.onTimedOut();
2140603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    break;
2141603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2142603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                default:
2143603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    throw new IllegalStateException("unhandled message: " + msg.what);
2144603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2145603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2146603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2147603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
214804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static String getDatabaseName(int userId) {
214904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        File systemDir = Environment.getSystemSecureDirectory();
215061f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani        File databaseFile = new File(Environment.getUserSystemDirectory(userId), DATABASE_NAME);
215104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        if (userId == 0) {
2152a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // Migrate old file, if it exists, to the new location.
2153a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // Make sure the new file doesn't already exist. A dummy file could have been
2154a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // accidentally created in the old location, causing the new one to become corrupted
2155a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // as well.
215604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            File oldFile = new File(systemDir, DATABASE_NAME);
2157a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            if (oldFile.exists() && !databaseFile.exists()) {
2158c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                // Check for use directory; create if it doesn't exist, else renameTo will fail
215961f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani                File userDir = Environment.getUserSystemDirectory(userId);
2160c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                if (!userDir.exists()) {
2161c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    if (!userDir.mkdirs()) {
2162c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                        throw new IllegalStateException("User dir cannot be created: " + userDir);
2163c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    }
2164c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                }
2165c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                if (!oldFile.renameTo(databaseFile)) {
2166c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    throw new IllegalStateException("User dir cannot be migrated: " + databaseFile);
2167c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                }
216804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
2169a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor        }
217004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        return databaseFile.getPath();
2171a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor    }
2172a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor
217304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    static class DatabaseHelper extends SQLiteOpenHelper {
2174a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor
217504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public DatabaseHelper(Context context, int userId) {
217604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(context, AccountManagerService.getDatabaseName(userId), null, DATABASE_VERSION);
2177603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2178603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2179f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        /**
2180f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * This call needs to be made while the mCacheLock is held. The way to
2181f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * ensure this is to get the lock any time a method is called ont the DatabaseHelper
2182f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * @param db The database.
2183f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         */
2184603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2185603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onCreate(SQLiteDatabase db) {
2186603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_ACCOUNTS + " ( "
2187603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
2188603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_NAME + " TEXT NOT NULL, "
2189603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_TYPE + " TEXT NOT NULL, "
2190603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_PASSWORD + " TEXT, "
2191603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
2192603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2193603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " (  "
2194603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,  "
2195603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_ACCOUNTS_ID + " INTEGER NOT NULL, "
2196603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_TYPE + " TEXT NOT NULL,  "
2197603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_AUTHTOKEN + " TEXT,  "
2198603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE (" + AUTHTOKENS_ACCOUNTS_ID + "," + AUTHTOKENS_TYPE + "))");
2199603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2200d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            createGrantsTable(db);
2201d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2202603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_EXTRAS + " ( "
2203603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
2204603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_ACCOUNTS_ID + " INTEGER, "
2205603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_KEY + " TEXT NOT NULL, "
2206603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_VALUE + " TEXT, "
2207603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE(" + EXTRAS_ACCOUNTS_ID + "," + EXTRAS_KEY + "))");
2208603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2209603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_META + " ( "
2210603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + META_KEY + " TEXT PRIMARY KEY NOT NULL, "
2211603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + META_VALUE + " TEXT)");
2212a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
221367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            createSharedAccountsTable(db);
221467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2215d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            createAccountsDeletionTrigger(db);
2216d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2217d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
221867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        private void createSharedAccountsTable(SQLiteDatabase db) {
221967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            db.execSQL("CREATE TABLE " + TABLE_SHARED_ACCOUNTS + " ( "
222067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
222167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_NAME + " TEXT NOT NULL, "
222267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_TYPE + " TEXT NOT NULL, "
222367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
222467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
222567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2226d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        private void createAccountsDeletionTrigger(SQLiteDatabase db) {
2227a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            db.execSQL(""
2228a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
2229a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " BEGIN"
2230a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "   DELETE FROM " + TABLE_AUTHTOKENS
2231a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "     WHERE " + AUTHTOKENS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2232a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "   DELETE FROM " + TABLE_EXTRAS
2233a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "     WHERE " + EXTRAS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2234d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "   DELETE FROM " + TABLE_GRANTS
2235d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "     WHERE " + GRANTS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2236a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " END");
2237603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2238603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2239d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        private void createGrantsTable(SQLiteDatabase db) {
2240d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            db.execSQL("CREATE TABLE " + TABLE_GRANTS + " (  "
2241d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_ACCOUNTS_ID + " INTEGER NOT NULL, "
2242d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_AUTH_TOKEN_TYPE + " STRING NOT NULL,  "
2243d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_GRANTEE_UID + " INTEGER NOT NULL,  "
2244d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "UNIQUE (" + GRANTS_ACCOUNTS_ID + "," + GRANTS_AUTH_TOKEN_TYPE
2245d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    +   "," + GRANTS_GRANTEE_UID + "))");
2246d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2247d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2248603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2249603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
2250a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
2251603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2252a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (oldVersion == 1) {
2253d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                // no longer need to do anything since the work is done
2254d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                // when upgrading from version 2
2255d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                oldVersion++;
2256d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
2257d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2258d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (oldVersion == 2) {
2259d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                createGrantsTable(db);
2260d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                db.execSQL("DROP TRIGGER " + TABLE_ACCOUNTS + "Delete");
2261d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                createAccountsDeletionTrigger(db);
2262a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                oldVersion++;
2263a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
22643348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache
22653348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache            if (oldVersion == 3) {
22663348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_TYPE +
22673348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                        " = 'com.google' WHERE " + ACCOUNTS_TYPE + " == 'com.google.GAIA'");
22683348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                oldVersion++;
22693348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache            }
227067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
227167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (oldVersion == 4) {
227267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                createSharedAccountsTable(db);
227367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                oldVersion++;
227467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
227567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
227667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (oldVersion != newVersion) {
227767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
227867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
2279603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2280603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2281603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2282603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onOpen(SQLiteDatabase db) {
2283603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "opened database " + DATABASE_NAME);
2284603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2285603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2286603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2287603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    public IBinder onBind(Intent intent) {
2288603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        return asBinder();
2289603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2290a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
22911cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    /**
22921cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * Searches array of arguments for the specified string
22931cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @param args array of argument strings
22941cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @param value value to search for
22951cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @return true if the value is contained in the array
22961cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     */
22971cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static boolean scanArgs(String[] args, String value) {
22981cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        if (args != null) {
22991cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks            for (String arg : args) {
23001cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                if (value.equals(arg)) {
23011cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                    return true;
23021cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2303a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2304a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
23051cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        return false;
23061cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    }
2307a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
23086eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    @Override
23091cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
23103abd75ba3a981850cac43a401d0014a836559cb0Kenny Root        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
23113abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                != PackageManager.PERMISSION_GRANTED) {
23123abd75ba3a981850cac43a401d0014a836559cb0Kenny Root            fout.println("Permission Denial: can't dump AccountsManager from from pid="
23133abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
23143abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                    + " without permission " + android.Manifest.permission.DUMP);
23153abd75ba3a981850cac43a401d0014a836559cb0Kenny Root            return;
23163abd75ba3a981850cac43a401d0014a836559cb0Kenny Root        }
231704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
23186eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final IndentingPrintWriter ipw = new IndentingPrintWriter(fout, "  ");
23196eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
23206eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final List<UserInfo> users = getUserManager().getUsers();
23216eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        for (UserInfo user : users) {
23226eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.println("User " + user + ":");
23236eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.increaseIndent();
23246eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            dumpUser(getUserAccounts(user.id), fd, ipw, args, isCheckinRequest);
23256eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.println();
23266eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.decreaseIndent();
232704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
232804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
23291cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks
233004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void dumpUser(UserAccounts userAccounts, FileDescriptor fd, PrintWriter fout,
233104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String[] args, boolean isCheckinRequest) {
233204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (userAccounts.cacheLock) {
233304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = userAccounts.openHelper.getReadableDatabase();
2334a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2335f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (isCheckinRequest) {
2336f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // This is a checkin request. *Only* upload the account types and the count of each.
2337f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
2338f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        null, null, ACCOUNTS_TYPE, null, null);
2339f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                try {
2340f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    while (cursor.moveToNext()) {
2341f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        // print type,count
2342f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        fout.println(cursor.getString(0) + "," + cursor.getString(1));
2343f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
2344f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } finally {
2345f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (cursor != null) {
2346f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        cursor.close();
2347f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
23481cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2349f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } else {
2350df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
2351df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        android.os.Process.myUid());
2352f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println("Accounts: " + accounts.length);
2353f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                for (Account account : accounts) {
2354f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    fout.println("  " + account);
23551cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2356307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
2357f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println();
2358f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                synchronized (mSessions) {
2359f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    final long now = SystemClock.elapsedRealtime();
2360f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    fout.println("Active Sessions: " + mSessions.size());
2361f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    for (Session session : mSessions.values()) {
2362f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        fout.println("  " + session.toDebugString(now));
2363f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
23641cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
23651cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks
2366f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println();
23676ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
2368f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
23691cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        }
2370a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2371a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
237204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void doNotification(UserAccounts accounts, Account account, CharSequence message,
23734120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            Intent intent, int userId) {
237426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
237526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
237626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
237726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                Log.v(TAG, "doNotification: " + message + " intent:" + intent);
237826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
2379a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2380d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (intent.getComponent() != null &&
2381d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    GrantCredentialsPermissionActivity.class.getName().equals(
2382d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            intent.getComponent().getClassName())) {
23834120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                createNoCredentialsPermissionNotification(account, intent, userId);
2384d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            } else {
238504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
238633f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                intent.addCategory(String.valueOf(notificationId));
2387d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
2388d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        0 /* when */);
238950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                UserHandle user = new UserHandle(userId);
239033f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                final String notificationTitleFormat =
239133f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                        mContext.getText(R.string.notification_title).toString();
239233f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                n.setLatestEventInfo(mContext,
239333f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                        String.format(notificationTitleFormat, account.name),
23944120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        message, PendingIntent.getActivityAsUser(
23954120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
239650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                        null, user));
239750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                installNotification(notificationId, n, user);
2398d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
239926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
240026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
240126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
2402a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2403a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
240450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    protected void installNotification(final int notificationId, final Notification n,
240550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            UserHandle user) {
240656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
240750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                .notifyAsUser(null, notificationId, n, user);
240856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
240956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
241050cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    protected void cancelNotification(int id, UserHandle user) {
241126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
241226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
241326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
241450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                .cancelAsUser(null, id, user);
241526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
241626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
241726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
2418a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2419d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2420b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    /** Succeeds if any of the specified permissions are granted. */
2421b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    private void checkBinderPermission(String... permissions) {
2422d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        final int uid = Binder.getCallingUid();
2423b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2424b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        for (String perm : permissions) {
2425b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana            if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
2426b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
242756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    Log.v(TAG, "  caller uid " + uid + " has " + perm);
2428b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                }
2429b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                return;
2430b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana            }
2431d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2432b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2433b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions);
243456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Log.w(TAG, "  " + msg);
2435b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        throw new SecurityException(msg);
2436d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2437d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
243867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private int handleIncomingUser(int userId) {
243967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
244067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return ActivityManagerNative.getDefault().handleIncomingUser(
244167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, true, "", null);
244267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } catch (RemoteException re) {
244367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Shouldn't happen, local.
244467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
244567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return userId;
244667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
244767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
24486ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    private boolean inSystemImage(int callingUid) {
24496ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int callingUserId = UserHandle.getUserId(callingUid);
24506ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
24516ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final PackageManager userPackageManager;
24526ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        try {
24536ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            userPackageManager = mContext.createPackageContextAsUser(
24546ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    "android", 0, new UserHandle(callingUserId)).getPackageManager();
24556ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        } catch (NameNotFoundException e) {
24566ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            return false;
24576ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
24586ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
24596ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        String[] packages = userPackageManager.getPackagesForUid(callingUid);
24607be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        for (String name : packages) {
24617be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            try {
24626ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
246356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                if (packageInfo != null
246456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
24657be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                    return true;
24667be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                }
24677be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            } catch (PackageManager.NameNotFoundException e) {
24687be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                return false;
24697be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            }
24707be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        }
24717be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        return false;
24727be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    }
24737be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
2474d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
2475b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        final boolean inSystemImage = inSystemImage(callerUid);
247631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        final boolean fromAuthenticator = account != null
247731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana                && hasAuthenticatorUid(account.type, callerUid);
247831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        final boolean hasExplicitGrants = account != null
247904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                && hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
2480d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
2481d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
248256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + callerUid + ", " + account
2483d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + ": is authenticator? " + fromAuthenticator
2484d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + ", has explicit permission? " + hasExplicitGrants);
2485d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2486b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        return fromAuthenticator || hasExplicitGrants || inSystemImage;
2487d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2488d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
24891a23191bbde11505d6e0c25c04a60b41cb27fd31Fred Quintana    private boolean hasAuthenticatorUid(String accountType, int callingUid) {
24906ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int callingUserId = UserHandle.getUserId(callingUid);
2491d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
24926ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.getAllServices(callingUserId)) {
2493d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (serviceInfo.type.type.equals(accountType)) {
2494ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                return (serviceInfo.uid == callingUid) ||
249556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        (mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
2496ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                                == PackageManager.SIGNATURE_MATCH);
2497d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
2498d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2499d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return false;
2500d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2501d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
250204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
250304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            int callerUid) {
250404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        if (callerUid == android.os.Process.SYSTEM_UID) {
2505d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            return true;
2506d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
250704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
250804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
250904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
251004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String[] args = { String.valueOf(callerUid), authTokenType,
2511f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    account.name, account.type};
2512f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final boolean permissionGranted =
2513f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
2514f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
2515f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // TODO: Skip this check when running automated tests. Replace this
2516f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // with a more general solution.
2517f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Log.d(TAG, "no credentials permission for usage of " + account + ", "
251804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        + authTokenType + " by uid " + callerUid
2519f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        + " but ignoring since device is in test harness.");
2520f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return true;
2521f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2522f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            return permissionGranted;
2523d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2524d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2525d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2526d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkCallingUidAgainstAuthenticator(Account account) {
2527d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        final int uid = Binder.getCallingUid();
252831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || !hasAuthenticatorUid(account.type, uid)) {
2529d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            String msg = "caller uid " + uid + " is different than the authenticator's uid";
2530d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.w(TAG, msg);
2531d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            throw new SecurityException(msg);
2532d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2533d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
2534d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid");
2535d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2536d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2537d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2538d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkAuthenticateAccountsPermission(Account account) {
2539d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.AUTHENTICATE_ACCOUNTS);
2540d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkCallingUidAgainstAuthenticator(account);
2541d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2542d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2543d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkReadAccountsPermission() {
2544d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
2545d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2546d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2547d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkManageAccountsPermission() {
2548d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS);
2549d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2550d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2551b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    private void checkManageAccountsOrUseCredentialsPermissions() {
2552b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS,
2553b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                Manifest.permission.USE_CREDENTIALS);
2554b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    }
2555b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2556e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani    private boolean canUserModifyAccounts(int callingUid) {
2557e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        if (callingUid != android.os.Process.myUid()) {
2558e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            Bundle restrictions = getUserManager().getUserRestrictions(
2559e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                    new UserHandle(UserHandle.getUserId(callingUid)));
256071e6c697e54a43d357cc25d87a446d140f17396aAmith Yamasani            if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
2561e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                return false;
2562e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            }
2563e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        }
2564e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        return true;
2565e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani    }
2566e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani
2567d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
2568d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throws RemoteException {
2569d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        final int callingUid = getCallingUid();
2570d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2571d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (callingUid != android.os.Process.SYSTEM_UID) {
2572d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throw new SecurityException();
2573d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
2574d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2575d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (value) {
2576d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            grantAppPermission(account, authTokenType, uid);
2577d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        } else {
2578d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            revokeAppPermission(account, authTokenType, uid);
2579d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
2580d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    }
2581d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2582d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
2583d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Allow callers with the given uid permission to get credentials for account/authTokenType.
2584d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * <p>
2585d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Although this is public it can only be accessed via the AccountManagerService object
2586d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * which is in the system. This means we don't need to protect it with permissions.
2587d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
2588d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
2589d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    private void grantAppPermission(Account account, String authTokenType, int uid) {
2590382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null || authTokenType == null) {
2591382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana            Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
259231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
259331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
2594f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
259504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
259604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
2597f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
2598f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
2599f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
2600f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
2601f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ContentValues values = new ContentValues();
2602f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_ACCOUNTS_ID, accountId);
2603f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
2604f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_GRANTEE_UID, uid);
2605f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
2606f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
2607f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
2608f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
2609f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
2610d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
261150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
261250cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    new UserHandle(accounts.userId));
2613d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2614d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2615d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2616d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
2617d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Don't allow callers with the given uid permission to get credentials for
2618d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * account/authTokenType.
2619d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * <p>
2620d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Although this is public it can only be accessed via the AccountManagerService object
2621d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * which is in the system. This means we don't need to protect it with permissions.
2622d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
2623d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
2624d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    private void revokeAppPermission(Account account, String authTokenType, int uid) {
2625382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null || authTokenType == null) {
2626382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana            Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
262731957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
262831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
2629f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
263004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
263104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
2632f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
2633f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
2634f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
2635f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
2636f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.delete(TABLE_GRANTS,
2637f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND "
2638f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    + GRANTS_GRANTEE_UID + "=?",
2639f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            new String[]{String.valueOf(accountId), authTokenType,
2640f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    String.valueOf(uid)});
2641f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
2642f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
2643f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
2644f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
2645d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
264650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
264750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    new UserHandle(accounts.userId));
2648d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2649d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
265056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
265156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    static final private String stringArrayToString(String[] value) {
265256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return value != null ? ("[" + TextUtils.join(",", value) + "]") : null;
265356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
265456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
265504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAccountFromCacheLocked(UserAccounts accounts, Account account) {
265604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final Account[] oldAccountsForType = accounts.accountCache.get(account.type);
2657f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (oldAccountsForType != null) {
2658f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            ArrayList<Account> newAccountsList = new ArrayList<Account>();
2659f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            for (Account curAccount : oldAccountsForType) {
2660f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (!curAccount.equals(account)) {
2661f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    newAccountsList.add(curAccount);
266256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                }
266356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
2664f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (newAccountsList.isEmpty()) {
266504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.remove(account.type);
2666f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } else {
2667f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Account[] newAccountsForType = new Account[newAccountsList.size()];
2668f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                newAccountsForType = newAccountsList.toArray(newAccountsForType);
266904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.put(account.type, newAccountsForType);
2670f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
267156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
267204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.userDataCache.remove(account);
267304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.authTokenCache.remove(account);
267456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
267556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
267656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    /**
267756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana     * This assumes that the caller has already checked that the account is not already present.
267856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana     */
267904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void insertAccountIntoCacheLocked(UserAccounts accounts, Account account) {
268004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        Account[] accountsForType = accounts.accountCache.get(account.type);
2681f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        int oldLength = (accountsForType != null) ? accountsForType.length : 0;
2682f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        Account[] newAccountsForType = new Account[oldLength + 1];
2683f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (accountsForType != null) {
2684f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
2685f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2686f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        newAccountsForType[oldLength] = account;
268704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.accountCache.put(account.type, newAccountsForType);
2688f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    }
2689f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana
2690df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered,
2691df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            int callingUid) {
2692df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
2693df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                || callingUid == android.os.Process.myUid()) {
2694df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return unfiltered;
2695df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
2696df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) {
2697df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            String[] packages = mPackageManager.getPackagesForUid(callingUid);
2698df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // If any of the packages includes a white listed package, return the full set,
2699df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // otherwise return non-shared accounts only.
2700df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // This might be a temporary way to specify a whitelist
2701df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            String whiteList = mContext.getResources().getString(
2702df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    com.android.internal.R.string.config_appsAuthorizedForSharedAccounts);
2703df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            for (String packageName : packages) {
2704df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                if (whiteList.contains(";" + packageName + ";")) {
2705df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    return unfiltered;
2706df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2707df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
2708df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            ArrayList<Account> allowed = new ArrayList<Account>();
2709df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId);
2710df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered;
2711df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            for (Account account : unfiltered) {
2712df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                boolean found = false;
2713df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                for (Account shared : sharedAccounts) {
2714df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    if (shared.equals(account)) {
2715df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        found = true;
2716df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        break;
2717df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    }
2718df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2719df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                if (!found) {
2720df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    allowed.add(account);
2721df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2722df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
2723df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            Account[] filtered = new Account[allowed.size()];
2724df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            allowed.toArray(filtered);
2725df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return filtered;
2726df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        } else {
2727df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return unfiltered;
2728df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
2729df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    }
2730df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani
2731df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
2732df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            int callingUid) {
2733f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (accountType != null) {
273404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final Account[] accounts = userAccounts.accountCache.get(accountType);
2735f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (accounts == null) {
2736f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return EMPTY_ACCOUNT_ARRAY;
273756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            } else {
2738df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
2739df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        callingUid);
2740f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2741f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2742f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            int totalLength = 0;
274304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (Account[] accounts : userAccounts.accountCache.values()) {
2744f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                totalLength += accounts.length;
2745f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2746f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (totalLength == 0) {
2747f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return EMPTY_ACCOUNT_ARRAY;
2748f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2749f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Account[] accounts = new Account[totalLength];
2750f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            totalLength = 0;
275104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (Account[] accountsOfType : userAccounts.accountCache.values()) {
2752f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                System.arraycopy(accountsOfType, 0, accounts, totalLength,
2753f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        accountsOfType.length);
2754f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                totalLength += accountsOfType.length;
275556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
2756df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return filterSharedAccounts(userAccounts, accounts, callingUid);
275756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
275856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
275956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
276004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void writeUserDataIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
276104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Account account, String key, String value) {
276204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
2763f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (userDataForAccount == null) {
2764f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
276504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            accounts.userDataCache.put(account, userDataForAccount);
2766f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2767f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (value == null) {
2768f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount.remove(key);
2769f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2770f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount.put(key, value);
277156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
277256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
277356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
277404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
277504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Account account, String key, String value) {
277604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
2777f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (authTokensForAccount == null) {
2778f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
277904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            accounts.authTokenCache.put(account, authTokensForAccount);
2780f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2781f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (value == null) {
2782f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount.remove(key);
2783f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2784f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount.put(key, value);
278556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
278656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
278756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
278804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected String readAuthTokenInternal(UserAccounts accounts, Account account,
278904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String authTokenType) {
279004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
279104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
279256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            if (authTokensForAccount == null) {
279356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                // need to populate the cache for this account
279404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
2795f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
279604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.authTokenCache.put(account, authTokensForAccount);
279756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
279856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            return authTokensForAccount.get(authTokenType);
279956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
280056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
280156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
280204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected String readUserDataInternal(UserAccounts accounts, Account account, String key) {
280304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
280404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
280556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            if (userDataForAccount == null) {
280656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                // need to populate the cache for this account
280704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
2808f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
280904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.userDataCache.put(account, userDataForAccount);
281056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
281156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            return userDataForAccount.get(key);
281256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
281356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
281456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2815f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected HashMap<String, String> readUserDataForAccountFromDatabaseLocked(
2816f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final SQLiteDatabase db, Account account) {
281756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        HashMap<String, String> userDataForAccount = new HashMap<String, String>();
281856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Cursor cursor = db.query(TABLE_EXTRAS,
281956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                COLUMNS_EXTRAS_KEY_AND_VALUE,
282056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                SELECTION_USERDATA_BY_ACCOUNT,
282156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                new String[]{account.name, account.type},
282256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                null, null, null);
282356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        try {
282456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            while (cursor.moveToNext()) {
282556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String tmpkey = cursor.getString(0);
282656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String value = cursor.getString(1);
282756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                userDataForAccount.put(tmpkey, value);
282856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
282956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        } finally {
283056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            cursor.close();
283156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
283256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return userDataForAccount;
283356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
283456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2835f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected HashMap<String, String> readAuthTokensForAccountFromDatabaseLocked(
2836f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final SQLiteDatabase db, Account account) {
283756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        HashMap<String, String> authTokensForAccount = new HashMap<String, String>();
283856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Cursor cursor = db.query(TABLE_AUTHTOKENS,
283956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
284056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                SELECTION_AUTHTOKENS_BY_ACCOUNT,
284156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                new String[]{account.name, account.type},
284256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                null, null, null);
284356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        try {
284456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            while (cursor.moveToNext()) {
284556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String type = cursor.getString(0);
284656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String authToken = cursor.getString(1);
284756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                authTokensForAccount.put(type, authToken);
284856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
284956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        } finally {
285056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            cursor.close();
285156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
285256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return authTokensForAccount;
285356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
2854603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana}
2855