Move findPreferredActivity logic into Computer

Bug: 187080582

Move the query portion of findPreferredActivityNotLocked() into
Computer.

The code is moved unchanged into ComputerEngine except that four lint
errors are corrected.

Test: atest
 * CtsContentTestCases:IntentFilterTest
 * CtsDynamicMimeHostTestCases
 * CtsRoleTestCases
 * FrameworksServicesTests:UserSystemPackageInstallerTest
 * FrameworksServicesTests:PackageManagerSettingsTests
 * FrameworksServicesTests:PackageManagerServiceTest
 * FrameworksServicesTests:AppsFilterTest
 * FrameworksServicesTests:PackageInstallerSessionTest
 * FrameworksServicesTests:ScanTests
 * UserLifecycleTests#startUser
 * UserLifecycleTests#stopUser
 * UserLifecycleTests#switchUser
 * FrameworksServicesTests:WatcherTest
 * android.appsecurity.cts.EphemeralTest
 * android.appsecurity.cts.InstantAppUserTest
Change-Id: I6d21792f3208689694b917a79cbee8a75a131c8e
This commit is contained in:
Lee Shombert
2021-08-28 18:02:14 -07:00
parent 37dc193270
commit 881452bf99

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);
}
/**
@@ -4846,6 +4853,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 +5290,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 +5867,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();
}
}
}
@@ -10414,61 +10731,9 @@ public class PackageManagerService extends IPackageManager.Stub
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 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;
return mComputer.findPersistentPreferredActivityLP(intent,
resolvedType,
flags, query, debug, userId);
}
private static boolean isHomeIntent(Intent intent) {
@@ -10485,223 +10750,14 @@ public class PackageManagerService extends IPackageManager.Stub
ResolveInfo mPreferredResolveInfo;
}
// The body of findPreferredActivity.
private 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) {
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;
}
}
private 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);
return mComputer.findPreferredActivityInternal(
intent, resolvedType, flags,
query, always,
removeMatches, debug, userId, queryMayBeFiltered);
}
ResolveInfo findPreferredActivityNotLocked(Intent intent, String resolvedType, int flags,