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
This commit is contained in:
Fyodor Kupolov
2016-08-24 11:27:49 -07:00
parent e9c519e049
commit 814464894c
4 changed files with 57 additions and 4 deletions

View File

@@ -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 {

View File

@@ -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()

View File

@@ -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);
}

View File

@@ -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 {