平台
Android 7.1 + RK3288
问题
为Activity添加组件优先级不生效, 如:
<activity android:name=".HomeLauncher"
android:enabled="false">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
</activity>
分析
android:priority=“1000” 提高优先级不行, 当把数值改成 < 0 是可以生效的.
尝试过许多方法得到的结果都是一样的, 从LOG中可看出, 都被重置为priority=0
D/PackageManager: chooseBestActivity:ResolveInfo{96d95e1 com.android.launcher3/.Launcher m=0x108000}, priority=0
D/PackageManager: chooseBestActivity:ResolveInfo{4598f06 com.test.launcher/.HomeLauncher m=0x108000}, priority=0
D/PackageManager: chooseBestActivity:ResolveInfo{4598f06 com.android.settings/.FallbackHome p=-1000 m=0x108000}, priority=-1000
原因以下代码的注释中已标注清楚:
|-- frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/**
* Adjusts the priority of the given intent filter according to policy.
* <p>
* <ul>
* <li>The priority for non privileged applications is capped to '0'</li>
* <li>The priority for protected actions on privileged applications is capped to '0'</li>
* <li>The priority for unbundled updates to privileged applications is capped to the
* priority defined on the system partition</li>
* </ul>
* <p>
* <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
* allowed to obtain any priority on any action.
*/
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 privilegedApp =
((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
if (!privilegedApp) {
// non-privileged applications can never define a priority >0
Slog.w(TAG, "Non-privileged 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
if (isProtectedAction(intent)) {
if (mDeferProtectedFilters) {
// We can't deal with these just yet. No component should ever obtain a
// >0 priority for a protected actions, with ONE exception -- the setup
// wizard. The setup wizard, however, cannot be known until we're able to
// query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
// until all intent filters have been processed. Chicken, meet egg.
// Let the filter temporarily have a high priority and rectify the
// priorities after all system packages have been scanned.
mProtectedFilters.add(intent);
if (DEBUG_FILTERS) {
Slog.i(TAG, "Protected action; save for later;"
+ " package: " + applicationInfo.packageName
+ " activity: " + intent.activity.className
+ " origPrio: " + intent.getPriority());
}
return;
} else {
if (DEBUG_FILTERS && mSetupWizardPackage == null) {
Slog.i(TAG, "No setup wizard;"
+ " All protected intents capped to priority 0");
}
if (intent.activity.info.packageName.equals(mSetupWizardPackage)) {
if (DEBUG_FILTERS) {
Slog.i(TAG, "Found setup wizard;"
+ " allow priority " + intent.getPriority() + ";"
+ " package: " + intent.activity.info.packageName
+ " activity: " + intent.activity.className
+ " priority: " + intent.getPriority());
}
// setup wizard gets whatever it wants
return;
}
Slog.w(TAG, "Protected action; cap priority to 0;"
+ " package: " + intent.activity.info.packageName
+ " activity: " + intent.activity.className
+ " origPrio: " + intent.getPriority());
intent.setPriority(0);
return;
}
}
// privileged apps on the system image get whatever priority they request
return;
}
// privileged 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
}
把应用内置到/system/priv-app后, 解决.
扩展
- 测试过的几种上不生效的情况
- 内置到/system/app 不生效
- 添加 android:sharedUserId=“android.uid.system” 不生效
- 手动安装方式不生效
- 目前仅测试过Launcher属性, 其它未测