Merge "Removing non-preferred activity from resolution set should not disrupt the preferred resolution" into oc-mr1-dev
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2db162d..88d7cf8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -7007,22 +7007,44 @@
// Okay we found a previously set preferred or last chosen app.
// If the result set is different from when this
- // was created, we need to clear it and re-ask the
- // user their preference, if we're looking for an "always" type entry.
+ // was created, and is not a subset of the preferred set, we need to
+ // clear it and re-ask the user their preference, if we're looking for
+ // an "always" type entry.
if (always && !pa.mPref.sameSet(query)) {
- Slog.i(TAG, "Result set changed, dropping preferred activity for "
- + intent + " type " + resolvedType);
- if (DEBUG_PREFERRED) {
- Slog.v(TAG, "Removing preferred activity since set changed "
- + pa.mPref.mComponent);
+ if (pa.mPref.isSuperset(query)) {
+ // some components of the set are no longer present in
+ // the query, but the preferred activity can still be reused
+ if (DEBUG_PREFERRED) {
+ Slog.i(TAG, "Result set changed, but PreferredActivity is"
+ + " still valid as only non-preferred components"
+ + " were removed for " + intent + " type "
+ + resolvedType);
+ }
+ // remove obsolete components and re-add the up-to-date filter
+ PreferredActivity freshPa = new PreferredActivity(pa,
+ pa.mPref.mMatch,
+ pa.mPref.discardObsoleteComponents(query),
+ pa.mPref.mComponent,
+ pa.mPref.mAlways);
+ pir.removeFilter(pa);
+ pir.addFilter(freshPa);
+ changed = true;
+ } else {
+ Slog.i(TAG,
+ "Result set changed, dropping preferred activity for "
+ + intent + " type " + resolvedType);
+ if (DEBUG_PREFERRED) {
+ Slog.v(TAG, "Removing preferred activity since set changed "
+ + pa.mPref.mComponent);
+ }
+ pir.removeFilter(pa);
+ // Re-add the filter as a "last chosen" entry (!always)
+ PreferredActivity lastChosen = new PreferredActivity(
+ pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
+ pir.addFilter(lastChosen);
+ changed = true;
+ return null;
}
- pir.removeFilter(pa);
- // Re-add the filter as a "last chosen" entry (!always)
- PreferredActivity lastChosen = new PreferredActivity(
- pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
- pir.addFilter(lastChosen);
- changed = true;
- return null;
}
// Yay! Either the set matched or we're looking for the last chosen
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
index 8e2e0cd..0f4df97 100644
--- a/services/core/java/com/android/server/pm/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -30,6 +30,7 @@
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.List;
public class PreferredComponent {
@@ -241,6 +242,54 @@
return numMatch == NS;
}
+ public boolean isSuperset(List<ResolveInfo> query) {
+ if (mSetPackages == null) {
+ return query == null;
+ }
+ if (query == null) {
+ return true;
+ }
+ final int NQ = query.size();
+ final int NS = mSetPackages.length;
+ if (NS < NQ) {
+ return false;
+ }
+ for (int i=0; i<NQ; i++) {
+ ResolveInfo ri = query.get(i);
+ ActivityInfo ai = ri.activityInfo;
+ boolean foundMatch = false;
+ for (int j=0; j<NS; j++) {
+ if (mSetPackages[j].equals(ai.packageName) && mSetClasses[j].equals(ai.name)) {
+ foundMatch = true;
+ break;
+ }
+ }
+ if (!foundMatch) return false;
+ }
+ return true;
+ }
+
+ /** Returns components from mSetPackages that are present in query. */
+ public ComponentName[] discardObsoleteComponents(List<ResolveInfo> query) {
+ if (mSetPackages == null || query == null) {
+ return new ComponentName[0];
+ }
+ final int NQ = query.size();
+ final int NS = mSetPackages.length;
+ ArrayList<ComponentName> aliveComponents = new ArrayList<>();
+ for (int i = 0; i < NQ; i++) {
+ ResolveInfo ri = query.get(i);
+ ActivityInfo ai = ri.activityInfo;
+ for (int j = 0; j < NS; j++) {
+ if (mSetPackages[j].equals(ai.packageName) && mSetClasses[j].equals(ai.name)) {
+ aliveComponents.add(new ComponentName(mSetPackages[j], mSetClasses[j]));
+ break;
+ }
+ }
+ }
+ return aliveComponents.toArray(new ComponentName[aliveComponents.size()]);
+ }
+
public void dump(PrintWriter out, String prefix, Object ident) {
out.print(prefix); out.print(
Integer.toHexString(System.identityHashCode(ident)));