Fixing index-out-of-bounds in AppWidgetService. (Bug 6717459)
Change-Id: I9d676fbb2110f01eb1d36adc59437a6a5ec97cc2
diff --git a/services/java/com/android/server/AppWidgetServiceImpl.java b/services/java/com/android/server/AppWidgetServiceImpl.java
index 7bc6a88..8156856 100644
--- a/services/java/com/android/server/AppWidgetServiceImpl.java
+++ b/services/java/com/android/server/AppWidgetServiceImpl.java
@@ -208,11 +208,19 @@
synchronized (mAppWidgetIds) {
ensureStateLoadedLocked();
- int N = mInstalledProviders.size();
+ // Note: updateProvidersForPackageLocked() may remove providers, so we must copy the
+ // list of installed providers and skip providers that we don't need to update.
+ // Also note that remove the provider does not clear the Provider component data.
+ ArrayList<Provider> installedProviders =
+ new ArrayList<Provider>(mInstalledProviders);
+ HashSet<ComponentName> removedProviders = new HashSet<ComponentName>();
+ int N = installedProviders.size();
for (int i = N - 1; i >= 0; i--) {
- Provider p = mInstalledProviders.get(i);
- String pkgName = p.info.provider.getPackageName();
- updateProvidersForPackageLocked(pkgName);
+ Provider p = installedProviders.get(i);
+ ComponentName cn = p.info.provider;
+ if (!removedProviders.contains(cn)) {
+ updateProvidersForPackageLocked(cn.getPackageName(), removedProviders);
+ }
}
saveStateLocked();
}
@@ -255,7 +263,7 @@
|| (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false))) {
for (String pkgName : pkgList) {
// The package was just upgraded
- providersModified |= updateProvidersForPackageLocked(pkgName);
+ providersModified |= updateProvidersForPackageLocked(pkgName, null);
}
} else {
// The package was just added
@@ -1675,7 +1683,13 @@
return providersAdded;
}
- boolean updateProvidersForPackageLocked(String pkgName) {
+ /**
+ * Updates all providers with the specified package names, and records any providers that were
+ * pruned.
+ *
+ * @return whether any providers were updated
+ */
+ boolean updateProvidersForPackageLocked(String pkgName, Set<ComponentName> removedProviders) {
boolean providersUpdated = false;
HashSet<String> keep = new HashSet<String>();
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
@@ -1752,6 +1766,9 @@
Provider p = mInstalledProviders.get(i);
if (pkgName.equals(p.info.provider.getPackageName())
&& !keep.contains(p.info.provider.getClassName())) {
+ if (removedProviders != null) {
+ removedProviders.add(p.info.provider);
+ }
removeProviderLocked(i, p);
providersUpdated = true;
}