DO NOT MERGE Fix intent filter priorities
am: eeb970a
* commit 'eeb970ada10d37495ad7a8a4b14ad0506b640eea':
DO NOT MERGE Fix intent filter priorities
Change-Id: I22cfcc61e9ec37242e0e47ef732c9364bdb8a886
This commit is contained in:
@@ -883,6 +883,15 @@ public class IntentFilter implements Parcelable {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof AuthorityEntry) {
|
||||
final AuthorityEntry other = (AuthorityEntry)obj;
|
||||
return match(other);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this AuthorityEntry matches the given data Uri.
|
||||
* <em>Note that this comparison is case-sensitive, unlike formal
|
||||
@@ -917,7 +926,7 @@ public class IntentFilter implements Parcelable {
|
||||
}
|
||||
return MATCH_CATEGORY_HOST;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Intent data "scheme specific part" to match against. The filter must
|
||||
|
||||
@@ -297,6 +297,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
private static final boolean DEBUG_PACKAGE_SCANNING = false;
|
||||
private static final boolean DEBUG_VERIFY = false;
|
||||
private static final boolean DEBUG_DEXOPT = false;
|
||||
private static final boolean DEBUG_FILTERS = false;
|
||||
private static final boolean DEBUG_ABI_SELECTION = false;
|
||||
|
||||
static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = false;
|
||||
@@ -8744,6 +8745,255 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a privileged activity that matches the specified activity names.
|
||||
*/
|
||||
private PackageParser.Activity findMatchingActivity(
|
||||
List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
|
||||
for (PackageParser.Activity sysActivity : activityList) {
|
||||
if (sysActivity.info.name.equals(activityInfo.name)) {
|
||||
return sysActivity;
|
||||
}
|
||||
if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
|
||||
return sysActivity;
|
||||
}
|
||||
if (sysActivity.info.targetActivity != null) {
|
||||
if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
|
||||
return sysActivity;
|
||||
}
|
||||
if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
|
||||
return sysActivity;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public class IterGenerator<E> {
|
||||
public Iterator<E> generate(ActivityIntentInfo info) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class ActionIterGenerator extends IterGenerator<String> {
|
||||
@Override
|
||||
public Iterator<String> generate(ActivityIntentInfo info) {
|
||||
return info.actionsIterator();
|
||||
}
|
||||
}
|
||||
|
||||
public class CategoriesIterGenerator extends IterGenerator<String> {
|
||||
@Override
|
||||
public Iterator<String> generate(ActivityIntentInfo info) {
|
||||
return info.categoriesIterator();
|
||||
}
|
||||
}
|
||||
|
||||
public class SchemesIterGenerator extends IterGenerator<String> {
|
||||
@Override
|
||||
public Iterator<String> generate(ActivityIntentInfo info) {
|
||||
return info.schemesIterator();
|
||||
}
|
||||
}
|
||||
|
||||
public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
|
||||
@Override
|
||||
public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
|
||||
return info.authoritiesIterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
|
||||
* MODIFIED. Do not pass in a list that should not be changed.
|
||||
*/
|
||||
private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
|
||||
IterGenerator<T> generator, Iterator<T> searchIterator) {
|
||||
// loop through the set of actions; every one must be found in the intent filter
|
||||
while (searchIterator.hasNext()) {
|
||||
// we must have at least one filter in the list to consider a match
|
||||
if (intentList.size() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
final T searchAction = searchIterator.next();
|
||||
|
||||
// loop through the set of intent filters
|
||||
final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
|
||||
while (intentIter.hasNext()) {
|
||||
final ActivityIntentInfo intentInfo = intentIter.next();
|
||||
boolean selectionFound = false;
|
||||
|
||||
// loop through the intent filter's selection criteria; at least one
|
||||
// of them must match the searched criteria
|
||||
final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
|
||||
while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
|
||||
final T intentSelection = intentSelectionIter.next();
|
||||
if (intentSelection != null && intentSelection.equals(searchAction)) {
|
||||
selectionFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the selection criteria wasn't found in this filter's set; this filter
|
||||
// is not a potential match
|
||||
if (!selectionFound) {
|
||||
intentIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts the priority of the given intent filter according to policy.
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>The priority for unbundled updates to system applications is capped to the
|
||||
* priority defined on the system partition</li>
|
||||
* </ul>
|
||||
*/
|
||||
private void adjustPriority(
|
||||
List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) {
|
||||
// nothing to do; priority is fine as-is
|
||||
if (intent.getPriority() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ActivityInfo activityInfo = intent.activity.info;
|
||||
final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
|
||||
|
||||
final boolean systemApp = applicationInfo.isSystemApp();
|
||||
if (!systemApp) {
|
||||
// non-system applications can never define a priority >0
|
||||
Slog.w(TAG, "Non-system app; cap priority to 0;"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
intent.setPriority(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (systemActivities == null) {
|
||||
// the system package is not disabled; we're parsing the system partition
|
||||
// apps on the system image get whatever priority they request
|
||||
return;
|
||||
}
|
||||
|
||||
// system app unbundled update ... try to find the same activity
|
||||
final PackageParser.Activity foundActivity =
|
||||
findMatchingActivity(systemActivities, activityInfo);
|
||||
if (foundActivity == null) {
|
||||
// this is a new activity; it cannot obtain >0 priority
|
||||
if (DEBUG_FILTERS) {
|
||||
Slog.i(TAG, "New activity; cap priority to 0;"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
}
|
||||
intent.setPriority(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// found activity, now check for filter equivalence
|
||||
|
||||
// a shallow copy is enough; we modify the list, not its contents
|
||||
final List<ActivityIntentInfo> intentListCopy =
|
||||
new ArrayList<>(foundActivity.intents);
|
||||
final List<ActivityIntentInfo> foundFilters = findFilters(intent);
|
||||
|
||||
// find matching action subsets
|
||||
final Iterator<String> actionsIterator = intent.actionsIterator();
|
||||
if (actionsIterator != null) {
|
||||
getIntentListSubset(
|
||||
intentListCopy, new ActionIterGenerator(), actionsIterator);
|
||||
if (intentListCopy.size() == 0) {
|
||||
// no more intents to match; we're not equivalent
|
||||
if (DEBUG_FILTERS) {
|
||||
Slog.i(TAG, "Mismatched action; cap priority to 0;"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
}
|
||||
intent.setPriority(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// find matching category subsets
|
||||
final Iterator<String> categoriesIterator = intent.categoriesIterator();
|
||||
if (categoriesIterator != null) {
|
||||
getIntentListSubset(intentListCopy, new CategoriesIterGenerator(),
|
||||
categoriesIterator);
|
||||
if (intentListCopy.size() == 0) {
|
||||
// no more intents to match; we're not equivalent
|
||||
if (DEBUG_FILTERS) {
|
||||
Slog.i(TAG, "Mismatched category; cap priority to 0;"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
}
|
||||
intent.setPriority(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// find matching schemes subsets
|
||||
final Iterator<String> schemesIterator = intent.schemesIterator();
|
||||
if (schemesIterator != null) {
|
||||
getIntentListSubset(intentListCopy, new SchemesIterGenerator(),
|
||||
schemesIterator);
|
||||
if (intentListCopy.size() == 0) {
|
||||
// no more intents to match; we're not equivalent
|
||||
if (DEBUG_FILTERS) {
|
||||
Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
}
|
||||
intent.setPriority(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// find matching authorities subsets
|
||||
final Iterator<IntentFilter.AuthorityEntry>
|
||||
authoritiesIterator = intent.authoritiesIterator();
|
||||
if (authoritiesIterator != null) {
|
||||
getIntentListSubset(intentListCopy,
|
||||
new AuthoritiesIterGenerator(),
|
||||
authoritiesIterator);
|
||||
if (intentListCopy.size() == 0) {
|
||||
// no more intents to match; we're not equivalent
|
||||
if (DEBUG_FILTERS) {
|
||||
Slog.i(TAG, "Mismatched authority; cap priority to 0;"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
}
|
||||
intent.setPriority(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we found matching filter(s); app gets the max priority of all intents
|
||||
int cappedPriority = 0;
|
||||
for (int i = intentListCopy.size() - 1; i >= 0; --i) {
|
||||
cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
|
||||
}
|
||||
if (intent.getPriority() > cappedPriority) {
|
||||
if (DEBUG_FILTERS) {
|
||||
Slog.i(TAG, "Found matching filter(s);"
|
||||
+ " cap priority to " + cappedPriority + ";"
|
||||
+ " package: " + applicationInfo.packageName
|
||||
+ " activity: " + intent.activity.className
|
||||
+ " origPrio: " + intent.getPriority());
|
||||
}
|
||||
intent.setPriority(cappedPriority);
|
||||
return;
|
||||
}
|
||||
// all this for nothing; the requested priority was <= what was on the system
|
||||
}
|
||||
|
||||
public final void addActivity(PackageParser.Activity a, String type) {
|
||||
final boolean systemApp = a.info.applicationInfo.isSystemApp();
|
||||
mActivities.put(a.getComponentName(), a);
|
||||
@@ -8756,10 +9006,12 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final int NI = a.intents.size();
|
||||
for (int j=0; j<NI; j++) {
|
||||
PackageParser.ActivityIntentInfo intent = a.intents.get(j);
|
||||
if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) {
|
||||
intent.setPriority(0);
|
||||
Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity "
|
||||
+ a.className + " with priority > 0, forcing to 0");
|
||||
if ("activity".equals(type)) {
|
||||
final PackageSetting ps =
|
||||
mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
|
||||
final List<PackageParser.Activity> systemActivities =
|
||||
ps != null && ps.pkg != null ? ps.pkg.activities : null;
|
||||
adjustPriority(systemActivities, intent);
|
||||
}
|
||||
if (DEBUG_SHOW_INFO) {
|
||||
Log.v(TAG, " IntentFilter:");
|
||||
@@ -8913,18 +9165,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
out.println();
|
||||
}
|
||||
|
||||
// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
|
||||
// final Iterator<ResolveInfo> i = resolveInfoList.iterator();
|
||||
// final List<ResolveInfo> retList = Lists.newArrayList();
|
||||
// while (i.hasNext()) {
|
||||
// final ResolveInfo resolveInfo = i.next();
|
||||
// if (isEnabledLP(resolveInfo.activityInfo)) {
|
||||
// retList.add(resolveInfo);
|
||||
// }
|
||||
// }
|
||||
// return retList;
|
||||
// }
|
||||
|
||||
// Keys are String (activity class name), values are Activity.
|
||||
private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
|
||||
= new ArrayMap<ComponentName, PackageParser.Activity>();
|
||||
@@ -10974,8 +11214,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
* Called after the source arguments are copied. This is used mostly for
|
||||
* MoveParams when it needs to read the source file to put it in the
|
||||
* destination.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int doPostCopy(int uid) {
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
|
||||
Reference in New Issue
Block a user