Merge "Revert "Do not load xml metadata for unchanged packages in RegisteredServicesCache"" into qt-dev
am: 660c234e9a
Change-Id: I466b3e4a3631614064be6aed38f1e74fde48544a
This commit is contained in:
@@ -17,7 +17,6 @@
|
|||||||
package android.content.pm;
|
package android.content.pm;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.annotation.UnsupportedAppUsage;
|
import android.annotation.UnsupportedAppUsage;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -177,8 +176,7 @@ public abstract class RegisteredServicesCache<V> {
|
|||||||
mContext.registerReceiver(mUserRemovedReceiver, userFilter);
|
mContext.registerReceiver(mUserRemovedReceiver, userFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
private void handlePackageEvent(Intent intent, int userId) {
|
||||||
protected void handlePackageEvent(Intent intent, int userId) {
|
|
||||||
// Don't regenerate the services map when the package is removed or its
|
// Don't regenerate the services map when the package is removed or its
|
||||||
// ASEC container unmounted as a step in replacement. The subsequent
|
// ASEC container unmounted as a step in replacement. The subsequent
|
||||||
// _ADDED / _AVAILABLE call will regenerate the map in the final state.
|
// _ADDED / _AVAILABLE call will regenerate the map in the final state.
|
||||||
@@ -240,9 +238,6 @@ public abstract class RegisteredServicesCache<V> {
|
|||||||
|
|
||||||
public void invalidateCache(int userId) {
|
public void invalidateCache(int userId) {
|
||||||
synchronized (mServicesLock) {
|
synchronized (mServicesLock) {
|
||||||
if (DEBUG) {
|
|
||||||
Slog.d(TAG, "invalidating cache for " + userId + " " + mInterfaceName);
|
|
||||||
}
|
|
||||||
final UserServices<V> user = findOrCreateUserLocked(userId);
|
final UserServices<V> user = findOrCreateUserLocked(userId);
|
||||||
user.services = null;
|
user.services = null;
|
||||||
onServicesChangedLocked(userId);
|
onServicesChangedLocked(userId);
|
||||||
@@ -472,37 +467,16 @@ public abstract class RegisteredServicesCache<V> {
|
|||||||
* or null to assume that everything is affected.
|
* or null to assume that everything is affected.
|
||||||
* @param userId the user for whom to update the services map.
|
* @param userId the user for whom to update the services map.
|
||||||
*/
|
*/
|
||||||
private void generateServicesMap(@Nullable int[] changedUids, int userId) {
|
private void generateServicesMap(int[] changedUids, int userId) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = "
|
Slog.d(TAG, "generateServicesMap() for " + userId + ", changed UIDs = "
|
||||||
+ Arrays.toString(changedUids));
|
+ Arrays.toString(changedUids));
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mServicesLock) {
|
|
||||||
final UserServices<V> user = findOrCreateUserLocked(userId);
|
|
||||||
final boolean cacheInvalid = user.services == null;
|
|
||||||
if (cacheInvalid) {
|
|
||||||
user.services = Maps.newHashMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
final ArrayList<ServiceInfo<V>> serviceInfos = new ArrayList<>();
|
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 {
|
||||||
// when changedUids == null, we want to do a rescan of everything, this means
|
|
||||||
// it's the initial scan, and containsUid will trivially return true
|
|
||||||
// when changedUids != null, we got here because a package changed, but
|
|
||||||
// invalidateCache could have been called (thus user.services == null), and we
|
|
||||||
// should query from PackageManager again
|
|
||||||
if (!cacheInvalid
|
|
||||||
&& !containsUid(
|
|
||||||
changedUids, resolveInfo.serviceInfo.applicationInfo.uid)) {
|
|
||||||
if (DEBUG) {
|
|
||||||
Slog.d(TAG, "Skipping parseServiceInfo for " + resolveInfo);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ServiceInfo<V> info = parseServiceInfo(resolveInfo);
|
ServiceInfo<V> info = parseServiceInfo(resolveInfo);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
|
Log.w(TAG, "Unable to load service info " + resolveInfo.toString());
|
||||||
@@ -514,6 +488,13 @@ public abstract class RegisteredServicesCache<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized (mServicesLock) {
|
||||||
|
final UserServices<V> user = findOrCreateUserLocked(userId);
|
||||||
|
final boolean firstScan = user.services == null;
|
||||||
|
if (firstScan) {
|
||||||
|
user.services = Maps.newHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
StringBuilder changes = new StringBuilder();
|
StringBuilder changes = new StringBuilder();
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for (ServiceInfo<V> info : serviceInfos) {
|
for (ServiceInfo<V> info : serviceInfos) {
|
||||||
@@ -534,7 +515,7 @@ public abstract class RegisteredServicesCache<V> {
|
|||||||
changed = true;
|
changed = true;
|
||||||
user.services.put(info.type, info);
|
user.services.put(info.type, info);
|
||||||
user.persistentServices.put(info.type, info.uid);
|
user.persistentServices.put(info.type, info.uid);
|
||||||
if (!(user.mPersistentServicesFileDidNotExist && cacheInvalid)) {
|
if (!(user.mPersistentServicesFileDidNotExist && firstScan)) {
|
||||||
notifyListener(info.type, userId, false /* removed */);
|
notifyListener(info.type, userId, false /* removed */);
|
||||||
}
|
}
|
||||||
} else if (previousUid == info.uid) {
|
} else if (previousUid == info.uid) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package android.content.pm;
|
package android.content.pm;
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.FileUtils;
|
import android.os.FileUtils;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
@@ -190,36 +189,6 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
|
|||||||
assertEquals(0, cache.getPersistentServicesSize(u1));
|
assertEquals(0, cache.getPersistentServicesSize(u1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check that an optimization to skip a call to PackageManager handles an invalidated cache.
|
|
||||||
*
|
|
||||||
* We added an optimization in generateServicesMap to only query PackageManager for packages
|
|
||||||
* that have been changed, because if a package is unchanged, we have already cached the
|
|
||||||
* services info for it, so we can save a query to PackageManager (and save some memory).
|
|
||||||
* However, if invalidateCache was called, we cannot optimize, and must do a full query.
|
|
||||||
* The initial optimization was buggy because it failed to check for an invalidated cache, and
|
|
||||||
* only scanned the changed packages, given in the ACTION_PACKAGE_CHANGED intent (b/122912184).
|
|
||||||
*/
|
|
||||||
public void testParseServiceInfoOptimizationHandlesInvalidatedCache() {
|
|
||||||
TestServicesCache cache = new TestServicesCache();
|
|
||||||
cache.addServiceForQuerying(U0, r1, newServiceInfo(t1, UID1));
|
|
||||||
cache.addServiceForQuerying(U0, r2, newServiceInfo(t2, UID2));
|
|
||||||
assertEquals(2, cache.getAllServicesSize(U0));
|
|
||||||
|
|
||||||
// simulate the client of the cache invalidating it
|
|
||||||
cache.invalidateCache(U0);
|
|
||||||
|
|
||||||
// there should be 0 services (userServices.services == null ) at this point, but we don't
|
|
||||||
// call getAllServicesSize since that would force a full scan of packages,
|
|
||||||
// instead we trigger a package change in a package that is in the list of services
|
|
||||||
Intent intent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
|
|
||||||
intent.putExtra(Intent.EXTRA_UID, UID1);
|
|
||||||
cache.handlePackageEvent(intent, U0);
|
|
||||||
|
|
||||||
// check that the optimization does a full query and caches both services
|
|
||||||
assertEquals(2, cache.getAllServicesSize(U0));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo(
|
private static RegisteredServicesCache.ServiceInfo<TestServiceType> newServiceInfo(
|
||||||
TestServiceType type, int uid) {
|
TestServiceType type, int uid) {
|
||||||
final ComponentInfo info = new ComponentInfo();
|
final ComponentInfo info = new ComponentInfo();
|
||||||
@@ -297,11 +266,6 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
|
|||||||
map = new HashMap<>();
|
map = new HashMap<>();
|
||||||
mServices.put(userId, map);
|
mServices.put(userId, map);
|
||||||
}
|
}
|
||||||
// in actual cases, resolveInfo should always have a serviceInfo, since we specifically
|
|
||||||
// query for intent services
|
|
||||||
resolveInfo.serviceInfo = new android.content.pm.ServiceInfo();
|
|
||||||
resolveInfo.serviceInfo.applicationInfo =
|
|
||||||
new ApplicationInfo(serviceInfo.componentInfo.applicationInfo);
|
|
||||||
map.put(resolveInfo, serviceInfo);
|
map.put(resolveInfo, serviceInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,11 +304,6 @@ public class RegisteredServicesCacheTest extends AndroidTestCase {
|
|||||||
public void onUserRemoved(int userId) {
|
public void onUserRemoved(int userId) {
|
||||||
super.onUserRemoved(userId);
|
super.onUserRemoved(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handlePackageEvent(Intent intent, int userId) {
|
|
||||||
super.handlePackageEvent(intent, userId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TestSerializer implements XmlSerializerAndParser<TestServiceType> {
|
static class TestSerializer implements XmlSerializerAndParser<TestServiceType> {
|
||||||
|
|||||||
Reference in New Issue
Block a user