Merge "Scope package manager queries for ephemeral apps"
This commit is contained in:
committed by
Android (Google) Code Review
commit
72d633f430
@@ -1425,6 +1425,7 @@ package android {
|
||||
field public static final int viewportWidth = 16843778; // 0x1010402
|
||||
field public static final int visibility = 16842972; // 0x10100dc
|
||||
field public static final int visible = 16843156; // 0x1010194
|
||||
field public static final int visibleToEphemeral = 16844095; // 0x101053f
|
||||
field public static final int vmSafeMode = 16843448; // 0x10102b8
|
||||
field public static final int voiceIcon = 16843908; // 0x1010484
|
||||
field public static final int voiceLanguage = 16843349; // 0x1010255
|
||||
|
||||
@@ -1536,6 +1536,7 @@ package android {
|
||||
field public static final int viewportWidth = 16843778; // 0x1010402
|
||||
field public static final int visibility = 16842972; // 0x10100dc
|
||||
field public static final int visible = 16843156; // 0x1010194
|
||||
field public static final int visibleToEphemeral = 16844095; // 0x101053f
|
||||
field public static final int vmSafeMode = 16843448; // 0x10102b8
|
||||
field public static final int voiceIcon = 16843908; // 0x1010484
|
||||
field public static final int voiceLanguage = 16843349; // 0x1010255
|
||||
|
||||
@@ -1425,6 +1425,7 @@ package android {
|
||||
field public static final int viewportWidth = 16843778; // 0x1010402
|
||||
field public static final int visibility = 16842972; // 0x10100dc
|
||||
field public static final int visible = 16843156; // 0x1010194
|
||||
field public static final int visibleToEphemeral = 16844095; // 0x101053f
|
||||
field public static final int vmSafeMode = 16843448; // 0x10102b8
|
||||
field public static final int voiceIcon = 16843908; // 0x1010484
|
||||
field public static final int voiceLanguage = 16843349; // 0x1010255
|
||||
|
||||
@@ -282,6 +282,10 @@ public class IntentFilter implements Parcelable {
|
||||
|
||||
private int mVerifyState;
|
||||
|
||||
/** Whether or not the intent filter is visible to ephemeral apps. */
|
||||
private boolean mVisibleToEphemeral;
|
||||
/** Whether or not the intent filter is part of an ephemeral app. */
|
||||
private boolean mEphemeral;
|
||||
// These functions are the start of more optimized code for managing
|
||||
// the string sets... not yet implemented.
|
||||
|
||||
@@ -647,6 +651,24 @@ public class IntentFilter implements Parcelable {
|
||||
if (verified) mVerifyState |= STATE_VERIFIED;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setVisibleToEphemeral(boolean visibleToEmphemeral) {
|
||||
mVisibleToEphemeral = visibleToEmphemeral;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isVisibleToEphemeral() {
|
||||
return mVisibleToEphemeral;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setEphemeral(boolean ephemeral) {
|
||||
mEphemeral = ephemeral;
|
||||
}
|
||||
/** @hide */
|
||||
public boolean isEphemeral() {
|
||||
return mEphemeral;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Intent action to match against. If any actions are included
|
||||
* in the filter, then an Intent's action must be one of those values for
|
||||
|
||||
@@ -362,6 +362,12 @@ public class ActivityInfo extends ComponentInfo
|
||||
*/
|
||||
public static final int FLAG_ON_TOP_LAUNCHER = 0x80000;
|
||||
|
||||
/**
|
||||
* Bit in {@link #flags} indicating if the activity is visible to ephemeral applications.
|
||||
* @hide
|
||||
*/
|
||||
public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
|
||||
|
||||
/**
|
||||
* @hide Bit in {@link #flags}: If set, this component will only be seen
|
||||
* by the system user. Only works with broadcast receivers. Set from the
|
||||
|
||||
@@ -449,6 +449,20 @@ public abstract class PackageManager {
|
||||
*/
|
||||
public static final int MATCH_KNOWN_PACKAGES = MATCH_UNINSTALLED_PACKAGES | MATCH_ANY_USER;
|
||||
|
||||
/**
|
||||
* Internal {@link PackageInfo} flag: include components that are part of an
|
||||
* ephemeral app. By default, ephemeral components are not matched.
|
||||
* @hide
|
||||
*/
|
||||
public static final int MATCH_EPHEMERAL = 0x00800000;
|
||||
|
||||
/**
|
||||
* Internal {@link PackageInfo} flag: include only components that are exposed to
|
||||
* ephemeral apps.
|
||||
* @hide
|
||||
*/
|
||||
public static final int MATCH_VISIBLE_TO_EPHEMERAL_ONLY = 0x01000000;
|
||||
|
||||
/**
|
||||
* Internal flag used to indicate that a system component has done their
|
||||
* homework and verified that they correctly handle packages and components
|
||||
|
||||
@@ -3780,6 +3780,13 @@ public class PackageParser {
|
||||
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
|
||||
}
|
||||
|
||||
final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
|
||||
final boolean visibleToEphemeral = isEphemeral
|
||||
|| sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToEphemeral, false);
|
||||
if (visibleToEphemeral) {
|
||||
a.info.flags |= ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL;
|
||||
}
|
||||
|
||||
sa.recycle();
|
||||
|
||||
if (receiver && (owner.applicationInfo.privateFlags
|
||||
@@ -3806,9 +3813,12 @@ public class PackageParser {
|
||||
|
||||
if (parser.getName().equals("intent-filter")) {
|
||||
ActivityIntentInfo intent = new ActivityIntentInfo(a);
|
||||
if (!parseIntent(res, parser, true, true, intent, outError)) {
|
||||
if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
|
||||
intent, outError)) {
|
||||
return null;
|
||||
}
|
||||
intent.setEphemeral(isEphemeral);
|
||||
intent.setVisibleToEphemeral(visibleToEphemeral);
|
||||
if (intent.countActions() == 0) {
|
||||
Slog.w(TAG, "No actions in intent filter at "
|
||||
+ mArchiveSourcePath + " "
|
||||
@@ -3818,9 +3828,12 @@ public class PackageParser {
|
||||
}
|
||||
} else if (!receiver && parser.getName().equals("preferred")) {
|
||||
ActivityIntentInfo intent = new ActivityIntentInfo(a);
|
||||
if (!parseIntent(res, parser, false, false, intent, outError)) {
|
||||
if (!parseIntent(res, parser, false /*allowGlobs*/, false /*allowAutoVerify*/,
|
||||
intent, outError)) {
|
||||
return null;
|
||||
}
|
||||
intent.setEphemeral(isEphemeral);
|
||||
intent.setVisibleToEphemeral(visibleToEphemeral);
|
||||
if (intent.countActions() == 0) {
|
||||
Slog.w(TAG, "No actions in preferred at "
|
||||
+ mArchiveSourcePath + " "
|
||||
@@ -4071,6 +4084,10 @@ public class PackageParser {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
|
||||
final boolean visibleToEphemeral = isEphemeral
|
||||
|| ((a.info.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0);
|
||||
|
||||
sa.recycle();
|
||||
|
||||
if (outError[0] != null) {
|
||||
@@ -4088,7 +4105,8 @@ public class PackageParser {
|
||||
|
||||
if (parser.getName().equals("intent-filter")) {
|
||||
ActivityIntentInfo intent = new ActivityIntentInfo(a);
|
||||
if (!parseIntent(res, parser, true, true, intent, outError)) {
|
||||
if (!parseIntent(res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/,
|
||||
intent, outError)) {
|
||||
return null;
|
||||
}
|
||||
if (intent.countActions() == 0) {
|
||||
@@ -4096,6 +4114,8 @@ public class PackageParser {
|
||||
+ mArchiveSourcePath + " "
|
||||
+ parser.getPositionDescription());
|
||||
} else {
|
||||
intent.setEphemeral(isEphemeral);
|
||||
intent.setVisibleToEphemeral(visibleToEphemeral);
|
||||
a.intents.add(intent);
|
||||
}
|
||||
} else if (parser.getName().equals("meta-data")) {
|
||||
@@ -4233,6 +4253,13 @@ public class PackageParser {
|
||||
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
|
||||
}
|
||||
|
||||
final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
|
||||
final boolean visibleToEphemeral = isEphemeral
|
||||
|| sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToEphemeral, false);
|
||||
if (visibleToEphemeral) {
|
||||
p.info.flags |= ProviderInfo.FLAG_VISIBLE_TO_EPHEMERAL;
|
||||
}
|
||||
|
||||
sa.recycle();
|
||||
|
||||
if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
|
||||
@@ -4255,15 +4282,15 @@ public class PackageParser {
|
||||
}
|
||||
p.info.authority = cpname.intern();
|
||||
|
||||
if (!parseProviderTags(res, parser, p, outError)) {
|
||||
if (!parseProviderTags(res, parser, isEphemeral, visibleToEphemeral, p, outError)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private boolean parseProviderTags(Resources res,
|
||||
XmlResourceParser parser, Provider outInfo, String[] outError)
|
||||
private boolean parseProviderTags(Resources res, XmlResourceParser parser,
|
||||
boolean isEphemeral, boolean visibleToEphemeral, Provider outInfo, String[] outError)
|
||||
throws XmlPullParserException, IOException {
|
||||
int outerDepth = parser.getDepth();
|
||||
int type;
|
||||
@@ -4276,9 +4303,12 @@ public class PackageParser {
|
||||
|
||||
if (parser.getName().equals("intent-filter")) {
|
||||
ProviderIntentInfo intent = new ProviderIntentInfo(outInfo);
|
||||
if (!parseIntent(res, parser, true, false, intent, outError)) {
|
||||
if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
|
||||
intent, outError)) {
|
||||
return false;
|
||||
}
|
||||
intent.setEphemeral(isEphemeral);
|
||||
intent.setVisibleToEphemeral(visibleToEphemeral);
|
||||
outInfo.intents.add(intent);
|
||||
|
||||
} else if (parser.getName().equals("meta-data")) {
|
||||
@@ -4526,6 +4556,13 @@ public class PackageParser {
|
||||
ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
|
||||
}
|
||||
|
||||
final boolean isEphemeral = ((flags & PARSE_IS_EPHEMERAL) != 0);
|
||||
final boolean visibleToEphemeral = isEphemeral
|
||||
|| sa.getBoolean(R.styleable.AndroidManifestService_visibleToEphemeral, false);
|
||||
if (visibleToEphemeral) {
|
||||
s.info.flags |= ServiceInfo.FLAG_VISIBLE_TO_EPHEMERAL;
|
||||
}
|
||||
|
||||
sa.recycle();
|
||||
|
||||
if ((owner.applicationInfo.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
|
||||
@@ -4549,9 +4586,12 @@ public class PackageParser {
|
||||
|
||||
if (parser.getName().equals("intent-filter")) {
|
||||
ServiceIntentInfo intent = new ServiceIntentInfo(s);
|
||||
if (!parseIntent(res, parser, true, false, intent, outError)) {
|
||||
if (!parseIntent(res, parser, true /*allowGlobs*/, false /*allowAutoVerify*/,
|
||||
intent, outError)) {
|
||||
return null;
|
||||
}
|
||||
intent.setEphemeral(isEphemeral);
|
||||
intent.setVisibleToEphemeral(visibleToEphemeral);
|
||||
|
||||
s.intents.add(intent);
|
||||
} else if (parser.getName().equals("meta-data")) {
|
||||
@@ -4755,9 +4795,9 @@ public class PackageParser {
|
||||
private static final String ANDROID_RESOURCES
|
||||
= "http://schemas.android.com/apk/res/android";
|
||||
|
||||
private boolean parseIntent(Resources res, XmlResourceParser parser,
|
||||
boolean allowGlobs, boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
|
||||
throws XmlPullParserException, IOException {
|
||||
private boolean parseIntent(Resources res, XmlResourceParser parser, boolean allowGlobs,
|
||||
boolean allowAutoVerify, IntentInfo outInfo, String[] outError)
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
TypedArray sa = res.obtainAttributes(parser,
|
||||
com.android.internal.R.styleable.AndroidManifestIntentFilter);
|
||||
|
||||
@@ -75,6 +75,12 @@ public final class ProviderInfo extends ComponentInfo
|
||||
* running in the same process. Higher goes first. */
|
||||
public int initOrder = 0;
|
||||
|
||||
/**
|
||||
* Bit in {@link #flags} indicating if the provider is visible to ephemeral applications.
|
||||
* @hide
|
||||
*/
|
||||
public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
|
||||
|
||||
/**
|
||||
* Bit in {@link #flags}: If set, a single instance of the provider will
|
||||
* run for all users on the device. Set from the
|
||||
|
||||
@@ -55,6 +55,12 @@ public class ServiceInfo extends ComponentInfo
|
||||
*/
|
||||
public static final int FLAG_EXTERNAL_SERVICE = 0x0004;
|
||||
|
||||
/**
|
||||
* Bit in {@link #flags} indicating if the service is visible to ephemeral applications.
|
||||
* @hide
|
||||
*/
|
||||
public static final int FLAG_VISIBLE_TO_EPHEMERAL = 0x100000;
|
||||
|
||||
/**
|
||||
* Bit in {@link #flags}: If set, a single instance of the service will
|
||||
* run for all users on the device. Set from the
|
||||
|
||||
@@ -1209,6 +1209,10 @@
|
||||
-->
|
||||
<attr name="autoVerify" format="boolean" />
|
||||
|
||||
<!-- Specify whether a component should be visible to ephemeral apps.
|
||||
-->
|
||||
<attr name="visibleToEphemeral" format="boolean" />
|
||||
|
||||
<!-- An XML resource with the application's Network Security Config. -->
|
||||
<attr name="networkSecurityConfig" format="reference" />
|
||||
|
||||
@@ -1731,6 +1735,7 @@
|
||||
<attr name="exported" />
|
||||
<attr name="singleUser" />
|
||||
<attr name="directBootAware" />
|
||||
<attr name="visibleToEphemeral" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- Attributes that can be supplied in an AndroidManifest.xml
|
||||
@@ -1820,6 +1825,7 @@
|
||||
client to bind to the service as if it were running it its own package. The service
|
||||
must also be {@link android.R.attr#exported} if this flag is set. -->
|
||||
<attr name="externalService" format="boolean" />
|
||||
<attr name="visibleToEphemeral" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>receiver</code> tag declares an
|
||||
@@ -1940,7 +1946,8 @@
|
||||
<!-- @hide This activity is a launcher which should always show up on the top of others.
|
||||
This attribute is ignored if the activity isn't a launcher. -->
|
||||
<attr name="onTopLauncher" format="boolean" />
|
||||
<attr name="rotationAnimation"/>
|
||||
<attr name="rotationAnimation" />
|
||||
<attr name="visibleToEphemeral" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>activity-alias</code> tag declares a new
|
||||
|
||||
@@ -2775,6 +2775,7 @@
|
||||
<public name="layout_marginVertical" />
|
||||
<public name="paddingHorizontal" />
|
||||
<public name="paddingVertical" />
|
||||
<public name="visibleToEphemeral" />
|
||||
</public-group>
|
||||
|
||||
<public-group type="style" first-id="0x010302e0">
|
||||
|
||||
@@ -350,8 +350,8 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
|
||||
return Collections.unmodifiableSet(mFilters);
|
||||
}
|
||||
|
||||
public List<R> queryIntentFromList(Intent intent, String resolvedType,
|
||||
boolean defaultOnly, ArrayList<F[]> listCut, int userId) {
|
||||
public List<R> queryIntentFromList(Intent intent, String resolvedType, boolean defaultOnly,
|
||||
boolean visibleToEphemeral, boolean isEphemeral, ArrayList<F[]> listCut, int userId) {
|
||||
ArrayList<R> resultList = new ArrayList<R>();
|
||||
|
||||
final boolean debug = localLOGV ||
|
||||
@@ -361,8 +361,8 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
|
||||
final String scheme = intent.getScheme();
|
||||
int N = listCut.size();
|
||||
for (int i = 0; i < N; ++i) {
|
||||
buildResolveList(intent, categories, debug, defaultOnly,
|
||||
resolvedType, scheme, listCut.get(i), resultList, userId);
|
||||
buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, resolvedType, scheme, listCut.get(i), resultList, userId);
|
||||
}
|
||||
filterResults(resultList);
|
||||
sortResults(resultList);
|
||||
@@ -370,7 +370,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
|
||||
}
|
||||
|
||||
public List<R> queryIntent(Intent intent, String resolvedType, boolean defaultOnly,
|
||||
int userId) {
|
||||
boolean visibleToEphemeral, boolean isEphemeral, int userId) {
|
||||
String scheme = intent.getScheme();
|
||||
|
||||
ArrayList<R> finalList = new ArrayList<R>();
|
||||
@@ -443,20 +443,20 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
|
||||
|
||||
FastImmutableArraySet<String> categories = getFastIntentCategories(intent);
|
||||
if (firstTypeCut != null) {
|
||||
buildResolveList(intent, categories, debug, defaultOnly,
|
||||
resolvedType, scheme, firstTypeCut, finalList, userId);
|
||||
buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, resolvedType, scheme, firstTypeCut, finalList, userId);
|
||||
}
|
||||
if (secondTypeCut != null) {
|
||||
buildResolveList(intent, categories, debug, defaultOnly,
|
||||
resolvedType, scheme, secondTypeCut, finalList, userId);
|
||||
buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, resolvedType, scheme, secondTypeCut, finalList, userId);
|
||||
}
|
||||
if (thirdTypeCut != null) {
|
||||
buildResolveList(intent, categories, debug, defaultOnly,
|
||||
resolvedType, scheme, thirdTypeCut, finalList, userId);
|
||||
buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, resolvedType, scheme, thirdTypeCut, finalList, userId);
|
||||
}
|
||||
if (schemeCut != null) {
|
||||
buildResolveList(intent, categories, debug, defaultOnly,
|
||||
resolvedType, scheme, schemeCut, finalList, userId);
|
||||
buildResolveList(intent, categories, debug, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, resolvedType, scheme, schemeCut, finalList, userId);
|
||||
}
|
||||
filterResults(finalList);
|
||||
sortResults(finalList);
|
||||
@@ -694,7 +694,7 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
|
||||
}
|
||||
|
||||
private void buildResolveList(Intent intent, FastImmutableArraySet<String> categories,
|
||||
boolean debug, boolean defaultOnly,
|
||||
boolean debug, boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral,
|
||||
String resolvedType, String scheme, F[] src, List<R> dest, int userId) {
|
||||
final String action = intent.getAction();
|
||||
final Uri data = intent.getData();
|
||||
@@ -735,6 +735,15 @@ public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
|
||||
continue;
|
||||
}
|
||||
|
||||
// throw out filters that aren't visible to ephemeral apps
|
||||
if (visibleToEphemeral && !filter.isVisibleToEphemeral()) {
|
||||
continue;
|
||||
}
|
||||
// throw out ephemeral filters if we're not explicitly requesting them
|
||||
if (!isEphemeral && filter.isEphemeral()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Are we verified ?
|
||||
if (filter.getAutoVerify()) {
|
||||
if (localVerificationLOGV || debug) {
|
||||
|
||||
@@ -18374,7 +18374,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
List<BroadcastFilter> registeredReceiversForUser =
|
||||
mReceiverResolver.queryIntent(intent,
|
||||
resolvedType, false, users[i]);
|
||||
resolvedType, false, false /*visibleToEphemeral*/,
|
||||
false /*isEphemeral*/, users[i]);
|
||||
if (registeredReceivers == null) {
|
||||
registeredReceivers = registeredReceiversForUser;
|
||||
} else if (registeredReceiversForUser != null) {
|
||||
@@ -18383,7 +18384,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
} else {
|
||||
registeredReceivers = mReceiverResolver.queryIntent(intent,
|
||||
resolvedType, false, userId);
|
||||
resolvedType, false, false /*visibleToEphemeral*/,
|
||||
false /*isEphemeral*/, userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,7 +151,8 @@ public class IntentFirewall {
|
||||
// For the first pass, find all the rules that have at least one intent-filter or
|
||||
// component-filter that matches this intent
|
||||
List<Rule> candidateRules;
|
||||
candidateRules = resolver.queryIntent(intent, resolvedType, false, 0);
|
||||
candidateRules = resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/,
|
||||
false /*visibleToEphemeral*/, false /*isEphemeral*/, 0);
|
||||
if (candidateRules == null) {
|
||||
candidateRules = new ArrayList<Rule>();
|
||||
}
|
||||
|
||||
@@ -227,8 +227,9 @@ public abstract class EphemeralResolver {
|
||||
ephemeralResolver.addFilter(intentInfo);
|
||||
}
|
||||
}
|
||||
List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver
|
||||
.queryIntent(intent, resolvedType, false /*defaultOnly*/, userId);
|
||||
List<EphemeralResponse> matchedResolveInfoList = ephemeralResolver.queryIntent(
|
||||
intent, resolvedType, false /*defaultOnly*/, false /*visibleToEphemeral*/,
|
||||
false /*isEphemeral*/, userId);
|
||||
if (!matchedResolveInfoList.isEmpty()) {
|
||||
return matchedResolveInfoList.get(0);
|
||||
}
|
||||
|
||||
@@ -3641,6 +3641,11 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if (mSafeMode) {
|
||||
flags |= PackageManager.MATCH_SYSTEM_ONLY;
|
||||
}
|
||||
final String ephemeralPkgName = getEphemeralPackageName(Binder.getCallingUid());
|
||||
if (ephemeralPkgName != null) {
|
||||
flags |= PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY;
|
||||
flags |= PackageManager.MATCH_EPHEMERAL;
|
||||
}
|
||||
|
||||
return updateFlagsForComponent(flags, userId, cookie);
|
||||
}
|
||||
@@ -5214,7 +5219,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
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)
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_EPHEMERAL) != 0, userId)
|
||||
: null;
|
||||
if (pprefs != null && pprefs.size() > 0) {
|
||||
final int M = pprefs.size();
|
||||
@@ -5289,7 +5296,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
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)
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_EPHEMERAL) != 0, userId)
|
||||
: null;
|
||||
if (prefs != null && prefs.size() > 0) {
|
||||
boolean changed = false;
|
||||
@@ -5460,7 +5469,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
String resolvedType, int userId) {
|
||||
CrossProfileIntentResolver resolver = mSettings.mCrossProfileIntentResolvers.get(userId);
|
||||
if (resolver != null) {
|
||||
return resolver.queryIntent(intent, resolvedType, false, userId);
|
||||
return resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/,
|
||||
false /*visibleToEphemeral*/, false /*isEphemeral*/, userId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -5478,9 +5488,26 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the package name of the calling Uid if it's an ephemeral app. If it isn't
|
||||
* ephemeral, returns {@code null}.
|
||||
*/
|
||||
private String getEphemeralPackageName(int callingUid) {
|
||||
final int appId = UserHandle.getAppId(callingUid);
|
||||
synchronized (mPackages) {
|
||||
final Object obj = mSettings.getUserIdLPr(appId);
|
||||
if (obj instanceof PackageSetting) {
|
||||
final PackageSetting ps = (PackageSetting) obj;
|
||||
return ps.pkg.applicationInfo.isEphemeralApp() ? ps.pkg.packageName : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
|
||||
String resolvedType, int flags, int userId) {
|
||||
if (!sUserManager.exists(userId)) return Collections.emptyList();
|
||||
final String ephemeralPkgName = getEphemeralPackageName(Binder.getCallingUid());
|
||||
flags = updateFlagsForResolve(flags, userId, intent);
|
||||
enforceCrossUserPermission(Binder.getCallingUid(), userId,
|
||||
false /* requireFullPermission */, false /* checkShell */,
|
||||
@@ -5507,7 +5534,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// reader
|
||||
boolean sortResult = false;
|
||||
boolean addEphemeral = false;
|
||||
boolean matchEphemeralPackage = false;
|
||||
List<ResolveInfo> result;
|
||||
final String pkgName = intent.getPackage();
|
||||
synchronized (mPackages) {
|
||||
@@ -5520,7 +5546,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if (xpResolveInfo != null) {
|
||||
List<ResolveInfo> xpResult = new ArrayList<ResolveInfo>(1);
|
||||
xpResult.add(xpResolveInfo);
|
||||
return filterIfNotSystemUser(xpResult, userId);
|
||||
return filterForEphemeral(
|
||||
filterIfNotSystemUser(xpResult, userId), ephemeralPkgName);
|
||||
}
|
||||
|
||||
// Check for results in the current profile.
|
||||
@@ -5560,13 +5587,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// And we are not going to add emphemeral app, so we can return the
|
||||
// result straight away.
|
||||
result.add(xpDomainInfo.resolveInfo);
|
||||
return result;
|
||||
return filterForEphemeral(result, ephemeralPkgName);
|
||||
}
|
||||
} else if (result.size() <= 1 && !addEphemeral) {
|
||||
// No result in parent user and <= 1 result in current profile, and we
|
||||
// are not going to add emphemeral app, so we can return the result without
|
||||
// further processing.
|
||||
return result;
|
||||
return filterForEphemeral(result, ephemeralPkgName);
|
||||
}
|
||||
// We have more than one candidate (combining results from current and parent
|
||||
// profile), so we need filtering and sorting.
|
||||
@@ -5586,7 +5613,6 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
// were no installed results, so, try to find an ephemeral result
|
||||
addEphemeral = isEphemeralAllowed(
|
||||
intent, null /*result*/, userId, true /*skipPackageCheck*/);
|
||||
matchEphemeralPackage = true;
|
||||
result = new ArrayList<ResolveInfo>();
|
||||
}
|
||||
}
|
||||
@@ -5619,7 +5645,7 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if (sortResult) {
|
||||
Collections.sort(result, mResolvePrioritySorter);
|
||||
}
|
||||
return result;
|
||||
return filterForEphemeral(result, ephemeralPkgName);
|
||||
}
|
||||
|
||||
private static class CrossProfileDomainInfo {
|
||||
@@ -5717,6 +5743,38 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return resolveInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out ephemeral activities.
|
||||
* <p>When resolving for an ephemeral app, only activities that 1) are defined in the
|
||||
* ephemeral app or 2) marked with {@code visibleToEphemeral} are returned.
|
||||
*
|
||||
* @param resolveInfos The pre-filtered list of resolved activities
|
||||
* @param ephemeralPkgName The ephemeral package name. If {@code null}, no filtering
|
||||
* is performed.
|
||||
* @return A filtered list of resolved activities.
|
||||
*/
|
||||
private List<ResolveInfo> filterForEphemeral(List<ResolveInfo> resolveInfos,
|
||||
String ephemeralPkgName) {
|
||||
if (ephemeralPkgName == null) {
|
||||
return resolveInfos;
|
||||
}
|
||||
for (int i = resolveInfos.size() - 1; i >= 0; i--) {
|
||||
ResolveInfo info = resolveInfos.get(i);
|
||||
final boolean isEphemeralApp = info.activityInfo.applicationInfo.isEphemeralApp();
|
||||
// allow activities that are defined in the provided package
|
||||
if (isEphemeralApp && ephemeralPkgName.equals(info.activityInfo.packageName)) {
|
||||
continue;
|
||||
}
|
||||
// allow activities that have been explicitly exposed to ephemeral apps
|
||||
if (!isEphemeralApp
|
||||
&& ((info.activityInfo.flags & ActivityInfo.FLAG_VISIBLE_TO_EPHEMERAL) != 0)) {
|
||||
continue;
|
||||
}
|
||||
resolveInfos.remove(i);
|
||||
}
|
||||
return resolveInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resolveInfos list of resolve infos in descending priority order
|
||||
* @return if the list contains a resolve info with non-negative priority
|
||||
@@ -10742,10 +10800,13 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
final class ActivityIntentResolver
|
||||
extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
|
||||
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
|
||||
boolean defaultOnly, int userId) {
|
||||
boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
|
||||
if (!sUserManager.exists(userId)) return null;
|
||||
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
|
||||
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
|
||||
mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0)
|
||||
| (visibleToEphemeral ? PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY : 0)
|
||||
| (isEphemeral ? PackageManager.MATCH_EPHEMERAL : 0);
|
||||
return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, userId);
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
|
||||
@@ -10753,7 +10814,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if (!sUserManager.exists(userId)) return null;
|
||||
mFlags = flags;
|
||||
return super.queryIntent(intent, resolvedType,
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
|
||||
@@ -10763,7 +10826,10 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return null;
|
||||
}
|
||||
mFlags = flags;
|
||||
final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
|
||||
final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
|
||||
final boolean vislbleToEphemeral =
|
||||
(flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
|
||||
final boolean isEphemeral = (flags & PackageManager.MATCH_EPHEMERAL) != 0;
|
||||
final int N = packageActivities.size();
|
||||
ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
|
||||
new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
|
||||
@@ -10778,7 +10844,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
listCut.add(array);
|
||||
}
|
||||
}
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly,
|
||||
vislbleToEphemeral, isEphemeral, listCut, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -11263,9 +11330,10 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
private final class ServiceIntentResolver
|
||||
extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
|
||||
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
|
||||
boolean defaultOnly, int userId) {
|
||||
boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
|
||||
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
|
||||
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
|
||||
return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, userId);
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
|
||||
@@ -11273,7 +11341,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
if (!sUserManager.exists(userId)) return null;
|
||||
mFlags = flags;
|
||||
return super.queryIntent(intent, resolvedType,
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
|
||||
@@ -11284,6 +11354,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
mFlags = flags;
|
||||
final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
|
||||
final boolean vislbleToEphemeral =
|
||||
(flags&PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
|
||||
final boolean isEphemeral = (flags&PackageManager.MATCH_EPHEMERAL) != 0;
|
||||
final int N = packageServices.size();
|
||||
ArrayList<PackageParser.ServiceIntentInfo[]> listCut =
|
||||
new ArrayList<PackageParser.ServiceIntentInfo[]>(N);
|
||||
@@ -11298,7 +11371,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
listCut.add(array);
|
||||
}
|
||||
}
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly,
|
||||
vislbleToEphemeral, isEphemeral, listCut, userId);
|
||||
}
|
||||
|
||||
public final void addService(PackageParser.Service s) {
|
||||
@@ -11468,14 +11542,15 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
private final ArrayMap<ComponentName, PackageParser.Service> mServices
|
||||
= new ArrayMap<ComponentName, PackageParser.Service>();
|
||||
private int mFlags;
|
||||
};
|
||||
}
|
||||
|
||||
private final class ProviderIntentResolver
|
||||
extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
|
||||
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
|
||||
boolean defaultOnly, int userId) {
|
||||
boolean defaultOnly, boolean visibleToEphemeral, boolean isEphemeral, int userId) {
|
||||
mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
|
||||
return super.queryIntent(intent, resolvedType, defaultOnly, userId);
|
||||
return super.queryIntent(intent, resolvedType, defaultOnly, visibleToEphemeral,
|
||||
isEphemeral, userId);
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
|
||||
@@ -11484,7 +11559,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
return null;
|
||||
mFlags = flags;
|
||||
return super.queryIntent(intent, resolvedType,
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId);
|
||||
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0,
|
||||
(flags & PackageManager.MATCH_EPHEMERAL) != 0, userId);
|
||||
}
|
||||
|
||||
public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
|
||||
@@ -11496,6 +11573,9 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
}
|
||||
mFlags = flags;
|
||||
final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
|
||||
final boolean isEphemeral = (flags&PackageManager.MATCH_EPHEMERAL) != 0;
|
||||
final boolean vislbleToEphemeral =
|
||||
(flags&PackageManager.MATCH_VISIBLE_TO_EPHEMERAL_ONLY) != 0;
|
||||
final int N = packageProviders.size();
|
||||
ArrayList<PackageParser.ProviderIntentInfo[]> listCut =
|
||||
new ArrayList<PackageParser.ProviderIntentInfo[]>(N);
|
||||
@@ -11510,7 +11590,8 @@ public class PackageManagerService extends IPackageManager.Stub {
|
||||
listCut.add(array);
|
||||
}
|
||||
}
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
|
||||
return super.queryIntentFromList(intent, resolvedType, defaultOnly,
|
||||
vislbleToEphemeral, isEphemeral, listCut, userId);
|
||||
}
|
||||
|
||||
public final void addProvider(PackageParser.Provider p) {
|
||||
|
||||
Reference in New Issue
Block a user