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:
@@ -30,6 +30,7 @@ import android.os.UserHandle;
|
|||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.util.AtomicFile;
|
import android.util.AtomicFile;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.IntArray;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
@@ -54,6 +55,7 @@ import java.io.InputStream;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
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
|
@VisibleForTesting
|
||||||
protected boolean inSystemImage(int callerUid) {
|
protected boolean inSystemImage(int callerUid) {
|
||||||
String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid);
|
String[] packages = mContext.getPackageManager().getPackagesForUid(callerUid);
|
||||||
@@ -379,10 +422,11 @@ public abstract class RegisteredServicesCache<V> {
|
|||||||
*/
|
*/
|
||||||
private void generateServicesMap(int[] changedUids, int userId) {
|
private void generateServicesMap(int[] changedUids, int userId) {
|
||||||
if (DEBUG) {
|
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);
|
final List<ResolveInfo> resolveInfos = queryIntentServices(userId);
|
||||||
for (ResolveInfo resolveInfo : resolveInfos) {
|
for (ResolveInfo resolveInfo : resolveInfos) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -934,6 +934,7 @@ public class AccountManagerService
|
|||||||
* Should only be called inside of a clearCallingIdentity block.
|
* Should only be called inside of a clearCallingIdentity block.
|
||||||
*/
|
*/
|
||||||
private AuthenticatorDescription[] getAuthenticatorTypesInternal(int userId) {
|
private AuthenticatorDescription[] getAuthenticatorTypesInternal(int userId) {
|
||||||
|
mAuthenticatorCache.updateServices(userId);
|
||||||
Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
|
Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
|
||||||
authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
|
authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
|
||||||
AuthenticatorDescription[] types =
|
AuthenticatorDescription[] types =
|
||||||
@@ -947,8 +948,6 @@ public class AccountManagerService
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isCrossUser(int callingUid, int userId) {
|
private boolean isCrossUser(int callingUid, int userId) {
|
||||||
return (userId != UserHandle.getCallingUserId()
|
return (userId != UserHandle.getCallingUserId()
|
||||||
&& callingUid != Process.myUid()
|
&& callingUid != Process.myUid()
|
||||||
|
|||||||
@@ -64,4 +64,10 @@ public interface IAccountAuthenticatorCache {
|
|||||||
Handler handler);
|
Handler handler);
|
||||||
|
|
||||||
void invalidateCache(int userId);
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -337,6 +337,10 @@ public class AccountManagerServiceTest extends AndroidTestCase {
|
|||||||
@Override
|
@Override
|
||||||
public void invalidateCache(int userId) {
|
public void invalidateCache(int userId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateServices(int userId) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static public class MyMockContext extends MockContext {
|
static public class MyMockContext extends MockContext {
|
||||||
|
|||||||
Reference in New Issue
Block a user