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

Commit 81446489 authored by Fyodor Kupolov's avatar Fyodor Kupolov
Browse files

Update services info before returning authenticators

Added RegisteredServicesCache.updateServices method which allows callers
to request an update to services for which package has been updated.

Added a call to updateServices in getAuthenticatorTypesInternal

Test: Manually tested update flow on test authenticator with an artificial
      delay in broadcast handling
Bug: 30979262
Change-Id: I499b2ee0be53fed01201c56068d929b6d621a78e
parent e9c519e0
Loading
Loading
Loading
Loading
+46 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.AtomicFile;
import android.util.AttributeSet;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -54,6 +55,7 @@ import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -344,6 +346,47 @@ public abstract class RegisteredServicesCache<V> {
        }
    }

    public void updateServices(int userId) {
        if (DEBUG) {
            Slog.d(TAG, "updateServices u" + userId);
        }
        List<ServiceInfo<V>> allServices;
        synchronized (mServicesLock) {
            final UserServices<V> user = findOrCreateUserLocked(userId);
            // If services haven't been initialized yet - no updates required
            if (user.services == null) {
                return;
            }
            allServices = new ArrayList<>(user.services.values());
        }
        IntArray updatedUids = null;
        for (ServiceInfo<V> service : allServices) {
            int versionCode = service.componentInfo.applicationInfo.versionCode;
            String pkg = service.componentInfo.packageName;
            ApplicationInfo newAppInfo = null;
            try {
                newAppInfo = mContext.getPackageManager().getApplicationInfoAsUser(pkg, 0, userId);
            } catch (NameNotFoundException e) {
                // Package uninstalled - treat as null app info
            }
            // If package updated or removed
            if ((newAppInfo == null) || (newAppInfo.versionCode != versionCode)) {
                if (DEBUG) {
                    Slog.d(TAG, "Package " + pkg + " uid=" + service.uid
                            + " updated. New appInfo: " + newAppInfo);
                }
                if (updatedUids == null) {
                    updatedUids = new IntArray();
                }
                updatedUids.add(service.uid);
            }
        }
        if (updatedUids != null && updatedUids.size() > 0) {
            int[] updatedUidsArray = updatedUids.toArray();
            generateServicesMap(updatedUidsArray, userId);
        }
    }

    @VisibleForTesting
    protected boolean inSystemImage(int callerUid) {
        String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid);
@@ -379,10 +422,11 @@ public abstract class RegisteredServicesCache<V> {
     */
    private void generateServicesMap(int[] changedUids, int userId) {
        if (DEBUG) {
            Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = " + changedUids);
            Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = "
                    + Arrays.toString(changedUids));
        }

        final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<ServiceInfo<V>>();
        final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
        final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
        for (ResolveInfo resolveInfo : resolveInfos) {
            try {
+1 −2
Original line number Diff line number Diff line
@@ -934,6 +934,7 @@ public class AccountManagerService
     * Should only be called inside of a clearCallingIdentity block.
     */
    private AuthenticatorDescription[] getAuthenticatorTypesInternal(int userId) {
        mAuthenticatorCache.updateServices(userId);
        Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
                authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
        AuthenticatorDescription[] types =
@@ -947,8 +948,6 @@ public class AccountManagerService
        return types;
    }



    private boolean isCrossUser(int callingUid, int userId) {
        return (userId != UserHandle.getCallingUserId()
                && callingUid != Process.myUid()
+6 −0
Original line number Diff line number Diff line
@@ -64,4 +64,10 @@ public interface IAccountAuthenticatorCache {
            Handler handler);

    void invalidateCache(int userId);

    /**
     * Request to update services info for which package has been updated, but hasn't been
     * picked up by the cache.
     */
    void updateServices(int userId);
}
+4 −0
Original line number Diff line number Diff line
@@ -337,6 +337,10 @@ public class AccountManagerServiceTest extends AndroidTestCase {
        @Override
        public void invalidateCache(int userId) {
        }

        @Override
        public void updateServices(int userId) {
        }
    }

    static public class MyMockContext extends MockContext {