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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user