Merge changes I64ce898e,I6d21792f,Ib977ea97,I006eddb0 into sc-qpr1-dev

* changes:
  Update getHomeActivitiesAsUser()
  Move findPreferredActivity logic into Computer
  Normalize findPreferredActivityNotLocked()
  DO NOT MERGE Removed unused priority argument
This commit is contained in:
Lee Shombert
2021-08-31 21:32:22 +00:00
committed by Android (Google) Code Review

View File

@@ -2132,6 +2132,13 @@ public class PackageManagerService extends IPackageManager.Stub
boolean filterAppAccess(String packageName, int callingUid, int userId);
@LiveImplementation(override = LiveImplementation.MANDATORY)
void dump(int type, FileDescriptor fd, PrintWriter pw, DumpState dumpState);
@LiveImplementation(override = LiveImplementation.NOT_ALLOWED)
FindPreferredActivityBodyResult findPreferredActivityInternal(Intent intent,
String resolvedType, int flags, List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered);
@LiveImplementation(override = LiveImplementation.NOT_ALLOWED)
ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, boolean debug, int userId);
}
/**
@@ -2914,7 +2921,24 @@ public class PackageManagerService extends IPackageManager.Stub
}
allHomeCandidates.addAll(resolveInfos);
final String packageName = mDefaultAppProvider.getDefaultHome(userId);
String packageName = mDefaultAppProvider.getDefaultHome(userId);
if (packageName == null) {
// Role changes are not and cannot be atomic because its implementation lives inside
// a system app, so when the home role changes, there is a window when the previous
// role holder is removed and the new role holder is granted the preferred activity,
// but hasn't become the role holder yet. However, this case may be easily hit
// because the preferred activity change triggers a broadcast and receivers may try
// to get the default home activity there. So we need to fix it for this time
// window, and an easy workaround is to fallback to the current preferred activity.
final int appId = UserHandle.getAppId(Binder.getCallingUid());
final boolean filtered = appId >= Process.FIRST_APPLICATION_UID;
FindPreferredActivityBodyResult result = findPreferredActivityInternal(
intent, null, 0, resolveInfos, true, false, false, userId, filtered);
ResolveInfo preferredResolveInfo = result.mPreferredResolveInfo;
if (preferredResolveInfo != null && preferredResolveInfo.activityInfo != null) {
packageName = preferredResolveInfo.activityInfo.packageName;
}
}
if (packageName == null) {
return null;
}
@@ -4846,6 +4870,284 @@ public class PackageManagerService extends IPackageManager.Stub
}
} // switch
}
// The body of findPreferredActivity.
protected FindPreferredActivityBodyResult findPreferredActivityBody(
Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered,
int callingUid, boolean isDeviceProvisioned) {
FindPreferredActivityBodyResult result = new FindPreferredActivityBodyResult();
flags = updateFlagsForResolve(
flags, userId, callingUid, false /*includeInstantApps*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId,
resolvedType, flags));
intent = updateIntentForResolve(intent);
// Try to find a matching persistent preferred activity.
result.mPreferredResolveInfo = findPersistentPreferredActivityLP(intent,
resolvedType, flags, query, debug, userId);
// If a persistent preferred activity matched, use it.
if (result.mPreferredResolveInfo != null) {
return result;
}
PreferredIntentResolver pir = mSettings.getPreferredActivities(userId);
// Get the list of preferred activities that handle the intent
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
List<PreferredActivity> prefs = pir != null
? pir.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
userId)
: null;
if (prefs != null && prefs.size() > 0) {
// First figure out how good the original match set is.
// We will only allow preferred activities that came
// from the same match quality.
int match = 0;
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match...");
final int N = query.size();
for (int j = 0; j < N; j++) {
final ResolveInfo ri = query.get(j);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Match for " + ri.activityInfo
+ ": 0x" + Integer.toHexString(match));
}
if (ri.match > match) {
match = ri.match;
}
}
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Best match: 0x" + Integer.toHexString(match));
}
match &= IntentFilter.MATCH_CATEGORY_MASK;
final int M = prefs.size();
for (int i = 0; i < M; i++) {
final PreferredActivity pa = prefs.get(i);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Checking PreferredActivity ds="
+ (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>")
+ "\n component=" + pa.mPref.mComponent);
pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
}
if (pa.mPref.mMatch != match) {
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Skipping bad match "
+ Integer.toHexString(pa.mPref.mMatch));
}
continue;
}
// If it's not an "always" type preferred activity and that's what we're
// looking for, skip it.
if (always && !pa.mPref.mAlways) {
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry");
continue;
}
final ActivityInfo ai = getActivityInfo(
pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS
| MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
userId);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Found preferred activity:");
if (ai != null) {
ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
} else {
Slog.v(TAG, " null");
}
}
final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent)
&& !isDeviceProvisioned;
final boolean allowSetMutation = !excludeSetupWizardHomeActivity
&& !queryMayBeFiltered;
if (ai == null) {
// Do not remove launcher's preferred activity during SetupWizard
// due to it may not install yet
if (!allowSetMutation) {
continue;
}
// This previously registered preferred activity
// component is no longer known. Most likely an update
// to the app was installed and in the new version this
// component no longer exists. Clean it up by removing
// it from the preferred activities list, and skip it.
Slog.w(TAG, "Removing dangling preferred activity: "
+ pa.mPref.mComponent);
pir.removeFilter(pa);
result.mChanged = true;
continue;
}
for (int j = 0; j < N; j++) {
final ResolveInfo ri = query.get(j);
if (!ri.activityInfo.applicationInfo.packageName
.equals(ai.applicationInfo.packageName)) {
continue;
}
if (!ri.activityInfo.name.equals(ai.name)) {
continue;
}
if (removeMatches && allowSetMutation) {
pir.removeFilter(pa);
result.mChanged = true;
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Removing match " + pa.mPref.mComponent);
}
break;
}
// Okay we found a previously set preferred or last chosen app.
// If the result set is different from when this
// 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, excludeSetupWizardHomeActivity)) {
if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) {
if (allowSetMutation) {
// 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);
result.mChanged = true;
} else {
if (DEBUG_PREFERRED) {
Slog.i(TAG, "Do not remove preferred activity");
}
}
} else {
if (allowSetMutation) {
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);
result.mChanged = true;
}
result.mPreferredResolveInfo = null;
return result;
}
}
// Yay! Either the set matched or we're looking for the last chosen
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Returning preferred activity: "
+ ri.activityInfo.packageName + "/" + ri.activityInfo.name);
}
result.mPreferredResolveInfo = ri;
return result;
}
}
}
return result;
}
public final FindPreferredActivityBodyResult findPreferredActivityInternal(
Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
final int callingUid = Binder.getCallingUid();
// Do NOT hold the packages lock; this calls up into the settings provider which
// could cause a deadlock.
final boolean isDeviceProvisioned =
android.provider.Settings.Global.getInt(mContext.getContentResolver(),
android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
// Find the preferred activity - the lock is held inside the method.
return findPreferredActivityBody(
intent, resolvedType, flags, query, always, removeMatches, debug,
userId, queryMayBeFiltered, callingUid, isDeviceProvisioned);
}
public final ResolveInfo findPersistentPreferredActivityLP(Intent intent,
String resolvedType,
int flags, List<ResolveInfo> query, boolean debug, int userId) {
final int N = query.size();
PersistentPreferredIntentResolver ppir =
mSettings.getPersistentPreferredActivities(userId);
// Get the list of persistent preferred activities that handle the intent
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Looking for persistent preferred activities...");
}
List<PersistentPreferredActivity> pprefs = ppir != null
? ppir.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
userId)
: null;
if (pprefs != null && pprefs.size() > 0) {
final int M = pprefs.size();
for (int i = 0; i < M; i++) {
final PersistentPreferredActivity ppa = pprefs.get(i);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Checking PersistentPreferredActivity ds="
+ (ppa.countDataSchemes() > 0 ? ppa.getDataScheme(0) : "<none>")
+ "\n component=" + ppa.mComponent);
ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
}
final ActivityInfo ai = getActivityInfo(ppa.mComponent,
flags | MATCH_DISABLED_COMPONENTS, userId);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Found persistent preferred activity:");
if (ai != null) {
ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
} else {
Slog.v(TAG, " null");
}
}
if (ai == null) {
// This previously registered persistent preferred activity
// component is no longer known. Ignore it and do NOT remove it.
continue;
}
for (int j = 0; j < N; j++) {
final ResolveInfo ri = query.get(j);
if (!ri.activityInfo.applicationInfo.packageName
.equals(ai.applicationInfo.packageName)) {
continue;
}
if (!ri.activityInfo.name.equals(ai.name)) {
continue;
}
// Found a persistent preference that can handle the intent.
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Returning persistent preferred activity: "
+ ri.activityInfo.packageName + "/" + ri.activityInfo.name);
}
return ri;
}
}
}
return null;
}
}
/**
@@ -5005,6 +5307,16 @@ public class PackageManagerService extends IPackageManager.Stub
super.dump(type, fd, pw, dumpState);
}
}
public final FindPreferredActivityBodyResult findPreferredActivityBody(Intent intent,
String resolvedType, int flags, List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered,
int callingUid, boolean isDeviceProvisioned) {
synchronized (mLock) {
return super.findPreferredActivityBody(intent, resolvedType, flags, query, always,
removeMatches, debug, userId, queryMayBeFiltered, callingUid,
isDeviceProvisioned);
}
}
}
/**
@@ -5572,6 +5884,28 @@ public class PackageManagerService extends IPackageManager.Stub
current.release();
}
}
public final FindPreferredActivityBodyResult findPreferredActivityInternal(Intent intent,
String resolvedType, int flags, List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
ThreadComputer current = live();
try {
return current.mComputer.findPreferredActivityInternal(intent, resolvedType, flags,
query, always, removeMatches, debug, userId, queryMayBeFiltered);
} finally {
current.release();
}
}
public final ResolveInfo findPersistentPreferredActivityLP(Intent intent,
String resolvedType, int flags, List<ResolveInfo> query, boolean debug,
int userId) {
ThreadComputer current = live();
try {
return current.mComputer.findPersistentPreferredActivityLP(intent, resolvedType,
flags, query, debug, userId);
} finally {
current.release();
}
}
}
@@ -9068,7 +9402,7 @@ public class PackageManagerService extends IPackageManager.Stub
/**
* Update given intent when being used to request {@link ResolveInfo}.
*/
private Intent updateIntentForResolve(Intent intent) {
private static Intent updateIntentForResolve(Intent intent) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
}
@@ -10240,7 +10574,7 @@ public class PackageManagerService extends IPackageManager.Stub
userId);
// Find any earlier preferred or last chosen entries and nuke them
findPreferredActivityNotLocked(
intent, resolvedType, flags, query, 0, false, true, false, userId);
intent, resolvedType, flags, query, false, true, false, userId);
// Add the new activity as the last chosen for this filter
addPreferredActivity(filter, match, null, activity, false, userId,
"Setting last chosen", false);
@@ -10256,7 +10590,7 @@ public class PackageManagerService extends IPackageManager.Stub
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType, flags,
userId);
return findPreferredActivityNotLocked(
intent, resolvedType, flags, query, 0, false, false, false, userId);
intent, resolvedType, flags, query, false, false, false, userId);
}
private void requestInstantAppResolutionPhaseTwo(AuxiliaryResolveInfo responseObj,
@@ -10298,7 +10632,7 @@ public class PackageManagerService extends IPackageManager.Stub
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivityNotLocked(intent, resolvedType,
flags, query, r0.priority, true, false, debug, userId, queryMayBeFiltered);
flags, query, true, false, debug, userId, queryMayBeFiltered);
if (ri != null) {
return ri;
}
@@ -10411,287 +10745,72 @@ public class PackageManagerService extends IPackageManager.Stub
}
@GuardedBy("mLock")
private ResolveInfo findPersistentPreferredActivityLP(Intent intent, String resolvedType,
private ResolveInfo findPersistentPreferredActivityLP(Intent intent,
String resolvedType,
int flags, List<ResolveInfo> query, boolean debug, int userId) {
final int N = query.size();
PersistentPreferredIntentResolver ppir = mSettings.getPersistentPreferredActivities(userId);
// Get the list of persistent preferred activities that handle the intent
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for presistent preferred activities...");
List<PersistentPreferredActivity> pprefs = ppir != null
? ppir.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
userId)
: null;
if (pprefs != null && pprefs.size() > 0) {
final int M = pprefs.size();
for (int i=0; i<M; i++) {
final PersistentPreferredActivity ppa = pprefs.get(i);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Checking PersistentPreferredActivity ds="
+ (ppa.countDataSchemes() > 0 ? ppa.getDataScheme(0) : "<none>")
+ "\n component=" + ppa.mComponent);
ppa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
}
final ActivityInfo ai = getActivityInfo(ppa.mComponent,
flags | MATCH_DISABLED_COMPONENTS, userId);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Found persistent preferred activity:");
if (ai != null) {
ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
} else {
Slog.v(TAG, " null");
}
}
if (ai == null) {
// This previously registered persistent preferred activity
// component is no longer known. Ignore it and do NOT remove it.
continue;
}
for (int j=0; j<N; j++) {
final ResolveInfo ri = query.get(j);
if (!ri.activityInfo.applicationInfo.packageName
.equals(ai.applicationInfo.packageName)) {
continue;
}
if (!ri.activityInfo.name.equals(ai.name)) {
continue;
}
// Found a persistent preference that can handle the intent.
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Returning persistent preferred activity: " +
ri.activityInfo.packageName + "/" + ri.activityInfo.name);
}
return ri;
}
}
}
return null;
return mComputer.findPersistentPreferredActivityLP(intent,
resolvedType,
flags, query, debug, userId);
}
private boolean isHomeIntent(Intent intent) {
private static boolean isHomeIntent(Intent intent) {
return ACTION_MAIN.equals(intent.getAction())
&& intent.hasCategory(CATEGORY_HOME)
&& intent.hasCategory(CATEGORY_DEFAULT);
}
// findPreferredActivityBody returns two items: a "things changed" flag and a
// ResolveInfo, which is the preferred activity itself.
private static class FindPreferredActivityBodyResult {
boolean mChanged;
ResolveInfo mPreferredResolveInfo;
}
private FindPreferredActivityBodyResult findPreferredActivityInternal(
Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
return mComputer.findPreferredActivityInternal(
intent, resolvedType, flags,
query, always,
removeMatches, debug, userId, queryMayBeFiltered);
}
ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, int priority, boolean always,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId) {
return findPreferredActivityNotLocked(
intent, resolvedType, flags, query, priority, always, removeMatches, debug, userId,
intent, resolvedType, flags, query, always, removeMatches, debug, userId,
UserHandle.getAppId(Binder.getCallingUid()) >= Process.FIRST_APPLICATION_UID);
}
// TODO: handle preferred activities missing while user has amnesia
/** <b>must not hold {@link #mLock}</b> */
ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, int priority, boolean always,
List<ResolveInfo> query, boolean always,
boolean removeMatches, boolean debug, int userId, boolean queryMayBeFiltered) {
if (Thread.holdsLock(mLock)) {
Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName()
+ " is holding mLock", new Throwable());
}
if (!mUserManager.exists(userId)) return null;
final int callingUid = Binder.getCallingUid();
// Do NOT hold the packages lock; this calls up into the settings provider which
// could cause a deadlock.
final boolean isDeviceProvisioned =
android.provider.Settings.Global.getInt(mContext.getContentResolver(),
android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
flags = updateFlagsForResolve(
flags, userId, callingUid, false /*includeInstantApps*/,
isImplicitImageCaptureIntentAndNotSetByDpcLocked(intent, userId, resolvedType,
flags));
intent = updateIntentForResolve(intent);
// writer
synchronized (mLock) {
// Try to find a matching persistent preferred activity.
ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query,
debug, userId);
// If a persistent preferred activity matched, use it.
if (pri != null) {
return pri;
FindPreferredActivityBodyResult body = findPreferredActivityInternal(
intent, resolvedType, flags, query, always,
removeMatches, debug, userId, queryMayBeFiltered);
if (body.mChanged) {
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
}
PreferredIntentResolver pir = mSettings.getPreferredActivities(userId);
// Get the list of preferred activities that handle the intent
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
List<PreferredActivity> prefs = pir != null
? pir.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
userId)
: null;
if (prefs != null && prefs.size() > 0) {
boolean changed = false;
try {
// First figure out how good the original match set is.
// We will only allow preferred activities that came
// from the same match quality.
int match = 0;
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match...");
final int N = query.size();
for (int j=0; j<N; j++) {
final ResolveInfo ri = query.get(j);
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Match for " + ri.activityInfo
+ ": 0x" + Integer.toHexString(match));
if (ri.match > match) {
match = ri.match;
}
}
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Best match: 0x"
+ Integer.toHexString(match));
match &= IntentFilter.MATCH_CATEGORY_MASK;
final int M = prefs.size();
for (int i=0; i<M; i++) {
final PreferredActivity pa = prefs.get(i);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Checking PreferredActivity ds="
+ (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>")
+ "\n component=" + pa.mPref.mComponent);
pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
}
if (pa.mPref.mMatch != match) {
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping bad match "
+ Integer.toHexString(pa.mPref.mMatch));
continue;
}
// If it's not an "always" type preferred activity and that's what we're
// looking for, skip it.
if (always && !pa.mPref.mAlways) {
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry");
continue;
}
final ActivityInfo ai = getActivityInfo(
pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS
| MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
userId);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Found preferred activity:");
if (ai != null) {
ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
} else {
Slog.v(TAG, " null");
}
}
final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent)
&& !isDeviceProvisioned;
final boolean allowSetMutation = !excludeSetupWizardHomeActivity
&& !queryMayBeFiltered;
if (ai == null) {
// Do not remove launcher's preferred activity during SetupWizard
// due to it may not install yet
if (!allowSetMutation) {
continue;
}
// This previously registered preferred activity
// component is no longer known. Most likely an update
// to the app was installed and in the new version this
// component no longer exists. Clean it up by removing
// it from the preferred activities list, and skip it.
Slog.w(TAG, "Removing dangling preferred activity: "
+ pa.mPref.mComponent);
pir.removeFilter(pa);
changed = true;
continue;
}
for (int j=0; j<N; j++) {
final ResolveInfo ri = query.get(j);
if (!ri.activityInfo.applicationInfo.packageName
.equals(ai.applicationInfo.packageName)) {
continue;
}
if (!ri.activityInfo.name.equals(ai.name)) {
continue;
}
if (removeMatches && allowSetMutation) {
pir.removeFilter(pa);
changed = true;
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Removing match " + pa.mPref.mComponent);
}
break;
}
// Okay we found a previously set preferred or last chosen app.
// If the result set is different from when this
// 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, excludeSetupWizardHomeActivity)) {
if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) {
if (allowSetMutation) {
// 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 {
if (DEBUG_PREFERRED) {
Slog.i(TAG, "Do not remove preferred activity");
}
}
} else {
if (allowSetMutation) {
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;
}
}
// Yay! Either the set matched or we're looking for the last chosen
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: "
+ ri.activityInfo.packageName + "/" + ri.activityInfo.name);
return ri;
}
}
} finally {
if (changed) {
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
}
scheduleWritePackageRestrictionsLocked(userId);
}
}
synchronized (mLock) {
scheduleWritePackageRestrictionsLocked(userId);
}
}
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "No preferred activity to return");
return null;
if ((DEBUG_PREFERRED || debug) && body.mPreferredResolveInfo == null) {
Slog.v(TAG, "No preferred activity to return");
}
return body.mPreferredResolveInfo;
}
/*
@@ -23468,7 +23587,7 @@ public class PackageManagerService extends IPackageManager.Stub
final List<ResolveInfo> resolveInfos = queryIntentActivitiesInternal(intent, null,
MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE, userId);
final ResolveInfo preferredResolveInfo = findPreferredActivityNotLocked(
intent, null, 0, resolveInfos, 0, true, false, false, userId);
intent, null, 0, resolveInfos, true, false, false, userId);
final String packageName = preferredResolveInfo != null
&& preferredResolveInfo.activityInfo != null
? preferredResolveInfo.activityInfo.packageName : null;