Merge "Scope package manager queries for ephemeral apps"

This commit is contained in:
TreeHugger Robot
2016-12-12 19:11:34 +00:00
committed by Android (Google) Code Review
16 changed files with 254 additions and 55 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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">

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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>();
}

View File

@@ -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);
}

View File

@@ -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) {