Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45ed828a authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

am c85e16ca: Merge "Make RegisteredServicesCache multi-user aware." into jb-mr1-dev

* commit 'c85e16ca':
  Make RegisteredServicesCache multi-user aware.
parents 27e2b6c2 c85e16ca
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -16,17 +16,18 @@


package android.accounts;
package android.accounts;


import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.XmlSerializerAndParser;
import android.content.pm.XmlSerializerAndParser;
import android.content.res.Resources;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.TypedArray;
import android.content.Context;
import android.util.AttributeSet;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.AttributeSet;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;


import java.io.IOException;
import java.io.IOException;


+64 −70
Original line number Original line Diff line number Diff line
@@ -18,7 +18,7 @@ package android.accounts;


import android.Manifest;
import android.Manifest;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.ActivityManagerNative;
import android.app.Notification;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.PendingIntent;
@@ -32,10 +32,9 @@ import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase;
@@ -59,6 +58,8 @@ import android.util.SparseArray;


import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;


import java.io.File;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileDescriptor;
@@ -67,8 +68,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReference;
@@ -243,8 +244,7 @@ public class AccountManagerService
    }
    }


    public void systemReady() {
    public void systemReady() {
        mAuthenticatorCache.generateServicesMap();
        initUser(UserHandle.USER_OWNER);
        initUser(0);
    }
    }


    private UserManager getUserManager() {
    private UserManager getUserManager() {
@@ -300,6 +300,14 @@ public class AccountManagerService
    }
    }


    private void validateAccountsAndPopulateCache(UserAccounts accounts) {
    private void validateAccountsAndPopulateCache(UserAccounts accounts) {
        mAuthenticatorCache.invalidateCache(accounts.userId);

        final HashSet<AuthenticatorDescription> knownAuth = Sets.newHashSet();
        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
                mAuthenticatorCache.getAllServices(accounts.userId)) {
            knownAuth.add(service.type);
        }

        synchronized (accounts.cacheLock) {
        synchronized (accounts.cacheLock) {
            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
            boolean accountDeleted = false;
            boolean accountDeleted = false;
@@ -314,8 +322,8 @@ public class AccountManagerService
                    final long accountId = cursor.getLong(0);
                    final long accountId = cursor.getLong(0);
                    final String accountType = cursor.getString(1);
                    final String accountType = cursor.getString(1);
                    final String accountName = cursor.getString(2);
                    final String accountName = cursor.getString(2);
                    if (mAuthenticatorCache.getServiceInfo(

                            AuthenticatorDescription.newKey(accountType)) == null) {
                    if (!knownAuth.contains(AuthenticatorDescription.newKey(accountType))) {
                        Log.d(TAG, "deleting account " + accountName + " because type "
                        Log.d(TAG, "deleting account " + accountName + " because type "
                                + accountType + " no longer has a registered authenticator");
                                + accountType + " no longer has a registered authenticator");
                        db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
                        db.delete(TABLE_ACCOUNTS, ACCOUNTS_ID + "=" + accountId, null);
@@ -390,20 +398,9 @@ public class AccountManagerService
        }
        }
    }
    }


    private List<UserInfo> getAllUsers() {
    @Override
        return getUserManager().getUsers();
    public void onServiceChanged(AuthenticatorDescription desc, int userId, boolean removed) {
    }
        validateAccountsAndPopulateCache(getUserAccounts(userId));

    public void onServiceChanged(AuthenticatorDescription desc, boolean removed) {
        // Validate accounts for all users
        List<UserInfo> users = getAllUsers();
        if (users == null) {
            validateAccountsAndPopulateCache(getUserAccountsForCaller());
        } else {
            for (UserInfo user : users) {
                validateAccountsAndPopulateCache(getUserAccounts(user.id));
            }
        }
    }
    }


    public String getPassword(Account account) {
    public String getPassword(Account account) {
@@ -470,10 +467,11 @@ public class AccountManagerService
                    + "caller's uid " + Binder.getCallingUid()
                    + "caller's uid " + Binder.getCallingUid()
                    + ", pid " + Binder.getCallingPid());
                    + ", pid " + Binder.getCallingPid());
        }
        }
        long identityToken = clearCallingIdentity();
        final int userId = UserHandle.getCallingUserId();
        final long identityToken = clearCallingIdentity();
        try {
        try {
            Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
            Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
                    authenticatorCollection = mAuthenticatorCache.getAllServices();
                    authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
            AuthenticatorDescription[] types =
            AuthenticatorDescription[] types =
                    new AuthenticatorDescription[authenticatorCollection.size()];
                    new AuthenticatorDescription[authenticatorCollection.size()];
            int i = 0;
            int i = 0;
@@ -1055,9 +1053,9 @@ public class AccountManagerService
        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
        if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
        final UserAccounts accounts = getUserAccountsForCaller();
        final UserAccounts accounts = getUserAccountsForCaller();
        AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
        final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
            mAuthenticatorCache.getServiceInfo(
        authenticatorInfo = mAuthenticatorCache.getServiceInfo(
                    AuthenticatorDescription.newKey(account.type));
                AuthenticatorDescription.newKey(account.type), accounts.userId);
        final boolean customTokens =
        final boolean customTokens =
            authenticatorInfo != null && authenticatorInfo.type.customTokens;
            authenticatorInfo != null && authenticatorInfo.type.customTokens;


@@ -1183,28 +1181,6 @@ public class AccountManagerService
                account, authTokenType, uid), n, user);
                account, authTokenType, uid), n, user);
    }
    }


    String getAccountLabel(String accountType) {
        RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo =
            mAuthenticatorCache.getServiceInfo(
                    AuthenticatorDescription.newKey(accountType));
        if (serviceInfo == null) {
            throw new IllegalArgumentException("unknown account type: " + accountType);
        }

        final Context authContext;
        try {
            authContext = mContext.createPackageContext(
                    serviceInfo.type.packageName, 0);
        } catch (PackageManager.NameNotFoundException e) {
            throw new IllegalArgumentException("unknown account type: " + accountType);
        }
        try {
            return authContext.getString(serviceInfo.type.labelId);
        } catch (Resources.NotFoundException e) {
            throw new IllegalArgumentException("unknown account type: " + accountType);
        }
    }

    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
    private Intent newGrantCredentialsPermissionIntent(Account account, int uid,
            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
            AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {


@@ -1506,28 +1482,35 @@ public class AccountManagerService
    }
    }


    /**
    /**
     * Returns all the accounts qualified by user.
     * Returns accounts for all running users.
     *
     * @hide
     * @hide
     */
     */
    public AccountAndUser[] getAllAccounts() {
    public AccountAndUser[] getRunningAccounts() {
        ArrayList<AccountAndUser> allAccounts = new ArrayList<AccountAndUser>();
        final int[] runningUserIds;
        List<UserInfo> users = getAllUsers();
        try {
        if (users == null)  return new AccountAndUser[0];
            runningUserIds = ActivityManagerNative.getDefault().getRunningUserIds();
        } catch (RemoteException e) {
            // Running in system_server; should never happen
            throw new RuntimeException(e);
        }


        final ArrayList<AccountAndUser> runningAccounts = Lists.newArrayList();
        synchronized (mUsers) {
        synchronized (mUsers) {
            for (UserInfo user : users) {
            for (int userId : runningUserIds) {
                UserAccounts userAccounts = getUserAccounts(user.id);
                UserAccounts userAccounts = getUserAccounts(userId);
                if (userAccounts == null) continue;
                if (userAccounts == null) continue;
                synchronized (userAccounts.cacheLock) {
                synchronized (userAccounts.cacheLock) {
                    Account[] accounts = getAccountsFromCacheLocked(userAccounts, null);
                    Account[] accounts = getAccountsFromCacheLocked(userAccounts, null);
                    for (int a = 0; a < accounts.length; a++) {
                    for (int a = 0; a < accounts.length; a++) {
                        allAccounts.add(new AccountAndUser(accounts[a], user.id));
                        runningAccounts.add(new AccountAndUser(accounts[a], userId));
                    }
                    }
                }
                }
            }
            }
        }
        }
        AccountAndUser[] accountsArray = new AccountAndUser[allAccounts.size()];

        return allAccounts.toArray(accountsArray);
        AccountAndUser[] accountsArray = new AccountAndUser[runningAccounts.size()];
        return runningAccounts.toArray(accountsArray);
    }
    }


    public Account[] getAccounts(String type) {
    public Account[] getAccounts(String type) {
@@ -1836,9 +1819,9 @@ public class AccountManagerService
         * if no authenticator or the bind fails then return false, otherwise return true
         * if no authenticator or the bind fails then return false, otherwise return true
         */
         */
        private boolean bindToAuthenticator(String authenticatorType) {
        private boolean bindToAuthenticator(String authenticatorType) {
            AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
            final AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
                    mAuthenticatorCache.getServiceInfo(
            authenticatorInfo = mAuthenticatorCache.getServiceInfo(
                            AuthenticatorDescription.newKey(authenticatorType));
                    AuthenticatorDescription.newKey(authenticatorType), mAccounts.userId);
            if (authenticatorInfo == null) {
            if (authenticatorInfo == null) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "there is no authenticator for " + authenticatorType
                    Log.v(TAG, "there is no authenticator for " + authenticatorType
@@ -2083,7 +2066,7 @@ public class AccountManagerService
                }
                }


                fout.println();
                fout.println();
                mAuthenticatorCache.dump(fd, fout, args);
                mAuthenticatorCache.dump(fd, fout, args, userAccounts.userId);
            }
            }
        }
        }
    }
    }
