AccountManagerService.java revision 23c8b96a7e5c3f4c169bf65ae3886357943bb7b0
1603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/*
2603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Copyright (C) 2009 The Android Open Source Project
3603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *
4603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Licensed under the Apache License, Version 2.0 (the "License");
5603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * you may not use this file except in compliance with the License.
6603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * You may obtain a copy of the License at
7603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *
8603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *      http://www.apache.org/licenses/LICENSE-2.0
9603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana *
10603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * Unless required by applicable law or agreed to in writing, software
11603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * distributed under the License is distributed on an "AS IS" BASIS,
12603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * See the License for the specific language governing permissions and
14603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * limitations under the License.
15603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */
16603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeypackage com.android.server.accounts;
18603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
19885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.Manifest;
207a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.Account;
217a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AccountAndUser;
227a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AccountAuthenticatorResponse;
237a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AccountManager;
247a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.AuthenticatorDescription;
2523c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasaniimport android.accounts.CantAddAccountActivity;
267a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.GrantCredentialsPermissionActivity;
277a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountAuthenticator;
287a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountAuthenticatorResponse;
297a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountManager;
307a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkeyimport android.accounts.IAccountManagerResponse;
313b4fcbc9f13bab6a2e9e5c37cc5e18fec7341c04Brett Chabotimport android.app.ActivityManager;
326ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.app.ActivityManagerNative;
33885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.Notification;
34885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.NotificationManager;
35885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.app.PendingIntent;
36a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.BroadcastReceiver;
37885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.ComponentName;
38a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.ContentValues;
39a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Context;
40a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.Intent;
41a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.content.IntentFilter;
42b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintanaimport android.content.ServiceConnection;
43885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.ApplicationInfo;
44885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.content.pm.PackageInfo;
45d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.PackageManager;
466ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
47d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.content.pm.RegisteredServicesCache;
483ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanaimport android.content.pm.RegisteredServicesCacheListener;
496eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport android.content.pm.UserInfo;
50603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.Cursor;
51603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintanaimport android.database.DatabaseUtils;
52a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteDatabase;
53a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.database.sqlite.SQLiteOpenHelper;
54885cfc23a42f2a4f8578e6a2182af4d9a0a78b1fDoug Zongkerimport android.os.Binder;
55a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Bundle;
56a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport android.os.Environment;
57a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Handler;
58a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.HandlerThread;
59a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.IBinder;
60a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Looper;
61a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.Message;
6227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasaniimport android.os.Process;
63a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.RemoteException;
64a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.os.SystemClock;
65f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
66258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasaniimport android.os.UserManager;
67a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.text.TextUtils;
68a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport android.util.Log;
69d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport android.util.Pair;
706eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport android.util.Slog;
7104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasaniimport android.util.SparseArray;
72603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
73b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolacheimport com.android.internal.R;
7467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasaniimport com.android.internal.util.ArrayUtils;
7504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasaniimport com.android.internal.util.IndentingPrintWriter;
766ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Lists;
776ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport com.google.android.collect.Sets;
78b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
79a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayorimport java.io.File;
80a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.FileDescriptor;
81a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.io.PrintWriter;
82a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.ArrayList;
8356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaimport java.util.Arrays;
84a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintanaimport java.util.Collection;
85d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.HashMap;
866ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkeyimport java.util.HashSet;
8756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintanaimport java.util.LinkedHashMap;
886eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkeyimport java.util.List;
892f36229db823d152f3efd879e751e81a601a75b0Andy McFaddenimport java.util.Map;
90d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicInteger;
91d4a1d2e14297a3387fdb5761090961e714370492Fred Quintanaimport java.util.concurrent.atomic.AtomicReference;
92603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
93603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana/**
94603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * A system service that provides  account, password, and authtoken management for all
95603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * accounts on the device. Some of these calls are implemented with the help of the corresponding
96603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * {@link IAccountAuthenticator} services. This service is not accessed by users directly,
97603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana * instead one uses an instance of {@link AccountManager}, which can be accessed as follows:
9846703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom *    AccountManager accountManager = AccountManager.get(context);
993326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana * @hide
100603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana */
1013ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintanapublic class AccountManagerService
1023ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana        extends IAccountManager.Stub
1035ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana        implements RegisteredServicesCacheListener<AuthenticatorDescription> {
104603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TAG = "AccountManagerService";
105603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
106603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final int TIMEOUT_DELAY_MS = 1000 * 60;
107603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String DATABASE_NAME = "accounts.db";
10867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private static final int DATABASE_VERSION = 5;
109603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
110603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private final Context mContext;
111603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
11256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private final PackageManager mPackageManager;
113258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    private UserManager mUserManager;
11456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
115603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private HandlerThread mMessageThread;
116603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private final MessageHandler mMessageHandler;
117603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
118603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    // Messages that can be sent on mHandler
119603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final int MESSAGE_TIMED_OUT = 3;
1205be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    private static final int MESSAGE_COPY_SHARED_ACCOUNT = 4;
121603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
12256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private final IAccountAuthenticatorCache mAuthenticatorCache;
123603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
124603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_ACCOUNTS = "accounts";
125603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_ID = "_id";
126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_NAME = "name";
127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_TYPE = "type";
1281cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static final String ACCOUNTS_TYPE_COUNT = "count(type)";
129603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String ACCOUNTS_PASSWORD = "password";
130603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
131603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_AUTHTOKENS = "authtokens";
132603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_ID = "_id";
133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_ACCOUNTS_ID = "accounts_id";
134603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_TYPE = "type";
135603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String AUTHTOKENS_AUTHTOKEN = "authtoken";
136603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
137d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String TABLE_GRANTS = "grants";
138d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_ACCOUNTS_ID = "accounts_id";
139d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_AUTH_TOKEN_TYPE = "auth_token_type";
140d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String GRANTS_GRANTEE_UID = "uid";
141d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
142603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_EXTRAS = "extras";
143603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_ID = "_id";
144603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_ACCOUNTS_ID = "accounts_id";
145603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_KEY = "key";
146603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String EXTRAS_VALUE = "value";
147603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
148603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String TABLE_META = "meta";
149603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String META_KEY = "key";
150603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private static final String META_VALUE = "value";
151603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
15267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private static final String TABLE_SHARED_ACCOUNTS = "shared_accounts";
15367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
1541cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION =
1551cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks            new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT};
1567be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    private static final Intent ACCOUNTS_CHANGED_INTENT;
157a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
158d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static final String COUNT_OF_MATCHING_GRANTS = ""
159d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS
160d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " WHERE " + GRANTS_ACCOUNTS_ID + "=" + ACCOUNTS_ID
161d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + GRANTS_GRANTEE_UID + "=?"
162d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + GRANTS_AUTH_TOKEN_TYPE + "=?"
163d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + ACCOUNTS_NAME + "=?"
164d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            + " AND " + ACCOUNTS_TYPE + "=?";
165d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
16656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String SELECTION_AUTHTOKENS_BY_ACCOUNT =
16756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
16856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN = {AUTHTOKENS_TYPE,
16956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            AUTHTOKENS_AUTHTOKEN};
17056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
17156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String SELECTION_USERDATA_BY_ACCOUNT =
17256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            EXTRAS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
17356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    private static final String[] COLUMNS_EXTRAS_KEY_AND_VALUE = {EXTRAS_KEY, EXTRAS_VALUE};
17456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
175a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    private final LinkedHashMap<String, Session> mSessions = new LinkedHashMap<String, Session>();
176d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private final AtomicInteger mNotificationIds = new AtomicInteger(1);
177d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
17804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    static class UserAccounts {
17904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final int userId;
18004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final DatabaseHelper openHelper;
18104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final HashMap<Pair<Pair<Account, String>, Integer>, Integer>
18204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                credentialsPermissionNotificationIds =
18304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Pair<Pair<Account, String>, Integer>, Integer>();
18404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final HashMap<Account, Integer> signinRequiredNotificationIds =
18504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, Integer>();
18604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private final Object cacheLock = new Object();
18704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
188b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani        private final HashMap<String, Account[]> accountCache =
189b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani                new LinkedHashMap<String, Account[]>();
19004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
19104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private HashMap<Account, HashMap<String, String>> userDataCache =
19204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, HashMap<String, String>>();
19304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        /** protected by the {@link #cacheLock} */
19404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        private HashMap<Account, HashMap<String, String>> authTokenCache =
19504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                new HashMap<Account, HashMap<String, String>>();
19604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
19704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts(Context context, int userId) {
19804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            this.userId = userId;
19904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (cacheLock) {
20004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                openHelper = new DatabaseHelper(context, userId);
20104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
20204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
20304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
20404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
20504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private final SparseArray<UserAccounts> mUsers = new SparseArray<UserAccounts>();
20604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
207d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private static AtomicReference<AccountManagerService> sThis =
208d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            new AtomicReference<AccountManagerService>();
20931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana    private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
2107be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
2117be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    static {
212f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana        ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
2137be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
2147be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    }
2157be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
21656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
217d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
218d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * This should only be called by system code. One should only call this after the service
219d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * has started.
220d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @return a reference to the AccountManagerService instance
221d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
222d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
223d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    public static AccountManagerService getSingleton() {
224d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return sThis.get();
225d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
226603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
22756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    public AccountManagerService(Context context) {
22856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        this(context, context.getPackageManager(), new AccountAuthenticatorCache(context));
229603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
230603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
23156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    public AccountManagerService(Context context, PackageManager packageManager,
23256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            IAccountAuthenticatorCache authenticatorCache) {
233603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mContext = context;
23456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mPackageManager = packageManager;
235603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
236603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mMessageThread = new HandlerThread("AccountManagerService");
237603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mMessageThread.start();
238603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        mMessageHandler = new MessageHandler(mMessageThread.getLooper());
239603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
24056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        mAuthenticatorCache = authenticatorCache;
2415ebbb4a6b3e16f711735ae0615b9a9ea64faad38Fred Quintana        mAuthenticatorCache.setListener(this, null /* Handler */);
242603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
243d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        sThis.set(this);
244afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana
245c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        IntentFilter intentFilter = new IntentFilter();
246c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
247c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        intentFilter.addDataScheme("package");
248c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        mContext.registerReceiver(new BroadcastReceiver() {
249c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            @Override
250c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            public void onReceive(Context context1, Intent intent) {
25104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrantsAll();
252c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            }
253c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        }, intentFilter);
254c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana
255135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        IntentFilter userFilter = new IntentFilter();
256135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        userFilter.addAction(Intent.ACTION_USER_REMOVED);
25767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userFilter.addAction(Intent.ACTION_USER_STARTED);
25867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        mContext.registerReceiverAsUser(new BroadcastReceiver() {
259135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            @Override
260135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            public void onReceive(Context context, Intent intent) {
26167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                String action = intent.getAction();
26267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                if (Intent.ACTION_USER_REMOVED.equals(action)) {
26367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    onUserRemoved(intent);
26467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } else if (Intent.ACTION_USER_STARTED.equals(action)) {
26567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    onUserStarted(intent);
26667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
267135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            }
26867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }, UserHandle.ALL, userFilter, null, null);
269afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana    }
270afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana
27126ff6626fc4ee0ae46f01ad309b366921da589feKenny Root    public void systemReady() {
27226ff6626fc4ee0ae46f01ad309b366921da589feKenny Root    }
27326ff6626fc4ee0ae46f01ad309b366921da589feKenny Root
274258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    private UserManager getUserManager() {
275258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        if (mUserManager == null) {
27627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            mUserManager = UserManager.get(mContext);
277258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        }
278258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani        return mUserManager;
279258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani    }
280258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasani
28104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private UserAccounts initUser(int userId) {
28204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
28304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            UserAccounts accounts = mUsers.get(userId);
28404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            if (accounts == null) {
28504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts = new UserAccounts(mContext, userId);
28604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                mUsers.append(userId, accounts);
28704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrants(accounts);
2886eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey                validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
28904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
29004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return accounts;
29104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
29204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
29304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
29404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void purgeOldGrantsAll() {
29504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
29604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (int i = 0; i < mUsers.size(); i++) {
29704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                purgeOldGrants(mUsers.valueAt(i));
29804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
29904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
30004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
30104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
30204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void purgeOldGrants(UserAccounts accounts) {
30304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
30404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
305c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            final Cursor cursor = db.query(TABLE_GRANTS,
306c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    new String[]{GRANTS_GRANTEE_UID},
307c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    null, null, GRANTS_GRANTEE_UID, null, null);
308c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            try {
309c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                while (cursor.moveToNext()) {
310c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    final int uid = cursor.getInt(0);
311c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
312c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    if (packageExists) {
313c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                        continue;
314c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    }
315c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    Log.d(TAG, "deleting grants for UID " + uid
316c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                            + " because its package is no longer installed");
317c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
318c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                            new String[]{Integer.toString(uid)});
319c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                }
320c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            } finally {
321c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana                cursor.close();
322c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana            }
323c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana        }
324c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana    }
325c1a4e5dc418d324f2fa2827d83002cc50e62c507Fred Quintana
3266eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /**
3276eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * Validate internal set of accounts against installed authenticators for
3286eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * given user. Clears cached authenticators before validating.
3296eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     */
3306eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    public void validateAccounts(int userId) {
3316eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final UserAccounts accounts = getUserAccounts(userId);
3326eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3336eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        // Invalidate user-specific cache to make sure we catch any
3346eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        // removed authenticators.
3356eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
3366eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
3376eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3386eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /**
3396eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * Validate internal set of accounts against installed authenticators for
3406eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     * given user. Clear cached authenticators before validating when requested.
3416eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey     */
3426eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    private void validateAccountsInternal(
3436eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            UserAccounts accounts, boolean invalidateAuthenticatorCache) {
3446eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        if (invalidateAuthenticatorCache) {
3456eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            mAuthenticatorCache.invalidateCache(accounts.userId);
3466eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        }
3476eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
3486ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
3496ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
3506ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.getAllServices(accounts.userId)) {
3516ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            knownAuth.add(service.type);
3526ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
3536ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
35404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
35504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
356f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            boolean accountDeleted = false;
357f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Cursor cursor = db.query(TABLE_ACCOUNTS,
358f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{ACCOUNTS_ID, ACCOUNTS_TYPE, ACCOUNTS_NAME},
359f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    null, null, null, null, null);
360f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
36104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.clear();
36256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final HashMap<String, ArrayList<String>> accountNamesByType =
363b483a99c6bdfee72fbb8fbcf893e63ef3f54658bAmith Yamasani                        new LinkedHashMap<String, ArrayList<String>>();
36456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                while (cursor.moveToNext()) {
36556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final long accountId = cursor.getLong(0);
36656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountType = cursor.getString(1);
36756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountName = cursor.getString(2);
3686ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
3696ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
3706eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey                        Slog.w(TAG, "deleting account " + accountName + " because type "
37156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + accountType + " no longer has a registered authenticator");
37256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
37356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountDeleted = true;
37456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        final Account account = new Account(accountName, accountType);
37504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        accounts.userDataCache.remove(account);
37604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        accounts.authTokenCache.remove(account);
37756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    } else {
37856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        ArrayList<String> accountNames = accountNamesByType.get(accountType);
37956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (accountNames == null) {
38056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            accountNames = new ArrayList<String>();
38156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            accountNamesByType.put(accountType, accountNames);
38256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
38356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountNames.add(accountName);
38456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
38556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                }
3862f36229db823d152f3efd879e751e81a601a75b0Andy McFadden                for (Map.Entry<String, ArrayList<String>> cur
387f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        : accountNamesByType.entrySet()) {
38856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final String accountType = cur.getKey();
38956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final ArrayList<String> accountNames = cur.getValue();
39056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    final Account[] accountsForType = new Account[accountNames.size()];
39156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    int i = 0;
39256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    for (String accountName : accountNames) {
39356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        accountsForType[i] = new Account(accountName, accountType);
39456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        ++i;
39556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
39604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    accounts.accountCache.put(accountType, accountsForType);
397afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana                }
398f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
399f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                cursor.close();
400f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountDeleted) {
40104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    sendAccountsChangedBroadcast(accounts.userId);
402f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
403afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana            }
404afa92b8f3d8f85fe2dde309f8f778926396539eaFred Quintana        }
4053ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana    }
4063ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana
40704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private UserAccounts getUserAccountsForCaller() {
408f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        return getUserAccounts(UserHandle.getCallingUserId());
40904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
41004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
41104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected UserAccounts getUserAccounts(int userId) {
41204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (mUsers) {
41304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            UserAccounts accounts = mUsers.get(userId);
41404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            if (accounts == null) {
41504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts = initUser(userId);
41604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                mUsers.append(userId, accounts);
41704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
41804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return accounts;
41904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
42004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
42104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
422135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    private void onUserRemoved(Intent intent) {
4232a00329c6d55c6cd9166e01963d7410e95d80d21Amith Yamasani        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
424135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        if (userId < 1) return;
425135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
426135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        UserAccounts accounts;
427135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        synchronized (mUsers) {
428135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            accounts = mUsers.get(userId);
429135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            mUsers.remove(userId);
430135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
431135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        if (accounts == null) {
432135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            File dbFile = new File(getDatabaseName(userId));
433135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            dbFile.delete();
434135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            return;
435135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
436135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
437135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        synchronized (accounts.cacheLock) {
438135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            accounts.openHelper.close();
439135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            File dbFile = new File(getDatabaseName(userId));
440135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani            dbFile.delete();
441135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani        }
442135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani    }
443135936072b24b090fb63940aea41b408d855a4f3Amith Yamasani
44467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private void onUserStarted(Intent intent) {
44567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
44667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (userId < 1) return;
44767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
44867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        // Check if there's a shared account that needs to be created as an account
44967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] sharedAccounts = getSharedAccountsAsUser(userId);
45067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (sharedAccounts == null || sharedAccounts.length == 0) return;
45167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] accounts = getAccountsAsUser(null, userId);
45267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        for (Account sa : sharedAccounts) {
45367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (ArrayUtils.contains(accounts, sa)) continue;
45467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Account doesn't exist. Copy it now.
45567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            copyAccountToUser(sa, UserHandle.USER_OWNER, userId);
45667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
45767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
45867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
4596ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    @Override
4606ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    public void onServiceChanged(AuthenticatorDescription desc, int userId, boolean removed) {
4616eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        validateAccountsInternal(getUserAccounts(userId), false /* invalidateAuthenticatorCache */);
462603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
463603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
464a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String getPassword(Account account) {
46556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
46656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getPassword: " + account
46756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
46856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
46956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
470382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
471d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
472d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
47304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
47426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
475603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
47604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readPasswordInternal(accounts, account);
477603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
47826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
479603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
480603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
481603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
48204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private String readPasswordInternal(UserAccounts accounts, Account account) {
48331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null) {
48431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return null;
48531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
48631957f1badbb900bbfe211317e1ea992d650a72dFred Quintana
48704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
48804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
489f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
490f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
491f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{account.name, account.type}, null, null, null);
492f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
493f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (cursor.moveToNext()) {
494f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return cursor.getString(0);
495f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
496f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return null;
497f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
498f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                cursor.close();
499ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
500ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
501ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
502ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
503a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String getUserData(Account account, String key) {
50456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
50556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getUserData: " + account
50656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", key " + key
50756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
50856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
50956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
510382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
511382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (key == null) throw new IllegalArgumentException("key is null");
512d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
51304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
51426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
515603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
51604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readUserDataInternal(accounts, account, key);
517ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
518ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
519ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
520ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
521ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
5229788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana    public AuthenticatorDescription[] getAuthenticatorTypes() {
52356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
52456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAuthenticatorTypes: "
52556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + "caller's uid " + Binder.getCallingUid()
52656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
52756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
5286ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int userId = UserHandle.getCallingUserId();
5296ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final long identityToken = clearCallingIdentity();
53026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
5319788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
5326ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
5339788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            AuthenticatorDescription[] types =
5349788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana                    new AuthenticatorDescription[authenticatorCollection.size()];
53526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            int i = 0;
5369788976b1465ce982b5ae7c741345edd0ecd9322Fred Quintana            for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
537718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana                    : authenticatorCollection) {
538718d8a2d7ff3e864a73879eb646f46c14ab74d07Fred Quintana                types[i] = authenticator.type;
53926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                i++;
54026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
54126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            return types;
54226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
54326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
544a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
545a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
546a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
5473df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia    @Override
54827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
54956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
55027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            Log.v(TAG, "addAccountExplicitly: " + account
55156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
55256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
55356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
554382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
555d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
5563df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia        /*
5573df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * Child users are not allowed to add accounts. Only the accounts that are
5583df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * shared by the parent profile can be added to child profile.
5593df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         *
5603df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         * TODO: Only allow accounts that were shared to be added by
5613df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         *     a limited user.
5623df7d697ca86ee2081bcfba31bcbd3ae4f4bcdf8Jatin Lodhia         */
563d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
56404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
565603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        // fails if the account already exists
56626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
567603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
56867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return addAccountInternal(accounts, account, password, extras, false);
56967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
57067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            restoreCallingIdentity(identityToken);
57167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
57267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
57367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
57467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private boolean copyAccountToUser(final Account account, int userFrom, int userTo) {
57567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        final UserAccounts fromAccounts = getUserAccounts(userFrom);
57667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        final UserAccounts toAccounts = getUserAccounts(userTo);
57767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (fromAccounts == null || toAccounts == null) {
57867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return false;
57967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
58067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
58167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long identityToken = clearCallingIdentity();
58267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
58367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            new Session(fromAccounts, null, account.type, false,
58467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    false /* stripAuthTokenFromResult */) {
58567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                protected String toDebugString(long now) {
58667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    return super.toDebugString(now) + ", getAccountCredentialsForClone"
58767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            + ", " + account.type;
58867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
58967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
59067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void run() throws RemoteException {
59167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mAuthenticator.getAccountCredentialsForCloning(this, account);
59267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
59367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
59467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onResult(Bundle result) {
59567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (result != null) {
59667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
59767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // Create a Session for the target user and pass in the bundle
59867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            completeCloningAccount(result, account, toAccounts);
59967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        }
60067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        return;
60167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    } else {
60267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        super.onResult(result);
60367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
60467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
60567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }.bind();
606ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
607ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
608ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
60967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return true;
61067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
61167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
61267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    void completeCloningAccount(final Bundle result, final Account account,
61367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            final UserAccounts targetUser) {
61467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long id = clearCallingIdentity();
61567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
61667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            new Session(targetUser, null, account.type, false,
61767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    false /* stripAuthTokenFromResult */) {
61867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                protected String toDebugString(long now) {
61967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    return super.toDebugString(now) + ", getAccountCredentialsForClone"
62067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            + ", " + account.type;
62167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
62267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
62367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void run() throws RemoteException {
6245be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    // Confirm that the owner's account still exists before this step.
6255be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
6265be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    synchronized (owner.cacheLock) {
6275be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        Account[] ownerAccounts = getAccounts(UserHandle.USER_OWNER);
6285be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        for (Account acc : ownerAccounts) {
6295be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                            if (acc.equals(account)) {
6305be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                mAuthenticator.addAccountFromCredentials(this, account, result);
6315be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                break;
6325be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                            }
6335be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        }
6345be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    }
63567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
63667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
63767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onResult(Bundle result) {
63867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (result != null) {
63967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
64067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Anything?
64167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        } else {
64267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Show error notification
64367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            // TODO: Should we remove the shadow account to avoid retries?
64467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        }
64567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        return;
64667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    } else {
64767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        super.onResult(result);
64867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
64967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
65067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
65167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                public void onError(int errorCode, String errorMessage) {
65267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    super.onError(errorCode,  errorMessage);
65367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    // TODO: Show error notification to user
65467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    // TODO: Should we remove the shadow account so that it doesn't keep trying?
65567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
65667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
65767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }.bind();
65867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
65967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            restoreCallingIdentity(id);
66067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
661ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
662ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
66304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
66467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            Bundle extras, boolean restricted) {
665743dfad2a51e016ddb741c104317637089187753Fred Quintana        if (account == null) {
666743dfad2a51e016ddb741c104317637089187753Fred Quintana            return false;
667743dfad2a51e016ddb741c104317637089187753Fred Quintana        }
66804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
66904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
670f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
671f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
672f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long numMatches = DatabaseUtils.longForQuery(db,
673f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        "select count(*) from " + TABLE_ACCOUNTS
674f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
675f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        new String[]{account.name, account.type});
676f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (numMatches > 0) {
677f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    Log.w(TAG, "insertAccountIntoDatabase: " + account
678f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            + ", skipping since the account already exists");
679f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
680f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
681f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                ContentValues values = new ContentValues();
682f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_NAME, account.name);
683f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_TYPE, account.type);
684f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_PASSWORD, password);
685f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
686f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
687f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    Log.w(TAG, "insertAccountIntoDatabase: " + account
688f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            + ", skipping the DB insert failed");
689f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
690f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
691f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (extras != null) {
692f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    for (String key : extras.keySet()) {
693f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        final String value = extras.getString(key);
694f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        if (insertExtraLocked(db, accountId, key, value) < 0) {
695f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            Log.w(TAG, "insertAccountIntoDatabase: " + account
696f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    + ", skipping since insertExtra failed for key " + key);
697f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            return false;
698f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        }
699603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    }
700603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                }
701f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.setTransactionSuccessful();
70204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                insertAccountIntoCacheLocked(accounts, account);
703f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
704f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
705603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
70604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
7075be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        }
7085be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        if (accounts.userId == UserHandle.USER_OWNER) {
7095be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani            addAccountToLimitedUsers(account);
7105be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        }
7115be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        return true;
7125be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    }
7135be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani
7145be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    /**
7155be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     * Adds the account to all limited users as shared accounts. If the user is currently
7165be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     * running, then clone the account too.
7175be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     * @param account the account to share with limited users
7185be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani     */
7195be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani    private void addAccountToLimitedUsers(Account account) {
720f4c240e68a3da9f1ebf42267c88af40c19ff49daMita Yun        List<UserInfo> users = getUserManager().getUsers();
7215be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani        for (UserInfo user : users) {
7225be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani            if (user.isRestricted()) {
7235be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                addSharedAccountAsUser(account, user.id);
7245be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                try {
7255be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    if (ActivityManagerNative.getDefault().isUserRunning(user.id, false)) {
7265be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                        mMessageHandler.sendMessage(mMessageHandler.obtainMessage(
7275be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                MESSAGE_COPY_SHARED_ACCOUNT, UserHandle.USER_OWNER, user.id,
7285be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                                account));
7295be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    }
7305be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                } catch (RemoteException re) {
7315be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    // Shouldn't happen
7325be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                }
7335be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani            }
734603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
735603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
736603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
737f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long insertExtraLocked(SQLiteDatabase db, long accountId, String key, String value) {
738603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        ContentValues values = new ContentValues();
739603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_KEY, key);
740603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_ACCOUNTS_ID, accountId);
741603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        values.put(EXTRAS_VALUE, value);
742603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values);
743603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
744603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
7453084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana    public void hasFeatures(IAccountManagerResponse response,
746bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            Account account, String[] features) {
74756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
74856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "hasFeatures: " + account
74956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
75056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", features " + stringArrayToString(features)
75156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
75256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
75356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
754382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
755382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
756382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (features == null) throw new IllegalArgumentException("features is null");
757bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        checkReadAccountsPermission();
75804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
759bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        long identityToken = clearCallingIdentity();
760bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        try {
76104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new TestFeaturesSession(accounts, response, account, features).bind();
762bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        } finally {
763bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            restoreCallingIdentity(identityToken);
764bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
765bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    }
766bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
767bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    private class TestFeaturesSession extends Session {
768bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        private final String[] mFeatures;
769bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        private final Account mAccount;
770bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
77104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public TestFeaturesSession(UserAccounts accounts, IAccountManagerResponse response,
772bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                Account account, String[] features) {
77304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, account.type, false /* expectActivityLaunch */,
7748570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
775bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            mFeatures = features;
776bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            mAccount = account;
777bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
778bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
779bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        public void run() throws RemoteException {
780bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            try {
781bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                mAuthenticator.hasFeatures(this, mAccount, mFeatures);
782bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            } catch (RemoteException e) {
783bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
784bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            }
785bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
786bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
787bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        public void onResult(Bundle result) {
788bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
789bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            if (response != null) {
790bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                try {
791bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    if (result == null) {
792166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
793bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                        return;
794bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    }
79556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
79656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
79756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
79856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
799bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    final Bundle newResult = new Bundle();
800bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    newResult.putBoolean(AccountManager.KEY_BOOLEAN_RESULT,
801bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                            result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false));
802bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    response.onResult(newResult);
803bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                } catch (RemoteException e) {
804bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
805bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
806bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
807bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    }
808bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                }
809bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana            }
810bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
811bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana
812bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        protected String toDebugString(long now) {
8133084a6f80180506ce26fe4773d9a19f004b7f625Fred Quintana            return super.toDebugString(now) + ", hasFeatures"
814bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    + ", " + mAccount
815bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana                    + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
816bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana        }
817bb68a4fc54231e147d91fe3668d1409ccfd81a45Fred Quintana    }
818307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
819ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    public void removeAccount(IAccountManagerResponse response, Account account) {
82056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
82156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "removeAccount: " + account
82256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
82356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
82456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
82556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
826382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
827382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
828d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
82950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        UserHandle user = Binder.getCallingUserHandle();
83004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
831e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        if (!canUserModifyAccounts(Binder.getCallingUid())) {
832e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            try {
833e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
834e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                        "User cannot modify accounts");
835e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            } catch (RemoteException re) {
836e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            }
837e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        }
838e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani
83926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
840ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache
84150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
84204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized(accounts.credentialsPermissionNotificationIds) {
843ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache            for (Pair<Pair<Account, String>, Integer> pair:
84404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.credentialsPermissionNotificationIds.keySet()) {
845ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache                if (account.equals(pair.first.first)) {
84604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    int id = accounts.credentialsPermissionNotificationIds.get(pair);
84750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    cancelNotification(id, user);
848ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache                }
849ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache            }
850ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache        }
851ec0c4f4183630a64c2b2cc8f961dc7e11cc628caCostin Manolache
85226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
85304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new RemoveAccountSession(accounts, response, account).bind();
85426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
85526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
856a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
857603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
858603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
859ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    private class RemoveAccountSession extends Session {
860ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        final Account mAccount;
86104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response,
86204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                Account account) {
86304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, account.type, false /* expectActivityLaunch */,
8648570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
865ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            mAccount = account;
866ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
867ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
868ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        protected String toDebugString(long now) {
869ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            return super.toDebugString(now) + ", removeAccount"
870ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    + ", account " + mAccount;
871ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
872ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
873ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        public void run() throws RemoteException {
874ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            mAuthenticator.getAccountRemovalAllowed(this, mAccount);
875ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
876ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
877ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        public void onResult(Bundle result) {
878f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result != null && result.containsKey(AccountManager.KEY_BOOLEAN_RESULT)
879f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    && !result.containsKey(AccountManager.KEY_INTENT)) {
880f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                final boolean removalAllowed = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
881ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                if (removalAllowed) {
88204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    removeAccountInternal(mAccounts, mAccount);
883ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                }
884ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                IAccountManagerResponse response = getResponseAndClose();
885ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                if (response != null) {
88656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
88756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
88856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
88956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
890ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    Bundle result2 = new Bundle();
891f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result2.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, removalAllowed);
892ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    try {
893ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                        response.onResult(result2);
894ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    } catch (RemoteException e) {
895ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                        // ignore
896ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    }
897ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                }
898ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
899ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            super.onResult(result);
900ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
901ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
902ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
90304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    /* For testing */
904f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected void removeAccountInternal(Account account) {
90504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        removeAccountInternal(getUserAccountsForCaller(), account);
90604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
90704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
90804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAccountInternal(UserAccounts accounts, Account account) {
90904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
91004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
911f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
912f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    new String[]{account.name, account.type});
91304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            removeAccountFromCacheLocked(accounts, account);
91404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
915f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
91667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (accounts.userId == UserHandle.USER_OWNER) {
91767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Owner's account was removed, remove from any users that are sharing
91867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // this account.
91967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            long id = Binder.clearCallingIdentity();
92067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            try {
92167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                List<UserInfo> users = mUserManager.getUsers(true);
92267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                for (UserInfo user : users) {
92367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    if (!user.isPrimary() && user.isRestricted()) {
92467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                        removeSharedAccountAsUser(account, user.id);
92567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    }
92667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
92767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            } finally {
92867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                Binder.restoreCallingIdentity(id);
92967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
93067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
931ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
932ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
933a12fccf57d5ec289793699d9b22ff45daccd3933Maggie Benthall    @Override
934a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void invalidateAuthToken(String accountType, String authToken) {
93556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
93656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "invalidateAuthToken: accountType " + accountType
93756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
93856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
93956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
940382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
941382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authToken == null) throw new IllegalArgumentException("authToken is null");
942b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        checkManageAccountsOrUseCredentialsPermissions();
94304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
94426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
945603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
94604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
94704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
948f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.beginTransaction();
949f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                try {
95004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    invalidateAuthTokenLocked(accounts, db, accountType, authToken);
951f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
952f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } finally {
953f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.endTransaction();
954f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
95526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
956603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
95726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
958603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
959603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
960603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
96104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db,
96204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String accountType, String authToken) {
963ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        if (authToken == null || accountType == null) {
964ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            return;
965ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
9663326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        Cursor cursor = db.rawQuery(
9673326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                "SELECT " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID
9683326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME
9693326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + ", " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_TYPE
9703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " FROM " + TABLE_ACCOUNTS
9713326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " JOIN " + TABLE_AUTHTOKENS
9723326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " ON " + TABLE_ACCOUNTS + "." + ACCOUNTS_ID
9733326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " = " + AUTHTOKENS_ACCOUNTS_ID
9743326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + " WHERE " + AUTHTOKENS_AUTHTOKEN + " = ? AND "
9753326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        + TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " = ?",
9763326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                new String[]{authToken, accountType});
9773326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        try {
9783326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            while (cursor.moveToNext()) {
9793326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                long authTokenId = cursor.getLong(0);
9803326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                String accountName = cursor.getString(1);
9813326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                String authTokenType = cursor.getString(2);
9823326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null);
98304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                writeAuthTokenIntoCacheLocked(accounts, db, new Account(accountName, accountType),
984f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        authTokenType, null);
985603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
9863326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        } finally {
9873326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            cursor.close();
988603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
989603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
990603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
99104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean saveAuthTokenToDatabase(UserAccounts accounts, Account account, String type,
99204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String authToken) {
99331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || type == null) {
99431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return false;
99531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
99650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        cancelNotification(getSigninRequiredNotificationId(accounts, account),
99750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                new UserHandle(accounts.userId));
99804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
99904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1000f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1001f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1002f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
1003f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
1004f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return false;
1005f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
1006f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.delete(TABLE_AUTHTOKENS,
1007f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        AUTHTOKENS_ACCOUNTS_ID + "=" + accountId + " AND " + AUTHTOKENS_TYPE + "=?",
1008f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        new String[]{type});
1009f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                ContentValues values = new ContentValues();
1010f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_ACCOUNTS_ID, accountId);
1011f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_TYPE, type);
1012f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(AUTHTOKENS_AUTHTOKEN, authToken);
1013f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (db.insert(TABLE_AUTHTOKENS, AUTHTOKENS_AUTHTOKEN, values) >= 0) {
1014f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
101504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    writeAuthTokenIntoCacheLocked(accounts, db, account, type, authToken);
1016f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    return true;
1017f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
10183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return false;
1019f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1020f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
10213326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
1022603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1023603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1024603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1025a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public String peekAuthToken(Account account, String authTokenType) {
102656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
102756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "peekAuthToken: " + account
102856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
102956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
103056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
103156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1032382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1033382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1034d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
103504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
103626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
103726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
103804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            return readAuthTokenInternal(accounts, account, authTokenType);
103926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
104026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
1041603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1042603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1043603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1044a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setAuthToken(Account account, String authTokenType, String authToken) {
104556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
104656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setAuthToken: " + account
104756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
104856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
104956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
105056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1051382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1052382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1053d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
105404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
105526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
105626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
105704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            saveAuthTokenToDatabase(accounts, account, authTokenType, authToken);
105826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
105926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
106026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1061603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1062603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1063a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setPassword(Account account, String password) {
106456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
106556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setAuthToken: " + account
106656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
106756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
106856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1069382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1070d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
107104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
107226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
107326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
107404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setPasswordInternal(accounts, account, password);
107526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
107626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
107726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1078603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1079603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
108004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void setPasswordInternal(UserAccounts accounts, Account account, String password) {
108131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null) {
108231957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
108331957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
108404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
108504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1086f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1087f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1088f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                final ContentValues values = new ContentValues();
1089f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                values.put(ACCOUNTS_PASSWORD, password);
1090f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                final long accountId = getAccountIdLocked(db, account);
1091f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
1092f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    final String[] argsAccountId = {String.valueOf(accountId)};
1093f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
1094f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
109504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                    accounts.authTokenCache.remove(account);
1096f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
1097f5ffe89e736caee1419f0acb469565d5100b8fb8Costin Manolache                }
1098f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1099f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
1100d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana            }
110104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            sendAccountsChangedBroadcast(accounts.userId);
1102d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana        }
11033ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana    }
11043ecd5f437580e49d80beecd29489d5fb1f7a7db0Fred Quintana
110504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void sendAccountsChangedBroadcast(int userId) {
110656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Log.i(TAG, "the accounts changed, sending broadcast of "
110756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                + ACCOUNTS_CHANGED_INTENT.getAction());
110879af1dd54c16cde063152922b42c96d72ae9eca8Dianne Hackborn        mContext.sendBroadcastAsUser(ACCOUNTS_CHANGED_INTENT, new UserHandle(userId));
11093326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
11103326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
1111a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void clearPassword(Account account) {
111256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
111356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "clearPassword: " + account
111456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
111556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
111656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1117382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1118d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
111904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
112026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
112126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
112204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setPasswordInternal(accounts, account, null);
112326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
112426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
112526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1126603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1127603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1128a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void setUserData(Account account, String key, String value) {
112956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
113056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "setUserData: " + account
113156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", key " + key
113256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
113356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
113456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1135382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (key == null) throw new IllegalArgumentException("key is null");
1136382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1137d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkAuthenticateAccountsPermission(account);
113804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
113926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
1140603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
114104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            setUserdataInternal(accounts, account, key, value);
1142ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
1143ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
1144ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
1145ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
1146ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
114704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void setUserdataInternal(UserAccounts accounts, Account account, String key,
114804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String value) {
114931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || key == null) {
115031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
115131957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
115204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
115304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
1154f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
1155f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
1156f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
1157f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId < 0) {
1158ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                    return;
115926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1160f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long extrasId = getExtrasIdLocked(db, accountId, key);
1161f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (extrasId < 0 ) {
1162f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    extrasId = insertExtraLocked(db, accountId, key, value);
1163f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (extrasId < 0) {
1164f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        return;
1165f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
1166f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } else {
1167f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ContentValues values = new ContentValues();
1168f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(EXTRAS_VALUE, value);
1169f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
1170f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        return;
1171f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
1172ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
1173f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
117404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                writeUserDataIntoCacheLocked(accounts, db, account, key, value);
1175f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.setTransactionSuccessful();
1176f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
1177f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
1178603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1179603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1180603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1181603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1182d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void onResult(IAccountManagerResponse response, Bundle result) {
118356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (result == null) {
118456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.e(TAG, "the result is unexpectedly null", new Exception());
118556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
118656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
118756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
118856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + response);
118956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1190d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        try {
1191d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            response.onResult(result);
1192d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        } catch (RemoteException e) {
1193d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // if the caller is dead then there is no one to care about remote
1194d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // exceptions
1195d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
1196d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                Log.v(TAG, "failure while notifying response", e);
1197d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1198d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1199d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1200d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1201d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType,
1202d9640ec712806508877868d08aafaa2d715ff441Fred Quintana                                  final String authTokenType)
1203d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throws RemoteException {
1204d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
12055f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
12065f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1207d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        final int callingUid = getCallingUid();
1208d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        clearCallingIdentity();
120927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callingUid != Process.SYSTEM_UID) {
1210d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throw new SecurityException("can only call from system");
1211d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
1212f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid));
12135f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        long identityToken = clearCallingIdentity();
12145f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        try {
1215d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            new Session(accounts, response, accountType, false,
12165f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    false /* stripAuthTokenFromResult */) {
12175f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                protected String toDebugString(long now) {
12185f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    return super.toDebugString(now) + ", getAuthTokenLabel"
1219d9640ec712806508877868d08aafaa2d715ff441Fred Quintana                            + ", " + accountType
12205f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                            + ", authTokenType " + authTokenType;
12215f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
12225f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
12235f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                public void run() throws RemoteException {
12245f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    mAuthenticator.getAuthTokenLabel(this, authTokenType);
12255f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
12265f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
12275f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                public void onResult(Bundle result) {
12285f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    if (result != null) {
12295f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        String label = result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL);
12305f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        Bundle bundle = new Bundle();
12315f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        bundle.putString(AccountManager.KEY_AUTH_TOKEN_LABEL, label);
12325f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        super.onResult(bundle);
12335f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        return;
12345f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    } else {
12355f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                        super.onResult(result);
12365f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                    }
12375f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache                }
12385f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            }.bind();
12395f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        } finally {
12405f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            restoreCallingIdentity(identityToken);
12415f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache        }
12425f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache    }
12435f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1244a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void getAuthToken(IAccountManagerResponse response, final Account account,
1245a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final String authTokenType, final boolean notifyOnAuthFailure,
1246c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache            final boolean expectActivityLaunch, Bundle loginOptionsIn) {
124756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
124856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAuthToken: " + account
124956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
125056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
125156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", notifyOnAuthFailure " + notifyOnAuthFailure
125256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
125356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
125456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
125556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1256382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1257382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1258382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1259d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
12604120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        final UserAccounts accounts = getUserAccountsForCaller();
12616ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
12626ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        authenticatorInfo = mAuthenticatorCache.getServiceInfo(
12636ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                AuthenticatorDescription.newKey(account.type), accounts.userId);
1264a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        final boolean customTokens =
1265a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            authenticatorInfo != null && authenticatorInfo.type.customTokens;
1266a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache
1267a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        // skip the check if customTokens
1268b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int callerUid = Binder.getCallingUid();
1269a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        final boolean permissionGranted = customTokens ||
1270a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            permissionIsGranted(account, authTokenType, callerUid);
1271a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache
1272c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache        final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
1273c6684f9e9790e92960504e9b32f20f27003d9f37Costin Manolache            loginOptionsIn;
1274b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        // let authenticator know the identity of the caller
1275b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
1276b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
1277b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        if (notifyOnAuthFailure) {
1278b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache            loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
1279a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache        }
12806ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
128126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
128226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
1283d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // if the caller has permission, do the peek. otherwise go the more expensive
1284d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            // route of starting a Session
1285a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache            if (!customTokens && permissionGranted) {
128604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                String authToken = readAuthTokenInternal(accounts, account, authTokenType);
1287d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                if (authToken != null) {
128826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    Bundle result = new Bundle();
1289f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_AUTHTOKEN, authToken);
1290f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
1291f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
1292d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    onResult(response, result);
1293d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    return;
1294a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
1295a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1296603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
129704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
12988570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    false /* stripAuthTokenFromResult */) {
129926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
130026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (loginOptions != null) loginOptions.keySet();
130126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", getAuthToken"
130226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account
130326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", authTokenType " + authTokenType
130426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", loginOptions " + loginOptions
130526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", notifyOnAuthFailure " + notifyOnAuthFailure;
130626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1307a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
130826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
1309d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    // If the caller doesn't have permission then create and return the
1310d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    // "grant permission" intent instead of the "getAuthToken" intent.
1311d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    if (!permissionGranted) {
1312d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        mAuthenticator.getAuthTokenLabel(this, authTokenType);
1313d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    } else {
1314d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        mAuthenticator.getAuthToken(this, account, authTokenType, loginOptions);
1315d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    }
131626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1317a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
131826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void onResult(Bundle result) {
131926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (result != null) {
1320f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        if (result.containsKey(AccountManager.KEY_AUTH_TOKEN_LABEL)) {
1321d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            Intent intent = newGrantCredentialsPermissionIntent(account, callerUid,
1322d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                                    new AccountAuthenticatorResponse(this),
1323d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                                    authTokenType,
1324f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                    result.getString(AccountManager.KEY_AUTH_TOKEN_LABEL));
1325d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            Bundle bundle = new Bundle();
1326f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            bundle.putParcelable(AccountManager.KEY_INTENT, intent);
1327d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            onResult(bundle);
1328d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            return;
1329d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        }
1330f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        String authToken = result.getString(AccountManager.KEY_AUTHTOKEN);
133126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                        if (authToken != null) {
1332f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            String name = result.getString(AccountManager.KEY_ACCOUNT_NAME);
1333f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                            String type = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
133426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) {
1335f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
133626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                                        "the type and name should not be empty");
133726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                                return;
133826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            }
1339a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                            if (!customTokens) {
134004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                                saveAuthTokenToDatabase(mAccounts, new Account(name, type),
1341a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                                        authTokenType, authToken);
1342a40c6304deb860f10a51ce950ac1abc21a23d08bCostin Manolache                            }
1343a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        }
1344603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1345f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
1346d606045070dcf6a011e49a7711d2f17d8f2de8c1Costin Manolache                        if (intent != null && notifyOnAuthFailure && !customTokens) {
134704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                            doNotification(mAccounts,
1348f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                                    account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
13494120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                                    intent, accounts.userId);
135026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                        }
1351a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
135226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    super.onResult(result);
1353a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
135426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
135526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
135626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
135726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1358603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1359603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
13604120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn    private void createNoCredentialsPermissionNotification(Account account, Intent intent,
13614120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            int userId) {
1362d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        int uid = intent.getIntExtra(
1363d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, -1);
1364d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        String authTokenType = intent.getStringExtra(
1365d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE);
1366d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        String authTokenLabel = intent.getStringExtra(
1367d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
1368d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1369d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
1370d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                0 /* when */);
1371ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer        final String titleAndSubtitle =
1372ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer                mContext.getString(R.string.permission_request_notification_with_subtitle,
1373ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer                account.name);
1374ee452ee5359cdfa3c3fbf6783722d3aaa2ec5ca6Eric Fischer        final int index = titleAndSubtitle.indexOf('\n');
137585e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        String title = titleAndSubtitle;
137685e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        String subtitle = "";
137785e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        if (index > 0) {
137885e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache            title = titleAndSubtitle.substring(0, index);
1379a12fccf57d5ec289793699d9b22ff45daccd3933Maggie Benthall            subtitle = titleAndSubtitle.substring(index + 1);
138085e7279d9cc1ee8e4dd1f993a9e61a9eb547ecbcCostin Manolache        }
138150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        UserHandle user = new UserHandle(userId);
13824120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        n.setLatestEventInfo(mContext, title, subtitle,
13834120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                PendingIntent.getActivityAsUser(mContext, 0, intent,
138450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                        PendingIntent.FLAG_CANCEL_CURRENT, null, user));
138550cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn        installNotification(getCredentialPermissionNotificationId(
138650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                account, authTokenType, uid), n, user);
1387d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1388d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
13895f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
13905f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
1391d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1392d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
139346703b099516c383a6882815bcf9cd4df0ec538dBrian Carlstrom        // See FLAG_ACTIVITY_NEW_TASK docs for limitations and benefits of the flag.
13949ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        // Since it was set in Eclair+ we can't change it without breaking apps using
13959ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        // the intent from a non-Activity context.
13969ec17366c17efd14c643ee88fa1132ab05197349Costin Manolache        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1397d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.addCategory(
1398d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                String.valueOf(getCredentialPermissionNotificationId(account, authTokenType, uid)));
13995f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1400d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_ACCOUNT, account);
1401d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_TYPE, authTokenType);
1402d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_RESPONSE, response);
1403d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        intent.putExtra(GrantCredentialsPermissionActivity.EXTRAS_REQUESTING_UID, uid);
14045f383ad9695a62d6c1aeb97c8e550d7fffe26244Costin Manolache
1405d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return intent;
1406d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1407d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
1408d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private Integer getCredentialPermissionNotificationId(Account account, String authTokenType,
1409d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            int uid) {
1410d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Integer id;
1411f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
141204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.credentialsPermissionNotificationIds) {
1413d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            final Pair<Pair<Account, String>, Integer> key =
1414d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    new Pair<Pair<Account, String>, Integer>(
1415d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            new Pair<Account, String>(account, authTokenType), uid);
141604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            id = accounts.credentialsPermissionNotificationIds.get(key);
1417d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (id == null) {
1418d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                id = mNotificationIds.incrementAndGet();
141904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.credentialsPermissionNotificationIds.put(key, id);
1420d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1421d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1422d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return id;
1423d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1424d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
142504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private Integer getSigninRequiredNotificationId(UserAccounts accounts, Account account) {
1426d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        Integer id;
142704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.signinRequiredNotificationIds) {
142804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            id = accounts.signinRequiredNotificationIds.get(account);
1429d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (id == null) {
1430d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                id = mNotificationIds.incrementAndGet();
143104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.signinRequiredNotificationIds.put(account, id);
1432d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
1433d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
1434d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return id;
1435d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
1436d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
143727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    public void addAccount(final IAccountManagerResponse response, final String accountType,
14383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            final String authTokenType, final String[] requiredFeatures,
1439b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache            final boolean expectActivityLaunch, final Bundle optionsIn) {
144056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
144156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "addAccount: accountType " + accountType
144256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
144356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
144456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", requiredFeatures " + stringArrayToString(requiredFeatures)
144556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
144656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
144756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
144856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1449382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1450382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
1451d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
1452b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
145371e6c697e54a43d357cc25d87a446d140f17396aAmith Yamasani        // Is user disallowed from modifying accounts?
145427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (!canUserModifyAccounts(Binder.getCallingUid())) {
1455df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            try {
1456df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
1457df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                        "User is not allowed to add an account!");
1458df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            } catch (RemoteException re) {
1459df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
146023c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            Intent cantAddAccount = new Intent(mContext, CantAddAccountActivity.class);
146123c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            cantAddAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
146223c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            long identityToken = clearCallingIdentity();
146323c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            try {
146423c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani                mContext.startActivityAsUser(cantAddAccount, UserHandle.CURRENT);
146523c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            } finally {
146623c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani                restoreCallingIdentity(identityToken);
146723c8b96a7e5c3f4c169bf65ae3886357943bb7b0Amith Yamasani            }
1468df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return;
1469df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
1470df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani
147104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
1472b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int pid = Binder.getCallingPid();
1473b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final int uid = Binder.getCallingUid();
1474b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
1475b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        options.putInt(AccountManager.KEY_CALLER_UID, uid);
1476b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache        options.putInt(AccountManager.KEY_CALLER_PID, pid);
1477b61e8fbabea2cc40ad65bf4f372a32d526cfc7acCostin Manolache
147826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
147926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
148004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, accountType, expectActivityLaunch,
14818570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
148226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
14833348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                    mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
14843326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            options);
148526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
1486a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
148726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
148826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", addAccount"
14893326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + ", accountType " + accountType
14903326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + ", requiredFeatures "
14913326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                            + (requiredFeatures != null
14923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                              ? TextUtils.join(",", requiredFeatures)
14933326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                              : null);
149426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
149526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
149626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
149726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
149826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1499603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1500603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
15012c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
15022c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public void confirmCredentialsAsUser(IAccountManagerResponse response,
15032c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            final Account account, final Bundle options, final boolean expectActivityLaunch,
15042c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            int userId) {
15052c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        // Only allow the system process to read accounts of other users
15062c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        if (userId != UserHandle.getCallingUserId()
150727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                && Binder.getCallingUid() != Process.myUid()) {
15082c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            throw new SecurityException("User " + UserHandle.getCallingUserId()
15092c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    + " trying to confirm account credentials for " + userId);
15102c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        }
15112c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
151256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
151356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "confirmCredentials: " + account
151456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
151556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
151656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
151756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
151856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1519382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1520382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1521d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
15222c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
152326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
152426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
152504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
15268570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
152726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
1528f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    mAuthenticator.confirmCredentials(this, account, options);
152926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
153026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
153126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", confirmCredentials"
153226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account;
153326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
153426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
153526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
153626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
153726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1538603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1539603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1540a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void updateCredentials(IAccountManagerResponse response, final Account account,
1541a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final String authTokenType, final boolean expectActivityLaunch,
1542a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final Bundle loginOptions) {
154356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
154456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "updateCredentials: " + account
154556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
154656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", authTokenType " + authTokenType
154756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
154856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
154956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
155056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1551382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1552382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null) throw new IllegalArgumentException("account is null");
1553382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
1554d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
155504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
155626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
155726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
155804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, account.type, expectActivityLaunch,
15598570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
156026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
156126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
156226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
156326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
156426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    if (loginOptions != null) loginOptions.keySet();
156526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", updateCredentials"
156626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", " + account
156726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", authTokenType " + authTokenType
156826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", loginOptions " + loginOptions;
156926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
157026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
157126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
157226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
157326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1574603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1575603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1576a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    public void editProperties(IAccountManagerResponse response, final String accountType,
1577a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            final boolean expectActivityLaunch) {
157856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
157956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "editProperties: accountType " + accountType
158056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
158156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", expectActivityLaunch " + expectActivityLaunch
158256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
158356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
158456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1585382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1586382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (accountType == null) throw new IllegalArgumentException("accountType is null");
1587d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkManageAccountsPermission();
158804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
158926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
159026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
159104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            new Session(accounts, response, accountType, expectActivityLaunch,
15928570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */) {
159326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                public void run() throws RemoteException {
159426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    mAuthenticator.editProperties(this, mAccountType);
159526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
159626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                protected String toDebugString(long now) {
159726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                    return super.toDebugString(now) + ", editProperties"
159826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                            + ", accountType " + accountType;
159926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                }
160026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }.bind();
160126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
160226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
160326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
1604603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1605603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
16063326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    private class GetAccountsByTypeAndFeatureSession extends Session {
16073326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private final String[] mFeatures;
16083326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile Account[] mAccountsOfType = null;
16093326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile ArrayList<Account> mAccountsWithFeatures = null;
16103326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        private volatile int mCurrentAccount = 0;
1611df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        private int mCallingUid;
16123326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
161304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public GetAccountsByTypeAndFeatureSession(UserAccounts accounts,
1614df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                IAccountManagerResponse response, String type, String[] features, int callingUid) {
161504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(accounts, response, type, false /* expectActivityLaunch */,
16168570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                    true /* stripAuthTokenFromResult */);
1617df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            mCallingUid = callingUid;
16183326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mFeatures = features;
16193326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
16203326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16213326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void run() throws RemoteException {
162204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (mAccounts.cacheLock) {
162327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                mAccountsOfType = getAccountsFromCacheLocked(mAccounts, mAccountType, mCallingUid,
162427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        null);
1625f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
16263326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            // check whether each account matches the requested features
16273326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mAccountsWithFeatures = new ArrayList<Account>(mAccountsOfType.length);
16283326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mCurrentAccount = 0;
16293326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16303326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            checkAccount();
16313326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
16323326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16333326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void checkAccount() {
16343326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (mCurrentAccount >= mAccountsOfType.length) {
16353326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                sendResult();
16363326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return;
16373326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
16383326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
163929e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            final IAccountAuthenticator accountAuthenticator = mAuthenticator;
164029e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            if (accountAuthenticator == null) {
164129e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // It is possible that the authenticator has died, which is indicated by
164229e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // mAuthenticator being set to null. If this happens then just abort.
164329e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // There is no need to send back a result or error in this case since
164429e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                // that already happened when mAuthenticator was cleared.
164529e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
164629e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                    Log.v(TAG, "checkAccount: aborting session since we are no longer"
164729e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                            + " connected to the authenticator, " + toDebugString());
164829e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                }
164929e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                return;
165029e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana            }
16513326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            try {
165229e94b81c7e145a5cb21f8c862e8d05b077b3548Fred Quintana                accountAuthenticator.hasFeatures(this, mAccountsOfType[mCurrentAccount], mFeatures);
16533326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            } catch (RemoteException e) {
1654f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "remote exception");
1655a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1656603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1657603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
16583326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void onResult(Bundle result) {
16593326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mNumResults++;
16603326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (result == null) {
1661f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, "null bundle");
16623326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                return;
16633326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
1664f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
16653326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                mAccountsWithFeatures.add(mAccountsOfType[mCurrentAccount]);
16663326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
16673326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            mCurrentAccount++;
16683326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            checkAccount();
1669a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
16703326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16713326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public void sendResult() {
16723326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
16733326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (response != null) {
16743326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                try {
16753326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    Account[] accounts = new Account[mAccountsWithFeatures.size()];
16763326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    for (int i = 0; i < accounts.length; i++) {
16773326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        accounts[i] = mAccountsWithFeatures.get(i);
16783326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    }
167956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
168056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        Log.v(TAG, getClass().getSimpleName() + " calling onResult() on response "
168156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                + response);
168256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    }
16833326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    Bundle result = new Bundle();
1684f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
16853326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    response.onResult(result);
16863326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                } catch (RemoteException e) {
16873326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
16883326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
16893326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
16903326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    }
16913326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                }
16923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            }
16933326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
16943326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16953326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
16963326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        protected String toDebugString(long now) {
16973326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            return super.toDebugString(now) + ", getAccountsByTypeAndFeatures"
16983326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana                    + ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
16993326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
17003326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
1701ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
170204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    /**
170304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     * Returns the accounts for a specific user
170404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     * @hide
170504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani     */
170604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    public Account[] getAccounts(int userId) {
170704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        checkReadAccountsPermission();
170804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
1709df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        int callingUid = Binder.getCallingUid();
171004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        long identityToken = clearCallingIdentity();
171104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        try {
171204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
171327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                return getAccountsFromCacheLocked(accounts, null, callingUid, null);
171404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
171504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        } finally {
171604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            restoreCallingIdentity(identityToken);
171704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
171804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
171904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani
1720f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani    /**
17216ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey     * Returns accounts for all running users.
17226ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey     *
1723f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani     * @hide
1724f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani     */
17256ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    public AccountAndUser[] getRunningAccounts() {
17266ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int[] runningUserIds;
17276ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        try {
17286ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            runningUserIds = ActivityManagerNative.getDefault().getRunningUserIds();
17296ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        } catch (RemoteException e) {
17306ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            // Running in system_server; should never happen
17316ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            throw new RuntimeException(e);
17326ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
17336eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        return getAccounts(runningUserIds);
17346eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
17356eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
17366eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    /** {@hide} */
17376eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    public AccountAndUser[] getAllAccounts() {
17386eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final List<UserInfo> users = getUserManager().getUsers();
17396eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final int[] userIds = new int[users.size()];
17406eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        for (int i = 0; i < userIds.length; i++) {
17416eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            userIds[i] = users.get(i).id;
17426eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        }
17436eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        return getAccounts(userIds);
17446eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    }
17456ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
17466eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    private AccountAndUser[] getAccounts(int[] userIds) {
17476ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList();
17486ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        synchronized (mUsers) {
17496eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            for (int userId : userIds) {
17506ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                UserAccounts userAccounts = getUserAccounts(userId);
1751f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                if (userAccounts == null) continue;
1752f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                synchronized (userAccounts.cacheLock) {
1753df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
175427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                            Binder.getCallingUid(), null);
1755f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                    for (int a = 0; a < accounts.length; a++) {
17566ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                        runningAccounts.add(new AccountAndUser(accounts[a], userId));
1757f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                    }
1758f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani                }
1759f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani            }
1760f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani        }
17616ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
17626ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        AccountAndUser[] accountsArray = new AccountAndUser[runningAccounts.size()];
17636ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        return runningAccounts.toArray(accountsArray);
1764f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani    }
1765f29f2369cf4e1de090c985ed53d3f5e59535986aAmith Yamasani
17662c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
17672c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public Account[] getAccountsAsUser(String type, int userId) {
176827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        return getAccountsAsUser(type, userId, null, -1);
176927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    }
177027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani
177127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    private Account[] getAccountsAsUser(String type, int userId, String callingPackage,
177227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            int packageUid) {
177327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        int callingUid = Binder.getCallingUid();
17742c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        // Only allow the system process to read accounts of other users
17752c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        if (userId != UserHandle.getCallingUserId()
177627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                && callingUid != Process.myUid()) {
17772c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani            throw new SecurityException("User " + UserHandle.getCallingUserId()
17782c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani                    + " trying to get account for " + userId);
17792c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        }
17802c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
178156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
178256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAccounts: accountType " + type
178356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
178456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
178556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
178627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        // If the original calling app was using the framework account chooser activity, we'll
178727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        // be passed in the original caller's uid here, which is what should be used for filtering.
178827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (packageUid != -1 && UserHandle.isSameApp(callingUid, Process.myUid())) {
178927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            callingUid = packageUid;
179027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        }
1791ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        checkReadAccountsPermission();
17922c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        UserAccounts accounts = getUserAccounts(userId);
1793ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        long identityToken = clearCallingIdentity();
1794ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        try {
179504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            synchronized (accounts.cacheLock) {
179627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage);
1797f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
1798ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        } finally {
1799ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            restoreCallingIdentity(identityToken);
1800ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana        }
1801ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    }
1802ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana
18032c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    @Override
180467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public boolean addSharedAccountAsUser(Account account, int userId) {
180567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
180667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        SQLiteDatabase db = getUserAccounts(userId).openHelper.getWritableDatabase();
180767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        ContentValues values = new ContentValues();
180867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        values.put(ACCOUNTS_NAME, account.name);
180967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        values.put(ACCOUNTS_TYPE, account.type);
181067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
181167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                new String[] {account.name, account.type});
181267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        long accountId = db.insert(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME, values);
181367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (accountId < 0) {
181467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            Log.w(TAG, "insertAccountIntoDatabase: " + account
181567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ", skipping the DB insert failed");
181667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return false;
181767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
181867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return true;
181967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
182067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
182167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
182267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public boolean removeSharedAccountAsUser(Account account, int userId) {
182367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
182467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        UserAccounts accounts = getUserAccounts(userId);
182567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
182667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        int r = db.delete(TABLE_SHARED_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
182767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                new String[] {account.name, account.type});
182867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        if (r > 0) {
182967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            removeAccountInternal(accounts, account);
183067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
183167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return r > 0;
183267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
183367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
183467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
183567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    public Account[] getSharedAccountsAsUser(int userId) {
183667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        userId = handleIncomingUser(userId);
183767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        UserAccounts accounts = getUserAccounts(userId);
183867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        ArrayList<Account> accountList = new ArrayList<Account>();
183967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Cursor cursor = null;
184067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
184167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            cursor = accounts.openHelper.getReadableDatabase()
184267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    .query(TABLE_SHARED_ACCOUNTS, new String[]{ACCOUNTS_NAME, ACCOUNTS_TYPE},
184367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    null, null, null, null, null);
184467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (cursor != null && cursor.moveToFirst()) {
184567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                int nameIndex = cursor.getColumnIndex(ACCOUNTS_NAME);
184667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                int typeIndex = cursor.getColumnIndex(ACCOUNTS_TYPE);
184767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                do {
184867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    accountList.add(new Account(cursor.getString(nameIndex),
184967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                            cursor.getString(typeIndex)));
185067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } while (cursor.moveToNext());
185167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
185267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } finally {
185367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (cursor != null) {
185467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                cursor.close();
185567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
185667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
185767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        Account[] accountArray = new Account[accountList.size()];
185867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        accountList.toArray(accountArray);
185967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return accountArray;
186067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
186167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
186267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    @Override
18632c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    public Account[] getAccounts(String type) {
18642c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani        return getAccountsAsUser(type, UserHandle.getCallingUserId());
18652c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani    }
18662c7bc26a7447e6ac9eadcf328259aa3bb1be2949Amith Yamasani
186727db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    @Override
186827db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    public Account[] getAccountsForPackage(String packageName, int uid) {
186927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        int callingUid = Binder.getCallingUid();
187027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (!UserHandle.isSameApp(callingUid, Process.myUid())) {
187127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
187227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    + callingUid + " with uid=" + uid);
187327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        }
187427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid);
187527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    }
187627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani
1877ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana    public void getAccountsByFeatures(IAccountManagerResponse response,
18783326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            String type, String[] features) {
187956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
188056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            Log.v(TAG, "getAccounts: accountType " + type
188156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", response " + response
188256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", features " + stringArrayToString(features)
188356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", caller's uid " + Binder.getCallingUid()
188456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + ", pid " + Binder.getCallingPid());
188556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
1886382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (response == null) throw new IllegalArgumentException("response is null");
1887382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (type == null) throw new IllegalArgumentException("accountType is null");
1888d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkReadAccountsPermission();
188904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts userAccounts = getUserAccountsForCaller();
1890df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        int callingUid = Binder.getCallingUid();
18913326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        long identityToken = clearCallingIdentity();
18923326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        try {
1893ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            if (features == null || features.length == 0) {
1894f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Account[] accounts;
189504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                synchronized (userAccounts.cacheLock) {
189627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    accounts = getAccountsFromCacheLocked(userAccounts, type, callingUid, null);
1897f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
1898d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                Bundle result = new Bundle();
1899d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                result.putParcelableArray(AccountManager.KEY_ACCOUNTS, accounts);
1900d4a9d6c42bb412e27a8383aaacd051419d98a662Fred Quintana                onResult(response, result);
1901ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                return;
1902ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana            }
1903df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            new GetAccountsByTypeAndFeatureSession(userAccounts, response, type, features,
1904df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    callingUid).bind();
19053326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        } finally {
19063326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            restoreCallingIdentity(identityToken);
19073326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        }
19083326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana    }
19093326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana
1910f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long getAccountIdLocked(SQLiteDatabase db, Account account) {
1911603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
1912ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
1913603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
1914603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (cursor.moveToNext()) {
1915603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return cursor.getLong(0);
1916603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1917603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            return -1;
1918603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
1919603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cursor.close();
1920603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1921603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1922603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1923f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    private long getExtrasIdLocked(SQLiteDatabase db, long accountId, String key) {
1924603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_ID},
1925603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
1926603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                new String[]{key}, null, null, null);
1927603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        try {
1928603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (cursor.moveToNext()) {
1929603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return cursor.getLong(0);
1930603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1931603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            return -1;
1932603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        } finally {
1933603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cursor.close();
1934603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1935603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
1936603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1937a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    private abstract class Session extends IAccountAuthenticatorResponse.Stub
1938b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            implements IBinder.DeathRecipient, ServiceConnection {
1939603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        IAccountManagerResponse mResponse;
1940603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        final String mAccountType;
1941a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        final boolean mExpectActivityLaunch;
1942a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        final long mCreationTime;
1943a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
19443326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana        public int mNumResults = 0;
1945a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private int mNumRequestContinued = 0;
1946a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private int mNumErrors = 0;
1947a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1948603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        IAccountAuthenticator mAuthenticator = null;
1949603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
19508570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana        private final boolean mStripAuthTokenFromResult;
195104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        protected final UserAccounts mAccounts;
19528570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana
195304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public Session(UserAccounts accounts, IAccountManagerResponse response, String accountType,
19548570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                boolean expectActivityLaunch, boolean stripAuthTokenFromResult) {
1955603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            super();
195667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            //if (response == null) throw new IllegalArgumentException("response is null");
19573326920329cecb57c7ff1fc5c6add5c98aab9ed9Fred Quintana            if (accountType == null) throw new IllegalArgumentException("accountType is null");
195804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            mAccounts = accounts;
19598570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana            mStripAuthTokenFromResult = stripAuthTokenFromResult;
1960603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mResponse = response;
1961603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mAccountType = accountType;
1962a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mExpectActivityLaunch = expectActivityLaunch;
1963a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mCreationTime = SystemClock.elapsedRealtime();
1964a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            synchronized (mSessions) {
1965a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mSessions.put(toString(), this);
1966a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
196767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (response != null) {
196867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                try {
196967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    response.asBinder().linkToDeath(this, 0 /* flags */);
197067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                } catch (RemoteException e) {
197167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    mResponse = null;
197267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    binderDied();
197367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                }
1974a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1975603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
1976603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
1977a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        IAccountManagerResponse getResponseAndClose() {
1978603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (mResponse == null) {
1979603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                // this session has already been closed
1980603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                return null;
1981603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
1982a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = mResponse;
1983a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            close(); // this clears mResponse so we need to save the response before this call
1984a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return response;
1985a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
1986a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1987a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        private void close() {
1988a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            synchronized (mSessions) {
1989a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (mSessions.remove(toString()) == null) {
1990a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    // the session was already closed, so bail out now
1991a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    return;
1992a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
1993a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
1994a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (mResponse != null) {
1995a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                // stop listening for response deaths
1996a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mResponse.asBinder().unlinkToDeath(this, 0 /* flags */);
1997a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
1998a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                // clear this so that we don't accidentally send any further results
1999a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                mResponse = null;
2000a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2001603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            cancelTimeout();
2002603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            unbind();
2003a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2004a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2005a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void binderDied() {
2006603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mResponse = null;
2007a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            close();
2008a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2009a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2010a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        protected String toDebugString() {
2011a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return toDebugString(SystemClock.elapsedRealtime());
2012a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
2013a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2014a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        protected String toDebugString(long now) {
2015a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            return "Session: expectLaunch " + mExpectActivityLaunch
2016a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", connected " + (mAuthenticator != null)
2017a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", stats (" + mNumResults + "/" + mNumRequestContinued
2018a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "/" + mNumErrors + ")"
2019a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + ", lifetime " + ((now - mCreationTime) / 1000.0);
2020603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2021603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2022603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        void bind() {
2023a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
2024a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                Log.v(TAG, "initiating bind to authenticator type " + mAccountType);
2025a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2026b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (!bindToAuthenticator(mAccountType)) {
2027a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                Log.d(TAG, "bind attempt failed for " + toDebugString());
2028f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION, "bind failure");
2029603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2030603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2031603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2032603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        private void unbind() {
2033603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (mAuthenticator != null) {
2034603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                mAuthenticator = null;
2035b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                mContext.unbindService(this);
2036603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2037603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2038603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2039603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void scheduleTimeout() {
2040603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mMessageHandler.sendMessageDelayed(
2041603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    mMessageHandler.obtainMessage(MESSAGE_TIMED_OUT, this), TIMEOUT_DELAY_MS);
2042603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2043603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2044603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void cancelTimeout() {
2045603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mMessageHandler.removeMessages(MESSAGE_TIMED_OUT, this);
2046603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2047603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2048b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public void onServiceConnected(ComponentName name, IBinder service) {
2049603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            mAuthenticator = IAccountAuthenticator.Stub.asInterface(service);
2050a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            try {
2051a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                run();
2052a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } catch (RemoteException e) {
2053f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2054a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        "remote exception");
2055a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2056603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2057603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2058b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public void onServiceDisconnected(ComponentName name) {
2059a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mAuthenticator = null;
2060a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2061603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2062166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                try {
2063166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2064166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                            "disconnected");
2065166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                } catch (RemoteException e) {
2066166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2067166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        Log.v(TAG, "Session.onServiceDisconnected: "
2068166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                                + "caught RemoteException while responding", e);
2069166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    }
2070166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                }
2071603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2072603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2073603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2074b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        public abstract void run() throws RemoteException;
2075b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2076603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onTimedOut() {
2077a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2078603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2079166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                try {
2080166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    response.onError(AccountManager.ERROR_CODE_REMOTE_EXCEPTION,
2081166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                            "timeout");
2082166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                } catch (RemoteException e) {
2083166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2084166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                        Log.v(TAG, "Session.onTimedOut: caught RemoteException while responding",
2085166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                                e);
2086166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                    }
2087166466d483cc3d57e7d3d465fd92ce62409c8455Fred Quintana                }
2088603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2089603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2090603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2091a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void onResult(Bundle result) {
2092a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumResults++;
2093f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana            if (result != null && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {
2094f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
2095f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
2096d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                if (!TextUtils.isEmpty(accountName) && !TextUtils.isEmpty(accountType)) {
2097d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    Account account = new Account(accountName, accountType);
209850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    cancelNotification(getSigninRequiredNotificationId(mAccounts, account),
209950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                            new UserHandle(mAccounts.userId));
2100d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                }
2101603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2102a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response;
2103a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (mExpectActivityLaunch && result != null
2104f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                    && result.containsKey(AccountManager.KEY_INTENT)) {
2105a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                response = mResponse;
2106a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } else {
2107a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                response = getResponseAndClose();
2108603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2109603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (response != null) {
2110603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                try {
2111a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (result == null) {
211256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
211356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            Log.v(TAG, getClass().getSimpleName()
211456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                    + " calling onError() on response " + response);
211556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
2116f7ae77cd67f1a3993b8e56c1af4720a7adf4e69dFred Quintana                        response.onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
2117a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                                "null bundle returned");
2118a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    } else {
21198570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                        if (mStripAuthTokenFromResult) {
21208570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                            result.remove(AccountManager.KEY_AUTHTOKEN);
21218570f7440780db5c9b410e033e843b0e80e2fd27Fred Quintana                        }
212256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
212356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            Log.v(TAG, getClass().getSimpleName()
212456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                                    + " calling onResult() on response " + response);
212556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        }
2126a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        response.onResult(result);
2127a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2128603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                } catch (RemoteException e) {
2129a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    // if the caller is dead then there is no one to care about remote exceptions
2130a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2131a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        Log.v(TAG, "failure while notifying response", e);
2132a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2133603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                }
2134603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2135603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2136603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2137a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        public void onRequestContinued() {
2138a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumRequestContinued++;
2139603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2140603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2141603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onError(int errorCode, String errorMessage) {
2142a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            mNumErrors++;
2143a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            IAccountManagerResponse response = getResponseAndClose();
2144a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (response != null) {
2145a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
214656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    Log.v(TAG, getClass().getSimpleName()
214756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                            + " calling onError() on response " + response);
2148a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2149a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                try {
2150a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    response.onError(errorCode, errorMessage);
2151a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                } catch (RemoteException e) {
2152a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
2153a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                        Log.v(TAG, "Session.onError: caught RemoteException while responding", e);
2154a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    }
2155a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2156a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            } else {
2157a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2158a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    Log.v(TAG, "Session.onError: already closed");
2159a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                }
2160603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2161603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2162b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2163b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        /**
2164b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         * find the component name for the authenticator and initiate a bind
2165b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         * if no authenticator or the bind fails then return false, otherwise return true
2166b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana         */
2167b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        private boolean bindToAuthenticator(String authenticatorType) {
21686ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            final AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
21696ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            authenticatorInfo = mAuthenticatorCache.getServiceInfo(
21706ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    AuthenticatorDescription.newKey(authenticatorType), mAccounts.userId);
2171b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (authenticatorInfo == null) {
2172b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2173b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                    Log.v(TAG, "there is no authenticator for " + authenticatorType
2174b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                            + ", bailing out");
2175b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                }
2176b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                return false;
2177b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
2178b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2179b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            Intent intent = new Intent();
2180b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            intent.setAction(AccountManager.ACTION_AUTHENTICATOR_INTENT);
2181b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            intent.setComponent(authenticatorInfo.componentName);
2182b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
2183b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName);
2184b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
218527b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani            if (!mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE,
218627b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                    new UserHandle(mAccounts.userId))) {
2187b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
2188b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                    Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed");
2189b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                }
2190b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana                return false;
2191b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            }
2192b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2193b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana
2194b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana            return true;
2195b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        }
2196603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2197603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2198603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    private class MessageHandler extends Handler {
2199603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        MessageHandler(Looper looper) {
2200603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            super(looper);
2201603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
22023348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache
2203603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void handleMessage(Message msg) {
2204603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            switch (msg.what) {
2205603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                case MESSAGE_TIMED_OUT:
2206603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    Session session = (Session)msg.obj;
2207603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    session.onTimedOut();
2208603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    break;
2209603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
22105be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                case MESSAGE_COPY_SHARED_ACCOUNT:
22115be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    copyAccountToUser((Account) msg.obj, msg.arg1, msg.arg2);
22125be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani                    break;
22135be347bc527ca3eebb448f85245957c810e6b142Amith Yamasani
2214603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                default:
2215603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    throw new IllegalStateException("unhandled message: " + msg.what);
2216603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            }
2217603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2218603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2219603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
222004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private static String getDatabaseName(int userId) {
222104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        File systemDir = Environment.getSystemSecureDirectory();
222261f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani        File databaseFile = new File(Environment.getUserSystemDirectory(userId), DATABASE_NAME);
222304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        if (userId == 0) {
2224a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // Migrate old file, if it exists, to the new location.
2225a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // Make sure the new file doesn't already exist. A dummy file could have been
2226a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // accidentally created in the old location, causing the new one to become corrupted
2227a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            // as well.
222804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            File oldFile = new File(systemDir, DATABASE_NAME);
2229a23bb38628ac1f5dc4ebe6847faedc424dd5fce1Amith Yamasani            if (oldFile.exists() && !databaseFile.exists()) {
2230c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                // Check for use directory; create if it doesn't exist, else renameTo will fail
223161f57379ca2c5b6290c8da7548fa17128f7ab24fAmith Yamasani                File userDir = Environment.getUserSystemDirectory(userId);
2232c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                if (!userDir.exists()) {
2233c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    if (!userDir.mkdirs()) {
2234c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                        throw new IllegalStateException("User dir cannot be created: " + userDir);
2235c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    }
2236c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                }
2237c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                if (!oldFile.renameTo(databaseFile)) {
2238c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                    throw new IllegalStateException("User dir cannot be migrated: " + databaseFile);
2239c6b0f99bb31405902b40a96f6491a9adcaaac169Marc Blank                }
224004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            }
2241a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor        }
224204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        return databaseFile.getPath();
2243a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor    }
2244a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor
224504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    static class DatabaseHelper extends SQLiteOpenHelper {
2246a8529f68671a8a118751cb6ad577f44eaf076b96Oscar Montemayor
224704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        public DatabaseHelper(Context context, int userId) {
224804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            super(context, AccountManagerService.getDatabaseName(userId), null, DATABASE_VERSION);
2249603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2250603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2251f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        /**
2252f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * This call needs to be made while the mCacheLock is held. The way to
2253f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * ensure this is to get the lock any time a method is called ont the DatabaseHelper
2254f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         * @param db The database.
2255f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana         */
2256603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2257603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onCreate(SQLiteDatabase db) {
2258603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_ACCOUNTS + " ( "
2259603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
2260603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_NAME + " TEXT NOT NULL, "
2261603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_TYPE + " TEXT NOT NULL, "
2262603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + ACCOUNTS_PASSWORD + " TEXT, "
2263603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
2264603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2265603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " (  "
2266603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,  "
2267603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_ACCOUNTS_ID + " INTEGER NOT NULL, "
2268603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_TYPE + " TEXT NOT NULL,  "
2269603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + AUTHTOKENS_AUTHTOKEN + " TEXT,  "
2270603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE (" + AUTHTOKENS_ACCOUNTS_ID + "," + AUTHTOKENS_TYPE + "))");
2271603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2272d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            createGrantsTable(db);
2273d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2274603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_EXTRAS + " ( "
2275603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
2276603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_ACCOUNTS_ID + " INTEGER, "
2277603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_KEY + " TEXT NOT NULL, "
2278603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + EXTRAS_VALUE + " TEXT, "
2279603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + "UNIQUE(" + EXTRAS_ACCOUNTS_ID + "," + EXTRAS_KEY + "))");
2280603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2281603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            db.execSQL("CREATE TABLE " + TABLE_META + " ( "
2282603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + META_KEY + " TEXT PRIMARY KEY NOT NULL, "
2283603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana                    + META_VALUE + " TEXT)");
2284a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
228567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            createSharedAccountsTable(db);
228667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2287d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            createAccountsDeletionTrigger(db);
2288d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2289d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
229067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        private void createSharedAccountsTable(SQLiteDatabase db) {
229167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            db.execSQL("CREATE TABLE " + TABLE_SHARED_ACCOUNTS + " ( "
229267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
229367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_NAME + " TEXT NOT NULL, "
229467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + ACCOUNTS_TYPE + " TEXT NOT NULL, "
229567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))");
229667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
229767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
2298d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        private void createAccountsDeletionTrigger(SQLiteDatabase db) {
2299a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            db.execSQL(""
2300a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " CREATE TRIGGER " + TABLE_ACCOUNTS + "Delete DELETE ON " + TABLE_ACCOUNTS
2301a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " BEGIN"
2302a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "   DELETE FROM " + TABLE_AUTHTOKENS
2303a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "     WHERE " + AUTHTOKENS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2304a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "   DELETE FROM " + TABLE_EXTRAS
2305a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + "     WHERE " + EXTRAS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2306d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "   DELETE FROM " + TABLE_GRANTS
2307d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "     WHERE " + GRANTS_ACCOUNTS_ID + "=OLD." + ACCOUNTS_ID + " ;"
2308a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                    + " END");
2309603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2310603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2311d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        private void createGrantsTable(SQLiteDatabase db) {
2312d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            db.execSQL("CREATE TABLE " + TABLE_GRANTS + " (  "
2313d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_ACCOUNTS_ID + " INTEGER NOT NULL, "
2314d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_AUTH_TOKEN_TYPE + " STRING NOT NULL,  "
2315d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + GRANTS_GRANTEE_UID + " INTEGER NOT NULL,  "
2316d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + "UNIQUE (" + GRANTS_ACCOUNTS_ID + "," + GRANTS_AUTH_TOKEN_TYPE
2317d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    +   "," + GRANTS_GRANTEE_UID + "))");
2318d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2319d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2320603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2321603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
2322a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            Log.e(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
2323603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2324a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            if (oldVersion == 1) {
2325d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                // no longer need to do anything since the work is done
2326d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                // when upgrading from version 2
2327d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                oldVersion++;
2328d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
2329d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2330d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (oldVersion == 2) {
2331d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                createGrantsTable(db);
2332d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                db.execSQL("DROP TRIGGER " + TABLE_ACCOUNTS + "Delete");
2333d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                createAccountsDeletionTrigger(db);
2334a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana                oldVersion++;
2335a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
23363348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache
23373348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache            if (oldVersion == 3) {
23383348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_TYPE +
23393348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                        " = 'com.google' WHERE " + ACCOUNTS_TYPE + " == 'com.google.GAIA'");
23403348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache                oldVersion++;
23413348f14b3d46b172a5b557f81aac526b7e8bf5fbCostin Manolache            }
234267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
234367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (oldVersion == 4) {
234467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                createSharedAccountsTable(db);
234567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                oldVersion++;
234667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
234767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
234867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            if (oldVersion != newVersion) {
234967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion);
235067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            }
2351603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2352603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2353603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        @Override
2354603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        public void onOpen(SQLiteDatabase db) {
2355603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "opened database " + DATABASE_NAME);
2356603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        }
2357603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2358603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana
2359603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    public IBinder onBind(Intent intent) {
2360603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana        return asBinder();
2361603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana    }
2362a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
23631cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    /**
23641cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * Searches array of arguments for the specified string
23651cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @param args array of argument strings
23661cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @param value value to search for
23671cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     * @return true if the value is contained in the array
23681cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks     */
23691cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    private static boolean scanArgs(String[] args, String value) {
23701cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        if (args != null) {
23711cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks            for (String arg : args) {
23721cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                if (value.equals(arg)) {
23731cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                    return true;
23741cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2375a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana            }
2376a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana        }
23771cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        return false;
23781cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    }
2379a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
23806eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey    @Override
23811cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
23823abd75ba3a981850cac43a401d0014a836559cb0Kenny Root        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
23833abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                != PackageManager.PERMISSION_GRANTED) {
23843abd75ba3a981850cac43a401d0014a836559cb0Kenny Root            fout.println("Permission Denial: can't dump AccountsManager from from pid="
23853abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
23863abd75ba3a981850cac43a401d0014a836559cb0Kenny Root                    + " without permission " + android.Manifest.permission.DUMP);
23873abd75ba3a981850cac43a401d0014a836559cb0Kenny Root            return;
23883abd75ba3a981850cac43a401d0014a836559cb0Kenny Root        }
238904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final boolean isCheckinRequest = scanArgs(args, "--checkin") || scanArgs(args, "-c");
23906eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final IndentingPrintWriter ipw = new IndentingPrintWriter(fout, "  ");
23916eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey
23926eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        final List<UserInfo> users = getUserManager().getUsers();
23936eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey        for (UserInfo user : users) {
23946eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.println("User " + user + ":");
23956eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.increaseIndent();
23966eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            dumpUser(getUserAccounts(user.id), fd, ipw, args, isCheckinRequest);
23976eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.println();
23986eb9620ff289105c3fc4a1be28a8eebb17d044e0Jeff Sharkey            ipw.decreaseIndent();
239904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        }
240004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    }
24011cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks
240204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void dumpUser(UserAccounts userAccounts, FileDescriptor fd, PrintWriter fout,
240304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String[] args, boolean isCheckinRequest) {
240404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (userAccounts.cacheLock) {
240504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = userAccounts.openHelper.getReadableDatabase();
2406a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2407f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (isCheckinRequest) {
2408f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // This is a checkin request. *Only* upload the account types and the count of each.
2409f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_TYPE_COUNT_PROJECTION,
2410f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        null, null, ACCOUNTS_TYPE, null, null);
2411f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                try {
2412f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    while (cursor.moveToNext()) {
2413f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        // print type,count
2414f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        fout.println(cursor.getString(0) + "," + cursor.getString(1));
2415f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
2416f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                } finally {
2417f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    if (cursor != null) {
2418f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        cursor.close();
2419f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
24201cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2421f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } else {
2422df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
242327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        Process.myUid(), null);
2424f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println("Accounts: " + accounts.length);
2425f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                for (Account account : accounts) {
2426f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    fout.println("  " + account);
24271cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
2428307da1a46b4c9b711bafe8fbaaa6b98e8868c18eFred Quintana
2429f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println();
2430f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                synchronized (mSessions) {
2431f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    final long now = SystemClock.elapsedRealtime();
2432f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    fout.println("Active Sessions: " + mSessions.size());
2433f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    for (Session session : mSessions.values()) {
2434f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        fout.println("  " + session.toDebugString(now));
2435f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    }
24361cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks                }
24371cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks
2438f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                fout.println();
24396ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
2440f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
24411cd7d0e591b61a1e5d0be4073e9b9f976279cc84Jason Parks        }
2442a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2443a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
244404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void doNotification(UserAccounts accounts, Account account, CharSequence message,
24454120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn            Intent intent, int userId) {
244626fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
244726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
244826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            if (Log.isLoggable(TAG, Log.VERBOSE)) {
244926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana                Log.v(TAG, "doNotification: " + message + " intent:" + intent);
245026fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            }
2451a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
2452d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (intent.getComponent() != null &&
2453d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    GrantCredentialsPermissionActivity.class.getName().equals(
2454d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                            intent.getComponent().getClassName())) {
24554120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                createNoCredentialsPermissionNotification(account, intent, userId);
2456d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            } else {
245704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
245833f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                intent.addCategory(String.valueOf(notificationId));
2459d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
2460d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                        0 /* when */);
246150cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                UserHandle user = new UserHandle(userId);
246233f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                final String notificationTitleFormat =
246333f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                        mContext.getText(R.string.notification_title).toString();
246433f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                n.setLatestEventInfo(mContext,
246533f889ae270f888f8fdc084f5f1f3d443532a46aFred Quintana                        String.format(notificationTitleFormat, account.name),
24664120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        message, PendingIntent.getActivityAsUser(
24674120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
246850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                        null, user));
246950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                installNotification(notificationId, n, user);
2470d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
247126fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
247226fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
247326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
2474a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2475a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana
247650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    protected void installNotification(final int notificationId, final Notification n,
247750cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            UserHandle user) {
247856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
247950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                .notifyAsUser(null, notificationId, n, user);
248056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
248156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
248250cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn    protected void cancelNotification(int id, UserHandle user) {
248326fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        long identityToken = clearCallingIdentity();
248426fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        try {
248526fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            ((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
248650cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                .cancelAsUser(null, id, user);
248726fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        } finally {
248826fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana            restoreCallingIdentity(identityToken);
248926fc5eba506bf29f7f5343e836484a43702c8deaFred Quintana        }
2490a698f4276968d078b1b9e2f3738c4f559a3307b2Fred Quintana    }
2491d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2492b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    /** Succeeds if any of the specified permissions are granted. */
2493b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    private void checkBinderPermission(String... permissions) {
2494d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        final int uid = Binder.getCallingUid();
2495b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2496b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        for (String perm : permissions) {
2497b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana            if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
2498b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                if (Log.isLoggable(TAG, Log.VERBOSE)) {
249956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    Log.v(TAG, "  caller uid " + uid + " has " + perm);
2500b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                }
2501b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                return;
2502b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana            }
2503d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2504b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2505b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions);
250656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Log.w(TAG, "  " + msg);
2507b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        throw new SecurityException(msg);
2508d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2509d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
251067df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    private int handleIncomingUser(int userId) {
251167df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        try {
251267df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            return ActivityManagerNative.getDefault().handleIncomingUser(
251367df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, true, "", null);
251467df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        } catch (RemoteException re) {
251567df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani            // Shouldn't happen, local.
251667df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        }
251767df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani        return userId;
251867df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani    }
251967df64b3a48a8157d08a98fa90135d0ac0ee621cAmith Yamasani
25206ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey    private boolean inSystemImage(int callingUid) {
25216ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int callingUserId = UserHandle.getUserId(callingUid);
25226ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
25236ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final PackageManager userPackageManager;
25246ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        try {
25256ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            userPackageManager = mContext.createPackageContextAsUser(
25266ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                    "android", 0, new UserHandle(callingUserId)).getPackageManager();
25276ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        } catch (NameNotFoundException e) {
25286ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey            return false;
25296ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        }
25306ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey
25316ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        String[] packages = userPackageManager.getPackagesForUid(callingUid);
25327be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        for (String name : packages) {
25337be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            try {
25346ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
253556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                if (packageInfo != null
253656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
25377be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                    return true;
25387be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                }
25397be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            } catch (PackageManager.NameNotFoundException e) {
25407be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana                return false;
25417be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana            }
25427be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        }
25437be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana        return false;
25447be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana    }
25457be5964e74978ebc7d5fd24562de5738d31cf009Fred Quintana
2546d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
2547b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        final boolean inSystemImage = inSystemImage(callerUid);
254831957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        final boolean fromAuthenticator = account != null
254931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana                && hasAuthenticatorUid(account.type, callerUid);
255031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        final boolean hasExplicitGrants = account != null
255104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                && hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
2552d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
2553d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
255456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                    + callerUid + ", " + account
2555d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + ": is authenticator? " + fromAuthenticator
2556d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana                    + ", has explicit permission? " + hasExplicitGrants);
2557d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2558b839afc33ea4a7b549b6dd703e5c48858ce877d0Fred Quintana        return fromAuthenticator || hasExplicitGrants || inSystemImage;
2559d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2560d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
25611a23191bbde11505d6e0c25c04a60b41cb27fd31Fred Quintana    private boolean hasAuthenticatorUid(String accountType, int callingUid) {
25626ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey        final int callingUserId = UserHandle.getUserId(callingUid);
2563d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
25646ab72d74b86e5f4ec3c3909366fd46c225a66bd7Jeff Sharkey                mAuthenticatorCache.getAllServices(callingUserId)) {
2565d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            if (serviceInfo.type.type.equals(accountType)) {
2566ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                return (serviceInfo.uid == callingUid) ||
256756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                        (mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
2568ffd0cb04f97e62d286d185c520580d81a9c328b1Fred Quintana                                == PackageManager.SIGNATURE_MATCH);
2569d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
2570d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2571d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        return false;
2572d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2573d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
257404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private boolean hasExplicitlyGrantedPermission(Account account, String authTokenType,
257504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            int callerUid) {
257627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callerUid == Process.SYSTEM_UID) {
2577d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            return true;
2578d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
257904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        UserAccounts accounts = getUserAccountsForCaller();
258004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
258104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
258204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String[] args = { String.valueOf(callerUid), authTokenType,
2583f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    account.name, account.type};
2584f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final boolean permissionGranted =
2585f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
2586f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (!permissionGranted && ActivityManager.isRunningInTestHarness()) {
2587f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // TODO: Skip this check when running automated tests. Replace this
2588f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                // with a more general solution.
2589f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Log.d(TAG, "no credentials permission for usage of " + account + ", "
259004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                        + authTokenType + " by uid " + callerUid
2591f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        + " but ignoring since device is in test harness.");
2592f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return true;
2593f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2594f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            return permissionGranted;
2595d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2596d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2597d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2598d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkCallingUidAgainstAuthenticator(Account account) {
2599d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        final int uid = Binder.getCallingUid();
260031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        if (account == null || !hasAuthenticatorUid(account.type, uid)) {
2601d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            String msg = "caller uid " + uid + " is different than the authenticator's uid";
2602d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.w(TAG, msg);
2603d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            throw new SecurityException(msg);
2604d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2605d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        if (Log.isLoggable(TAG, Log.VERBOSE)) {
2606d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid");
2607d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2608d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2609d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2610d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkAuthenticateAccountsPermission(Account account) {
2611d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.AUTHENTICATE_ACCOUNTS);
2612d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkCallingUidAgainstAuthenticator(account);
2613d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2614d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2615d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkReadAccountsPermission() {
2616d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
2617d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2618d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2619d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    private void checkManageAccountsPermission() {
2620d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS);
2621d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2622d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2623b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    private void checkManageAccountsOrUseCredentialsPermissions() {
2624b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana        checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS,
2625b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana                Manifest.permission.USE_CREDENTIALS);
2626b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana    }
2627b38eb14dbf58c8230f5b54c481b85587d9ef7c78Fred Quintana
2628e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani    private boolean canUserModifyAccounts(int callingUid) {
262927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callingUid != Process.myUid()) {
263027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            if (getUserManager().getUserRestrictions(
263127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    new UserHandle(UserHandle.getUserId(callingUid)))
263227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                    .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
2633e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani                return false;
2634e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani            }
2635e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        }
2636e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani        return true;
2637e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani    }
2638e4cf73437a18c1444055f88a1fcc0d146ec23ac5Amith Yamasani
2639d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
2640d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throws RemoteException {
2641d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        final int callingUid = getCallingUid();
2642d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
264327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani        if (callingUid != Process.SYSTEM_UID) {
2644d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            throw new SecurityException();
2645d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
2646d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2647d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        if (value) {
2648d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            grantAppPermission(account, authTokenType, uid);
2649d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        } else {
2650d9640ec712806508877868d08aafaa2d715ff441Fred Quintana            revokeAppPermission(account, authTokenType, uid);
2651d9640ec712806508877868d08aafaa2d715ff441Fred Quintana        }
2652d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    }
2653d9640ec712806508877868d08aafaa2d715ff441Fred Quintana
2654d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
2655d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Allow callers with the given uid permission to get credentials for account/authTokenType.
2656d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * <p>
2657d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Although this is public it can only be accessed via the AccountManagerService object
2658d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * which is in the system. This means we don't need to protect it with permissions.
2659d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
2660d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
2661d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    private void grantAppPermission(Account account, String authTokenType, int uid) {
2662382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null || authTokenType == null) {
2663382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana            Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
266431957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
266531957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
2666f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
266704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
266804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
2669f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
2670f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
2671f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
2672f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
2673f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    ContentValues values = new ContentValues();
2674f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_ACCOUNTS_ID, accountId);
2675f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_AUTH_TOKEN_TYPE, authTokenType);
2676f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    values.put(GRANTS_GRANTEE_UID, uid);
2677f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.insert(TABLE_GRANTS, GRANTS_ACCOUNTS_ID, values);
2678f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
2679f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
2680f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
2681f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
2682d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
268350cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
268450cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    new UserHandle(accounts.userId));
2685d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2686d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
2687d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana
2688d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    /**
2689d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Don't allow callers with the given uid permission to get credentials for
2690d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * account/authTokenType.
2691d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * <p>
2692d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * Although this is public it can only be accessed via the AccountManagerService object
2693d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * which is in the system. This means we don't need to protect it with permissions.
2694d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     * @hide
2695d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana     */
2696d9640ec712806508877868d08aafaa2d715ff441Fred Quintana    private void revokeAppPermission(Account account, String authTokenType, int uid) {
2697382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana        if (account == null || authTokenType == null) {
2698382601fc8babccee0d0b953ecd9bef745d126996Fred Quintana            Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
269931957f1badbb900bbfe211317e1ea992d650a72dFred Quintana            return;
270031957f1badbb900bbfe211317e1ea992d650a72dFred Quintana        }
2701f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn        UserAccounts accounts = getUserAccounts(UserHandle.getUserId(uid));
270204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
270304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
2704f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            db.beginTransaction();
2705f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            try {
2706f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                long accountId = getAccountIdLocked(db, account);
2707f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (accountId >= 0) {
2708f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.delete(TABLE_GRANTS,
2709f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            GRANTS_ACCOUNTS_ID + "=? AND " + GRANTS_AUTH_TOKEN_TYPE + "=? AND "
2710f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    + GRANTS_GRANTEE_UID + "=?",
2711f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                            new String[]{String.valueOf(accountId), authTokenType,
2712f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                                    String.valueOf(uid)});
2713f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    db.setTransactionSuccessful();
2714f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                }
2715f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } finally {
2716f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                db.endTransaction();
2717d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana            }
271850cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn            cancelNotification(getCredentialPermissionNotificationId(account, authTokenType, uid),
271950cdf7c3069eb2cf82acbad73c322b7a5f3af4b1Dianne Hackborn                    new UserHandle(accounts.userId));
2720d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana        }
2721d4a1d2e14297a3387fdb5761090961e714370492Fred Quintana    }
272256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
272356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    static final private String stringArrayToString(String[] value) {
272456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return value != null ? ("[" + TextUtils.join(",", value) + "]") : null;
272556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
272656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
272704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void removeAccountFromCacheLocked(UserAccounts accounts, Account account) {
272804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        final Account[] oldAccountsForType = accounts.accountCache.get(account.type);
2729f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (oldAccountsForType != null) {
2730f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            ArrayList<Account> newAccountsList = new ArrayList<Account>();
2731f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            for (Account curAccount : oldAccountsForType) {
2732f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                if (!curAccount.equals(account)) {
2733f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                    newAccountsList.add(curAccount);
273456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                }
273556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
2736f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (newAccountsList.isEmpty()) {
273704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.remove(account.type);
2738f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            } else {
2739f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                Account[] newAccountsForType = new Account[newAccountsList.size()];
2740f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                newAccountsForType = newAccountsList.toArray(newAccountsForType);
274104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.accountCache.put(account.type, newAccountsForType);
2742f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
274356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
274404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.userDataCache.remove(account);
274504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.authTokenCache.remove(account);
274656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
274756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
274856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    /**
274956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana     * This assumes that the caller has already checked that the account is not already present.
275056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana     */
275104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    private void insertAccountIntoCacheLocked(UserAccounts accounts, Account account) {
275204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        Account[] accountsForType = accounts.accountCache.get(account.type);
2753f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        int oldLength = (accountsForType != null) ? accountsForType.length : 0;
2754f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        Account[] newAccountsForType = new Account[oldLength + 1];
2755f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (accountsForType != null) {
2756f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            System.arraycopy(accountsForType, 0, newAccountsForType, 0, oldLength);
2757f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2758f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        newAccountsForType[oldLength] = account;
275904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        accounts.accountCache.put(account.type, newAccountsForType);
2760f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    }
2761f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana
2762df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    private Account[] filterSharedAccounts(UserAccounts userAccounts, Account[] unfiltered,
276327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            int callingUid, String callingPackage) {
2764df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        if (getUserManager() == null || userAccounts == null || userAccounts.userId < 0
276527db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                || callingUid == Process.myUid()) {
2766df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return unfiltered;
2767df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
2768df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) {
2769df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            String[] packages = mPackageManager.getPackagesForUid(callingUid);
27700ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            // If any of the packages is a white listed package, return the full set,
2771df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // otherwise return non-shared accounts only.
2772df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            // This might be a temporary way to specify a whitelist
2773df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            String whiteList = mContext.getResources().getString(
2774df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    com.android.internal.R.string.config_appsAuthorizedForSharedAccounts);
2775df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            for (String packageName : packages) {
2776df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                if (whiteList.contains(";" + packageName + ";")) {
2777df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    return unfiltered;
2778df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2779df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
2780df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            ArrayList<Account> allowed = new ArrayList<Account>();
2781df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId);
2782df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered;
27830ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            String requiredAccountType = "";
27840ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            try {
27850ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                for (String packageName : packages) {
27860ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
27870ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    if (pi != null && pi.restrictedAccountType != null) {
27880ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        requiredAccountType = pi.restrictedAccountType;
278927db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        // If it matches the package name of the original caller, use this choice.
279027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        if (callingPackage != null && packageName.equals(callingPackage)) {
279127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                            break;
279227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        }
2793df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    }
2794df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
27950ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            } catch (NameNotFoundException nnfe) {
27960ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            }
27970ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani            for (Account account : unfiltered) {
27980ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                if (account.type.equals(requiredAccountType)) {
2799df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                    allowed.add(account);
28000ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                } else {
28010ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    boolean found = false;
28020ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    for (Account shared : sharedAccounts) {
28030ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        if (shared.equals(account)) {
28040ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                            found = true;
28050ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                            break;
28060ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        }
28070ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    }
28080ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    if (!found) {
28090ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                        allowed.add(account);
28100ac1fc9d233b8671f371a71e2a6374b47ef069a9Amith Yamasani                    }
2811df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                }
2812df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            }
2813df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            Account[] filtered = new Account[allowed.size()];
2814df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            allowed.toArray(filtered);
2815df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return filtered;
2816df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        } else {
2817df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani            return unfiltered;
2818df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani        }
2819df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    }
2820df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani
282127db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani    /*
282227db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani     * packageName can be null. If not null, it should be used to filter out restricted accounts
282327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani     * that the package is not allowed to access.
282427db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani     */
2825df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani    protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
282627db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            int callingUid, String callingPackage) {
2827f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (accountType != null) {
282804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            final Account[] accounts = userAccounts.accountCache.get(accountType);
2829f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (accounts == null) {
2830f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return EMPTY_ACCOUNT_ARRAY;
283156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            } else {
2832df2e92a535e19c00edd37318d974dab992ccc2c1Amith Yamasani                return filterSharedAccounts(userAccounts, Arrays.copyOf(accounts, accounts.length),
283327db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani                        callingUid, callingPackage);
2834f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2835f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2836f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            int totalLength = 0;
283704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (Account[] accounts : userAccounts.accountCache.values()) {
2838f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                totalLength += accounts.length;
2839f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2840f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            if (totalLength == 0) {
2841f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                return EMPTY_ACCOUNT_ARRAY;
2842f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            }
2843f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            Account[] accounts = new Account[totalLength];
2844f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            totalLength = 0;
284504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            for (Account[] accountsOfType : userAccounts.accountCache.values()) {
2846f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                System.arraycopy(accountsOfType, 0, accounts, totalLength,
2847f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                        accountsOfType.length);
2848f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                totalLength += accountsOfType.length;
284956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
285027db46850b708070452c0ce49daf5f79503fbde6Amith Yamasani            return filterSharedAccounts(userAccounts, accounts, callingUid, callingPackage);
285156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
285256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
285356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
285404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void writeUserDataIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
285504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Account account, String key, String value) {
285604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
2857f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (userDataForAccount == null) {
2858f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
285904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            accounts.userDataCache.put(account, userDataForAccount);
2860f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2861f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (value == null) {
2862f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount.remove(key);
2863f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2864f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            userDataForAccount.put(key, value);
286556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
286656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
286756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
286804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
286904e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            Account account, String key, String value) {
287004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
2871f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (authTokensForAccount == null) {
2872f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
287304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            accounts.authTokenCache.put(account, authTokensForAccount);
2874f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        }
2875f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        if (value == null) {
2876f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount.remove(key);
2877f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana        } else {
2878f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            authTokensForAccount.put(key, value);
287956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
288056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
288156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
288204e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected String readAuthTokenInternal(UserAccounts accounts, Account account,
288304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            String authTokenType) {
288404e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
288504e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
288656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            if (authTokensForAccount == null) {
288756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                // need to populate the cache for this account
288804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
2889f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                authTokensForAccount = readAuthTokensForAccountFromDatabaseLocked(db, account);
289004e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.authTokenCache.put(account, authTokensForAccount);
289156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
289256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            return authTokensForAccount.get(authTokenType);
289356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
289456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
289556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
289604e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani    protected String readUserDataInternal(UserAccounts accounts, Account account, String key) {
289704e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani        synchronized (accounts.cacheLock) {
289804e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani            HashMap<String, String> userDataForAccount = accounts.userDataCache.get(account);
289956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            if (userDataForAccount == null) {
290056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                // need to populate the cache for this account
290104e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                final SQLiteDatabase db = accounts.openHelper.getReadableDatabase();
2902f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana                userDataForAccount = readUserDataForAccountFromDatabaseLocked(db, account);
290304e0d265e3385e9d1fbc35e43c4e8caffbbe3290Amith Yamasani                accounts.userDataCache.put(account, userDataForAccount);
290456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
290556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            return userDataForAccount.get(key);
290656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
290756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
290856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2909f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected HashMap<String, String> readUserDataForAccountFromDatabaseLocked(
2910f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final SQLiteDatabase db, Account account) {
291156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        HashMap<String, String> userDataForAccount = new HashMap<String, String>();
291256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Cursor cursor = db.query(TABLE_EXTRAS,
291356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                COLUMNS_EXTRAS_KEY_AND_VALUE,
291456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                SELECTION_USERDATA_BY_ACCOUNT,
291556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                new String[]{account.name, account.type},
291656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                null, null, null);
291756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        try {
291856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            while (cursor.moveToNext()) {
291956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String tmpkey = cursor.getString(0);
292056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String value = cursor.getString(1);
292156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                userDataForAccount.put(tmpkey, value);
292256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
292356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        } finally {
292456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            cursor.close();
292556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
292656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return userDataForAccount;
292756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
292856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana
2929f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana    protected HashMap<String, String> readAuthTokensForAccountFromDatabaseLocked(
2930f9f240e3ad5ff5eeaa32fbb2dd65ef7f3b06af32Fred Quintana            final SQLiteDatabase db, Account account) {
293156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        HashMap<String, String> authTokensForAccount = new HashMap<String, String>();
293256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        Cursor cursor = db.query(TABLE_AUTHTOKENS,
293356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN,
293456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                SELECTION_AUTHTOKENS_BY_ACCOUNT,
293556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                new String[]{account.name, account.type},
293656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                null, null, null);
293756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        try {
293856285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            while (cursor.moveToNext()) {
293956285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String type = cursor.getString(0);
294056285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                final String authToken = cursor.getString(1);
294156285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana                authTokensForAccount.put(type, authToken);
294256285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            }
294356285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        } finally {
294456285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana            cursor.close();
294556285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        }
294656285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana        return authTokensForAccount;
294756285a60e83138bb4b4f2d3bdec91b2f3ca11aa2Fred Quintana    }
2948603073430bbcb1bd29db7afb9b14e2732ad589fbFred Quintana}
2949