1818
1919import android .Manifest ;
2020import android .app .ActivityManager ;
21- import android .app .AppGlobals ;
21+ import android .app .ActivityManagerNative ;
2222import android .app .Notification ;
2323import android .app .NotificationManager ;
2424import android .app .PendingIntent ;
3232import android .content .pm .ApplicationInfo ;
3333import android .content .pm .PackageInfo ;
3434import android .content .pm .PackageManager ;
35+ import android .content .pm .PackageManager .NameNotFoundException ;
3536import android .content .pm .RegisteredServicesCache ;
3637import android .content .pm .RegisteredServicesCacheListener ;
37- import android .content .pm .UserInfo ;
38- import android .content .res .Resources ;
3938import android .database .Cursor ;
4039import android .database .DatabaseUtils ;
4140import android .database .sqlite .SQLiteDatabase ;
5958
6059import com .android .internal .R ;
6160import com .android .internal .util .IndentingPrintWriter ;
61+ import com .google .android .collect .Lists ;
62+ import com .google .android .collect .Sets ;
6263
6364import java .io .File ;
6465import java .io .FileDescriptor ;
6768import java .util .Arrays ;
6869import java .util .Collection ;
6970import java .util .HashMap ;
71+ import java .util .HashSet ;
7072import java .util .LinkedHashMap ;
71- import java .util .List ;
7273import java .util .Map ;
7374import java .util .concurrent .atomic .AtomicInteger ;
7475import java .util .concurrent .atomic .AtomicReference ;
@@ -243,8 +244,7 @@ public void onReceive(Context context, Intent intent) {
243244 }
244245
245246 public void systemReady () {
246- mAuthenticatorCache .generateServicesMap ();
247- initUser (0 );
247+ initUser (UserHandle .USER_OWNER );
248248 }
249249
250250 private UserManager getUserManager () {
@@ -300,6 +300,14 @@ private void purgeOldGrants(UserAccounts accounts) {
300300 }
301301
302302 private void validateAccountsAndPopulateCache (UserAccounts accounts ) {
303+ mAuthenticatorCache .invalidateCache (accounts .userId );
304+
305+ final HashSet <AuthenticatorDescription > knownAuth = Sets .newHashSet ();
306+ for (RegisteredServicesCache .ServiceInfo <AuthenticatorDescription > service :
307+ mAuthenticatorCache .getAllServices (accounts .userId )) {
308+ knownAuth .add (service .type );
309+ }
310+
303311 synchronized (accounts .cacheLock ) {
304312 final SQLiteDatabase db = accounts .openHelper .getWritableDatabase ();
305313 boolean accountDeleted = false ;
@@ -314,8 +322,8 @@ private void validateAccountsAndPopulateCache(UserAccounts accounts) {
314322 final long accountId = cursor .getLong (0 );
315323 final String accountType = cursor .getString (1 );
316324 final String accountName = cursor .getString (2 );
317- if ( mAuthenticatorCache . getServiceInfo (
318- AuthenticatorDescription .newKey (accountType )) == null ) {
325+
326+ if (! knownAuth . contains ( AuthenticatorDescription .newKey (accountType ))) {
319327 Log .d (TAG , "deleting account " + accountName + " because type "
320328 + accountType + " no longer has a registered authenticator" );
321329 db .delete (TABLE_ACCOUNTS , ACCOUNTS_ID + "=" + accountId , null );
@@ -390,20 +398,9 @@ private void onUserRemoved(Intent intent) {
390398 }
391399 }
392400
393- private List <UserInfo > getAllUsers () {
394- return getUserManager ().getUsers ();
395- }
396-
397- public void onServiceChanged (AuthenticatorDescription desc , boolean removed ) {
398- // Validate accounts for all users
399- List <UserInfo > users = getAllUsers ();
400- if (users == null ) {
401- validateAccountsAndPopulateCache (getUserAccountsForCaller ());
402- } else {
403- for (UserInfo user : users ) {
404- validateAccountsAndPopulateCache (getUserAccounts (user .id ));
405- }
406- }
401+ @ Override
402+ public void onServiceChanged (AuthenticatorDescription desc , int userId , boolean removed ) {
403+ validateAccountsAndPopulateCache (getUserAccounts (userId ));
407404 }
408405
409406 public String getPassword (Account account ) {
@@ -470,10 +467,11 @@ public AuthenticatorDescription[] getAuthenticatorTypes() {
470467 + "caller's uid " + Binder .getCallingUid ()
471468 + ", pid " + Binder .getCallingPid ());
472469 }
473- long identityToken = clearCallingIdentity ();
470+ final int userId = UserHandle .getCallingUserId ();
471+ final long identityToken = clearCallingIdentity ();
474472 try {
475473 Collection <AccountAuthenticatorCache .ServiceInfo <AuthenticatorDescription >>
476- authenticatorCollection = mAuthenticatorCache .getAllServices ();
474+ authenticatorCollection = mAuthenticatorCache .getAllServices (userId );
477475 AuthenticatorDescription [] types =
478476 new AuthenticatorDescription [authenticatorCollection .size ()];
479477 int i = 0 ;
@@ -1055,9 +1053,9 @@ public void getAuthToken(IAccountManagerResponse response, final Account account
10551053 if (authTokenType == null ) throw new IllegalArgumentException ("authTokenType is null" );
10561054 checkBinderPermission (Manifest .permission .USE_CREDENTIALS );
10571055 final UserAccounts accounts = getUserAccountsForCaller ();
1058- AccountAuthenticatorCache .ServiceInfo <AuthenticatorDescription > authenticatorInfo =
1059- mAuthenticatorCache .getServiceInfo (
1060- AuthenticatorDescription .newKey (account .type ));
1056+ final RegisteredServicesCache .ServiceInfo <AuthenticatorDescription > authenticatorInfo ;
1057+ authenticatorInfo = mAuthenticatorCache .getServiceInfo (
1058+ AuthenticatorDescription .newKey (account .type ), accounts . userId );
10611059 final boolean customTokens =
10621060 authenticatorInfo != null && authenticatorInfo .type .customTokens ;
10631061
@@ -1074,7 +1072,7 @@ public void getAuthToken(IAccountManagerResponse response, final Account account
10741072 if (notifyOnAuthFailure ) {
10751073 loginOptions .putBoolean (AccountManager .KEY_NOTIFY_ON_FAILURE , true );
10761074 }
1077-
1075+
10781076 long identityToken = clearCallingIdentity ();
10791077 try {
10801078 // if the caller has permission, do the peek. otherwise go the more expensive
@@ -1183,28 +1181,6 @@ private void createNoCredentialsPermissionNotification(Account account, Intent i
11831181 account , authTokenType , uid ), n , user );
11841182 }
11851183
1186- String getAccountLabel (String accountType ) {
1187- RegisteredServicesCache .ServiceInfo <AuthenticatorDescription > serviceInfo =
1188- mAuthenticatorCache .getServiceInfo (
1189- AuthenticatorDescription .newKey (accountType ));
1190- if (serviceInfo == null ) {
1191- throw new IllegalArgumentException ("unknown account type: " + accountType );
1192- }
1193-
1194- final Context authContext ;
1195- try {
1196- authContext = mContext .createPackageContext (
1197- serviceInfo .type .packageName , 0 );
1198- } catch (PackageManager .NameNotFoundException e ) {
1199- throw new IllegalArgumentException ("unknown account type: " + accountType );
1200- }
1201- try {
1202- return authContext .getString (serviceInfo .type .labelId );
1203- } catch (Resources .NotFoundException e ) {
1204- throw new IllegalArgumentException ("unknown account type: " + accountType );
1205- }
1206- }
1207-
12081184 private Intent newGrantCredentialsPermissionIntent (Account account , int uid ,
12091185 AccountAuthenticatorResponse response , String authTokenType , String authTokenLabel ) {
12101186
@@ -1506,28 +1482,35 @@ public Account[] getAccounts(int userId) {
15061482 }
15071483
15081484 /**
1509- * Returns all the accounts qualified by user.
1485+ * Returns accounts for all running users.
1486+ *
15101487 * @hide
15111488 */
1512- public AccountAndUser [] getAllAccounts () {
1513- ArrayList <AccountAndUser > allAccounts = new ArrayList <AccountAndUser >();
1514- List <UserInfo > users = getAllUsers ();
1515- if (users == null ) return new AccountAndUser [0 ];
1516-
1517- synchronized (mUsers ) {
1518- for (UserInfo user : users ) {
1519- UserAccounts userAccounts = getUserAccounts (user .id );
1489+ public AccountAndUser [] getRunningAccounts () {
1490+ final int [] runningUserIds ;
1491+ try {
1492+ runningUserIds = ActivityManagerNative .getDefault ().getRunningUserIds ();
1493+ } catch (RemoteException e ) {
1494+ // Running in system_server; should never happen
1495+ throw new RuntimeException (e );
1496+ }
1497+
1498+ final ArrayList <AccountAndUser > runningAccounts = Lists .newArrayList ();
1499+ synchronized (mUsers ) {
1500+ for (int userId : runningUserIds ) {
1501+ UserAccounts userAccounts = getUserAccounts (userId );
15201502 if (userAccounts == null ) continue ;
15211503 synchronized (userAccounts .cacheLock ) {
15221504 Account [] accounts = getAccountsFromCacheLocked (userAccounts , null );
15231505 for (int a = 0 ; a < accounts .length ; a ++) {
1524- allAccounts .add (new AccountAndUser (accounts [a ], user . id ));
1506+ runningAccounts .add (new AccountAndUser (accounts [a ], userId ));
15251507 }
15261508 }
15271509 }
15281510 }
1529- AccountAndUser [] accountsArray = new AccountAndUser [allAccounts .size ()];
1530- return allAccounts .toArray (accountsArray );
1511+
1512+ AccountAndUser [] accountsArray = new AccountAndUser [runningAccounts .size ()];
1513+ return runningAccounts .toArray (accountsArray );
15311514 }
15321515
15331516 public Account [] getAccounts (String type ) {
@@ -1836,9 +1819,9 @@ public void onError(int errorCode, String errorMessage) {
18361819 * if no authenticator or the bind fails then return false, otherwise return true
18371820 */
18381821 private boolean bindToAuthenticator (String authenticatorType ) {
1839- AccountAuthenticatorCache .ServiceInfo <AuthenticatorDescription > authenticatorInfo =
1840- mAuthenticatorCache .getServiceInfo (
1841- AuthenticatorDescription .newKey (authenticatorType ));
1822+ final AccountAuthenticatorCache .ServiceInfo <AuthenticatorDescription > authenticatorInfo ;
1823+ authenticatorInfo = mAuthenticatorCache .getServiceInfo (
1824+ AuthenticatorDescription .newKey (authenticatorType ), mAccounts . userId );
18421825 if (authenticatorInfo == null ) {
18431826 if (Log .isLoggable (TAG , Log .VERBOSE )) {
18441827 Log .v (TAG , "there is no authenticator for " + authenticatorType
@@ -2083,7 +2066,7 @@ private void dumpUser(UserAccounts userAccounts, FileDescriptor fd, PrintWriter
20832066 }
20842067
20852068 fout .println ();
2086- mAuthenticatorCache .dump (fd , fout , args );
2069+ mAuthenticatorCache .dump (fd , fout , args , userAccounts . userId );
20872070 }
20882071 }
20892072 }
@@ -2154,11 +2137,21 @@ private void checkBinderPermission(String... permissions) {
21542137 throw new SecurityException (msg );
21552138 }
21562139
2157- private boolean inSystemImage (int callerUid ) {
2158- String [] packages = mPackageManager .getPackagesForUid (callerUid );
2140+ private boolean inSystemImage (int callingUid ) {
2141+ final int callingUserId = UserHandle .getUserId (callingUid );
2142+
2143+ final PackageManager userPackageManager ;
2144+ try {
2145+ userPackageManager = mContext .createPackageContextAsUser (
2146+ "android" , 0 , new UserHandle (callingUserId )).getPackageManager ();
2147+ } catch (NameNotFoundException e ) {
2148+ return false ;
2149+ }
2150+
2151+ String [] packages = userPackageManager .getPackagesForUid (callingUid );
21592152 for (String name : packages ) {
21602153 try {
2161- PackageInfo packageInfo = mPackageManager .getPackageInfo (name , 0 /* flags */ );
2154+ PackageInfo packageInfo = userPackageManager .getPackageInfo (name , 0 /* flags */ );
21622155 if (packageInfo != null
21632156 && (packageInfo .applicationInfo .flags & ApplicationInfo .FLAG_SYSTEM ) != 0 ) {
21642157 return true ;
@@ -2186,8 +2179,9 @@ private boolean permissionIsGranted(Account account, String authTokenType, int c
21862179 }
21872180
21882181 private boolean hasAuthenticatorUid (String accountType , int callingUid ) {
2182+ final int callingUserId = UserHandle .getUserId (callingUid );
21892183 for (RegisteredServicesCache .ServiceInfo <AuthenticatorDescription > serviceInfo :
2190- mAuthenticatorCache .getAllServices ()) {
2184+ mAuthenticatorCache .getAllServices (callingUserId )) {
21912185 if (serviceInfo .type .type .equals (accountType )) {
21922186 return (serviceInfo .uid == callingUid ) ||
21932187 (mPackageManager .checkSignatures (serviceInfo .uid , callingUid )
0 commit comments