Merge "Adds queries->provider tag"
This commit is contained in:
committed by
Android (Google) Code Review
commit
172c497117
@@ -286,6 +286,8 @@ public interface AndroidPackage extends Parcelable {
|
||||
|
||||
List<String> getQueriesPackages();
|
||||
|
||||
Set<String> getQueriesProviders();
|
||||
|
||||
String getRealPackage();
|
||||
|
||||
// TODO(b/135203078): Rename to getRequiredFeatures? Somewhat ambiguous whether "Req" is
|
||||
|
||||
@@ -96,6 +96,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/** @hide */
|
||||
public class ApkParseUtils {
|
||||
@@ -1817,6 +1818,25 @@ public class ApkParseUtils {
|
||||
);
|
||||
}
|
||||
parsingPackage.addQueriesPackage(packageName.intern());
|
||||
} else if (parser.getName().equals("provider")) {
|
||||
final TypedArray sa = res.obtainAttributes(parser,
|
||||
R.styleable.AndroidManifestQueriesProvider);
|
||||
try {
|
||||
final String authorities =
|
||||
sa.getString(R.styleable.AndroidManifestQueriesProvider_authorities);
|
||||
if (TextUtils.isEmpty(authorities)) {
|
||||
return parseInput.error(
|
||||
PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
|
||||
"Authority missing from provider tag."
|
||||
);
|
||||
}
|
||||
StringTokenizer authoritiesTokenizer = new StringTokenizer(authorities, ";");
|
||||
while (authoritiesTokenizer.hasMoreElements()) {
|
||||
parsingPackage.addQueriesProvider(authoritiesTokenizer.nextToken());
|
||||
}
|
||||
} finally {
|
||||
sa.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
return parseInput.success(parsingPackage);
|
||||
|
||||
@@ -215,6 +215,9 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
|
||||
@Nullable
|
||||
private ArrayList<String> queriesPackages;
|
||||
|
||||
@Nullable
|
||||
private ArraySet<String> queriesProviders;
|
||||
|
||||
@Nullable
|
||||
private ArrayMap<String, ComponentParseUtils.ParsedProcess> processes;
|
||||
|
||||
@@ -956,6 +959,12 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParsingPackage addQueriesProvider(String authority) {
|
||||
this.queriesProviders = ArrayUtils.add(this.queriesProviders, authority);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageImpl setProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> processes) {
|
||||
this.processes = processes;
|
||||
@@ -2975,6 +2984,11 @@ public final class PackageImpl implements ParsingPackage, ParsedPackage, Android
|
||||
return queriesPackages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getQueriesProviders() {
|
||||
return queriesProviders;
|
||||
}
|
||||
|
||||
private static void internStringArrayList(List<String> list) {
|
||||
if (list != null) {
|
||||
final int N = list.size();
|
||||
|
||||
@@ -100,6 +100,8 @@ public interface ParsingPackage extends AndroidPackage {
|
||||
|
||||
ParsingPackage addQueriesPackage(String packageName);
|
||||
|
||||
ParsingPackage addQueriesProvider(String authority);
|
||||
|
||||
ParsingPackage setProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> processes);
|
||||
|
||||
ParsingPackage asSplit(
|
||||
|
||||
@@ -2056,6 +2056,9 @@
|
||||
<attr name="name" />
|
||||
</declare-styleable>
|
||||
<declare-styleable name="AndroidManifestQueriesIntent" parent="AndroidManifestQueries" />
|
||||
<declare-styleable name="AndroidManifestQueriesProvider" parent="AndroidManifestQueries" >
|
||||
<attr name="authorities" />
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
<!-- The <code>static-library</code> tag declares that this apk is providing itself
|
||||
|
||||
@@ -33,7 +33,6 @@ import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
|
||||
import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
|
||||
import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
|
||||
import android.content.pm.parsing.ComponentParseUtils.ParsedService;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.Process;
|
||||
import android.os.Trace;
|
||||
@@ -87,10 +86,10 @@ public class AppsFilter {
|
||||
private final SparseSetArray<Integer> mQueriesViaPackage = new SparseSetArray<>();
|
||||
|
||||
/**
|
||||
* A mapping from the set of App IDs that query others via intent to the list
|
||||
* of packages that the intents resolve to.
|
||||
* A mapping from the set of App IDs that query others via component match to the list
|
||||
* of packages that the they resolve to.
|
||||
*/
|
||||
private final SparseSetArray<Integer> mQueriesViaIntent = new SparseSetArray<>();
|
||||
private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
|
||||
|
||||
/**
|
||||
* A set of App IDs that are always queryable by any package, regardless of their manifest
|
||||
@@ -206,16 +205,19 @@ public class AppsFilter {
|
||||
}
|
||||
|
||||
/** Returns true if the querying package may query for the potential target package */
|
||||
private static boolean canQueryViaIntent(AndroidPackage querying,
|
||||
private static boolean canQueryViaComponents(AndroidPackage querying,
|
||||
AndroidPackage potentialTarget) {
|
||||
if (querying.getQueriesIntents() == null) {
|
||||
return false;
|
||||
}
|
||||
for (Intent intent : querying.getQueriesIntents()) {
|
||||
if (matches(intent, potentialTarget)) {
|
||||
return true;
|
||||
if (querying.getQueriesIntents() != null) {
|
||||
for (Intent intent : querying.getQueriesIntents()) {
|
||||
if (matchesIntentFilters(intent, potentialTarget)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (querying.getQueriesProviders() != null
|
||||
&& matchesProviders(querying.getQueriesProviders(), potentialTarget)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -238,24 +240,25 @@ public class AppsFilter {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean matches(Intent intent, AndroidPackage potentialTarget) {
|
||||
private static boolean matchesProviders(
|
||||
Set<String> queriesAuthorities, AndroidPackage potentialTarget) {
|
||||
for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
|
||||
ParsedProvider provider = potentialTarget.getProviders().get(p);
|
||||
if (!provider.isExported()) {
|
||||
continue;
|
||||
}
|
||||
final Uri data = intent.getData();
|
||||
if (!"content".equalsIgnoreCase(intent.getScheme()) || data == null
|
||||
|| provider.getAuthority() == null) {
|
||||
continue;
|
||||
}
|
||||
StringTokenizer authorities = new StringTokenizer(provider.getAuthority(), ";", false);
|
||||
StringTokenizer authorities = new StringTokenizer(provider.getAuthority(), ";",
|
||||
false);
|
||||
while (authorities.hasMoreElements()) {
|
||||
if (Objects.equals(authorities.nextElement(), data.getAuthority())) {
|
||||
if (queriesAuthorities.contains(authorities.nextToken())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget) {
|
||||
for (int s = ArrayUtils.size(potentialTarget.getServices()) - 1; s >= 0; s--) {
|
||||
ParsedService service = potentialTarget.getServices().get(s);
|
||||
if (!service.exported) {
|
||||
@@ -368,8 +371,8 @@ public class AppsFilter {
|
||||
final AndroidPackage existingPkg = existingSetting.pkg;
|
||||
// let's evaluate the ability of already added packages to see this new package
|
||||
if (!newIsForceQueryable) {
|
||||
if (canQueryViaIntent(existingPkg, newPkg)) {
|
||||
mQueriesViaIntent.add(existingSetting.appId, newPkgSetting.appId);
|
||||
if (canQueryViaComponents(existingPkg, newPkg)) {
|
||||
mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId);
|
||||
}
|
||||
if (canQueryViaPackage(existingPkg, newPkg)
|
||||
|| canQueryAsInstaller(existingSetting, newPkg)) {
|
||||
@@ -378,8 +381,8 @@ public class AppsFilter {
|
||||
}
|
||||
// now we'll evaluate our new package's ability to see existing packages
|
||||
if (!mForceQueryable.contains(existingSetting.appId)) {
|
||||
if (canQueryViaIntent(newPkg, existingPkg)) {
|
||||
mQueriesViaIntent.add(newPkgSetting.appId, existingSetting.appId);
|
||||
if (canQueryViaComponents(newPkg, existingPkg)) {
|
||||
mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId);
|
||||
}
|
||||
if (canQueryViaPackage(newPkg, existingPkg)
|
||||
|| canQueryAsInstaller(newPkgSetting, existingPkg)) {
|
||||
@@ -427,9 +430,9 @@ public class AppsFilter {
|
||||
}
|
||||
}
|
||||
|
||||
mQueriesViaIntent.remove(setting.appId);
|
||||
for (int i = mQueriesViaIntent.size() - 1; i >= 0; i--) {
|
||||
mQueriesViaIntent.remove(mQueriesViaIntent.keyAt(i), setting.appId);
|
||||
mQueriesViaComponent.remove(setting.appId);
|
||||
for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
|
||||
mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId);
|
||||
}
|
||||
mQueriesViaPackage.remove(setting.appId);
|
||||
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
|
||||
@@ -594,10 +597,10 @@ public class AppsFilter {
|
||||
Trace.endSection();
|
||||
}
|
||||
try {
|
||||
Trace.beginSection("mQueriesViaIntent");
|
||||
if (mQueriesViaIntent.contains(callingAppId, targetAppId)) {
|
||||
Trace.beginSection("mQueriesViaComponent");
|
||||
if (mQueriesViaComponent.contains(callingAppId, targetAppId)) {
|
||||
if (DEBUG_LOGGING) {
|
||||
log(callingSetting, targetPkgSetting, "queries intent");
|
||||
log(callingSetting, targetPkgSetting, "queries component");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -732,7 +735,7 @@ public class AppsFilter {
|
||||
pw.println(" queries via package name:");
|
||||
dumpQueriesMap(pw, filteringAppId, mQueriesViaPackage, " ", expandPackages);
|
||||
pw.println(" queries via intent:");
|
||||
dumpQueriesMap(pw, filteringAppId, mQueriesViaIntent, " ", expandPackages);
|
||||
dumpQueriesMap(pw, filteringAppId, mQueriesViaComponent, " ", expandPackages);
|
||||
pw.println(" queryable via interaction:");
|
||||
for (int user : users) {
|
||||
pw.append(" User ").append(Integer.toString(user)).println(":");
|
||||
|
||||
@@ -35,7 +35,6 @@ import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
|
||||
import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
|
||||
import android.content.pm.parsing.PackageImpl;
|
||||
import android.content.pm.parsing.ParsingPackage;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.util.ArrayMap;
|
||||
@@ -87,6 +86,17 @@ public class AppsFilterTest {
|
||||
return pkg;
|
||||
}
|
||||
|
||||
private static ParsingPackage pkgQueriesProvider(String packageName,
|
||||
String... queriesAuthorities) {
|
||||
ParsingPackage pkg = pkg(packageName);
|
||||
if (queriesAuthorities != null) {
|
||||
for (String authority : queriesAuthorities) {
|
||||
pkg.addQueriesProvider(authority);
|
||||
}
|
||||
}
|
||||
return pkg;
|
||||
}
|
||||
|
||||
private static ParsingPackage pkg(String packageName, String... queriesPackages) {
|
||||
ParsingPackage pkg = pkg(packageName);
|
||||
if (queriesPackages != null) {
|
||||
@@ -172,8 +182,7 @@ public class AppsFilterTest {
|
||||
PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_UID);
|
||||
PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package",
|
||||
new Intent().setData(Uri.parse("content://com.some.authority"))),
|
||||
pkgQueriesProvider("com.some.other.package", "com.some.authority"),
|
||||
DUMMY_CALLING_UID);
|
||||
|
||||
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
|
||||
@@ -188,8 +197,7 @@ public class AppsFilterTest {
|
||||
PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_UID);
|
||||
PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package",
|
||||
new Intent().setData(Uri.parse("content://com.some.other.authority"))),
|
||||
pkgQueriesProvider("com.some.other.package", "com.some.other.authority"),
|
||||
DUMMY_CALLING_UID);
|
||||
|
||||
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
|
||||
@@ -205,8 +213,7 @@ public class AppsFilterTest {
|
||||
pkgWithProvider("com.some.package", "com.some.authority;com.some.other.authority"),
|
||||
DUMMY_TARGET_UID);
|
||||
PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package",
|
||||
new Intent().setData(Uri.parse("content://com.some.authority"))),
|
||||
pkgQueriesProvider("com.some.other.package", "com.some.authority"),
|
||||
DUMMY_CALLING_UID);
|
||||
|
||||
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
|
||||
@@ -266,7 +273,7 @@ public class AppsFilterTest {
|
||||
appsFilter.onSystemReady();
|
||||
|
||||
PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_UID);
|
||||
pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_UID);
|
||||
PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package"), DUMMY_CALLING_UID);
|
||||
|
||||
|
||||
@@ -391,6 +391,7 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
|
||||
manifest_action["uses-split"].Action(RequiredNameIsJavaPackage);
|
||||
manifest_action["queries"]["package"].Action(RequiredNameIsJavaPackage);
|
||||
manifest_action["queries"]["intent"] = intent_filter_action;
|
||||
manifest_action["queries"]["provider"].Action(RequiredAndroidAttribute("authorities"));
|
||||
// TODO: more complicated component name tag
|
||||
|
||||
manifest_action["key-sets"]["key-set"]["public-key"];
|
||||
|
||||
Reference in New Issue
Block a user