Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ff5defa authored by Michal Karpinski's avatar Michal Karpinski
Browse files

Removing non-preferred activity from resolution set should

not disrupt the preferred resolution

We used to show disambiguation whenever the resolution set
was different in any way from the preferred activity's one.
Now we force disambiguation only when the new state isn't
a preference-inclusive subset of the prior state.

Test: manual, various scenarios with installing, uninstalling, reinstalling multiple launcher apps
Bug: 38387746
Bug: 31955881
Change-Id: I60d963127bc2eb75340b47f2b54e9554549a921b
parent a20bf80a
Loading
Loading
Loading
Loading
+36 −14
Original line number Diff line number Diff line
@@ -6964,10 +6964,31 @@ public class PackageManagerService extends IPackageManager.Stub
                            // 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 "
                                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 "
@@ -6981,6 +7002,7 @@ public class PackageManagerService extends IPackageManager.Stub
                                    changed = true;
                                    return null;
                                }
                            }
                            // Yay! Either the set matched or we're looking for the last chosen
                            if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: "
+49 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.util.Slog;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

public class PreferredComponent {
@@ -241,6 +242,54 @@ public class PreferredComponent {
        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)));