diff options
4 files changed, 57 insertions, 4 deletions
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java index 6162d1aeeceb..a1103838280c 100644 --- a/core/java/android/content/pm/RegisteredServicesCache.java +++ b/core/java/android/content/pm/RegisteredServicesCache.java @@ -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 { diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 9108acf9c40a..c9bbb7609f13 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -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() diff --git a/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java index bb09687720cc..2c7d921edbcb 100644 --- a/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java +++ b/services/core/java/com/android/server/accounts/IAccountAuthenticatorCache.java @@ -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); } diff --git a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java index ef9739da0094..404c14271b89 100644 --- a/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java @@ -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 { |