@@ -2154,11 +2137,21 @@ public class AccountManagerService
        throw new SecurityException(msg);
        throw new SecurityException(msg);
    }
    }


    private boolean inSystemImage(int callerUid) {
    private boolean inSystemImage(int callingUid) {
        String[] packages = mPackageManager.getPackagesForUid(callerUid);
        final int callingUserId = UserHandle.getUserId(callingUid);

        final PackageManager userPackageManager;
        try {
            userPackageManager = mContext.createPackageContextAsUser(
                    "android", 0, new UserHandle(callingUserId)).getPackageManager();
        } catch (NameNotFoundException e) {
            return false;
        }

        String[] packages = userPackageManager.getPackagesForUid(callingUid);
        for (String name : packages) {
        for (String name : packages) {
            try {
            try {
                PackageInfo packageInfo = mPackageManager.getPackageInfo(name, 0 /* flags */);
                PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
                if (packageInfo != null
                if (packageInfo != null
                        && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                        && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                    return true;
                    return true;
@@ -2186,8 +2179,9 @@ public class AccountManagerService
    }
    }


    private boolean hasAuthenticatorUid(String accountType, int callingUid) {
    private boolean hasAuthenticatorUid(String accountType, int callingUid) {
        final int callingUserId = UserHandle.getUserId(callingUid);
        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
                mAuthenticatorCache.getAllServices()) {
                mAuthenticatorCache.getAllServices(callingUserId)) {
            if (serviceInfo.type.type.equals(accountType)) {
            if (serviceInfo.type.type.equals(accountType)) {
                return (serviceInfo.uid == callingUid) ||
                return (serviceInfo.uid == callingUid) ||
                        (mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
                        (mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
+6 −8
Original line number Original line Diff line number Diff line
@@ -39,18 +39,19 @@ public interface IAccountAuthenticatorCache {
     * matches the account type or null if none is present
     * matches the account type or null if none is present
     */
     */
    RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> getServiceInfo(
    RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> getServiceInfo(
            AuthenticatorDescription type);
            AuthenticatorDescription type, int userId);


    /**
    /**
     * @return A copy of a Collection of all the current Authenticators.
     * @return A copy of a Collection of all the current Authenticators.
     */
     */
    Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> getAllServices();
    Collection<RegisteredServicesCache.ServiceInfo<AuthenticatorDescription>> getAllServices(
            int userId);


    /**
    /**
     * Dumps the state of the cache. See
     * Dumps the state of the cache. See
     * {@link android.os.Binder#dump(java.io.FileDescriptor, java.io.PrintWriter, String[])}
     * {@link android.os.Binder#dump(java.io.FileDescriptor, java.io.PrintWriter, String[])}
     */
     */
    void dump(FileDescriptor fd, PrintWriter fout, String[] args);
    void dump(FileDescriptor fd, PrintWriter fout, String[] args, int userId);


    /**
    /**
     * Sets a listener that will be notified whenever the authenticator set changes
     * Sets a listener that will be notified whenever the authenticator set changes
@@ -61,8 +62,5 @@ public interface IAccountAuthenticatorCache {
    void setListener(RegisteredServicesCacheListener<AuthenticatorDescription> listener,
    void setListener(RegisteredServicesCacheListener<AuthenticatorDescription> listener,
            Handler handler);
            Handler handler);


    /**
    void invalidateCache(int userId);
     * Refreshes the authenticator cache.
     */
    void generateServicesMap();
}
}
+3 −2
Original line number Original line Diff line number Diff line
@@ -345,10 +345,11 @@ public final class ContentService extends IContentService.Stub {
    public SyncAdapterType[] getSyncAdapterTypes() {
    public SyncAdapterType[] getSyncAdapterTypes() {
        // This makes it so that future permission checks will be in the context of this
        // This makes it so that future permission checks will be in the context of this
        // process rather than the caller's process. We will restore this before returning.
        // process rather than the caller's process. We will restore this before returning.
        long identityToken = clearCallingIdentity();
        final int userId = UserHandle.getCallingUserId();
        final long identityToken = clearCallingIdentity();
        try {
        try {
            SyncManager syncManager = getSyncManager();
            SyncManager syncManager = getSyncManager();
            return syncManager.getSyncAdapterTypes();
            return syncManager.getSyncAdapterTypes(userId);
        } finally {
        } finally {
            restoreCallingIdentity(identityToken);
            restoreCallingIdentity(identityToken);
        }
        }
+120 −123

File changed.

Preview size limit exceeded, changes collapsed.

Loading