Merge "Grant package visibility to dependent library" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0446108ed6
@@ -104,6 +104,12 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
*/
|
||||
private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
|
||||
|
||||
/**
|
||||
* A mapping from the set of App IDs that query other App IDs via library name to the
|
||||
* list of packages that they can see.
|
||||
*/
|
||||
private final SparseSetArray<Integer> mQueryableViaUsesLibrary = new SparseSetArray<>();
|
||||
|
||||
/**
|
||||
* Executor for running reasonably short background tasks such as building the initial
|
||||
* visibility cache.
|
||||
@@ -239,6 +245,7 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
|
||||
Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
|
||||
Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
|
||||
Snapshots.copy(mQueryableViaUsesLibrary, orig.mQueryableViaUsesLibrary);
|
||||
mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
|
||||
mForceQueryable.addAll(orig.mForceQueryable);
|
||||
mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
|
||||
@@ -508,6 +515,22 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean canQueryViaUsesLibrary(AndroidPackage querying,
|
||||
AndroidPackage potentialTarget) {
|
||||
if (potentialTarget.getLibraryNames().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
final List<String> libNames = potentialTarget.getLibraryNames();
|
||||
for (int i = 0, size = libNames.size(); i < size; i++) {
|
||||
final String libName = libNames.get(i);
|
||||
if (querying.getUsesLibraries().contains(libName)
|
||||
|| querying.getUsesOptionalLibraries().contains(libName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean matchesProviders(
|
||||
Set<String> queriesAuthorities, AndroidPackage potentialTarget) {
|
||||
for (int p = ArrayUtils.size(potentialTarget.getProviders()) - 1; p >= 0; p--) {
|
||||
@@ -707,6 +730,9 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
|| canQueryAsInstaller(existingSetting, newPkg)) {
|
||||
mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
|
||||
}
|
||||
if (canQueryViaUsesLibrary(existingPkg, newPkg)) {
|
||||
mQueryableViaUsesLibrary.add(existingSetting.appId, newPkgSetting.appId);
|
||||
}
|
||||
}
|
||||
// now we'll evaluate our new package's ability to see existing packages
|
||||
if (!mForceQueryable.contains(existingSetting.appId)) {
|
||||
@@ -718,6 +744,9 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
|| canQueryAsInstaller(newPkgSetting, existingPkg)) {
|
||||
mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
|
||||
}
|
||||
if (canQueryViaUsesLibrary(newPkg, existingPkg)) {
|
||||
mQueryableViaUsesLibrary.add(newPkgSetting.appId, existingSetting.appId);
|
||||
}
|
||||
}
|
||||
// if either package instruments the other, mark both as visible to one another
|
||||
if (newPkgSetting.pkg != null && existingSetting.pkg != null
|
||||
@@ -1035,6 +1064,10 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
|
||||
mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
|
||||
}
|
||||
mQueryableViaUsesLibrary.remove(setting.appId);
|
||||
for (int i = mQueryableViaUsesLibrary.size() - 1; i >= 0; i--) {
|
||||
mQueryableViaUsesLibrary.remove(mQueryableViaUsesLibrary.keyAt(i), setting.appId);
|
||||
}
|
||||
|
||||
mForceQueryable.remove(setting.appId);
|
||||
|
||||
@@ -1315,6 +1348,18 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
|
||||
}
|
||||
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mQueryableViaUsesLibrary");
|
||||
if (mQueryableViaUsesLibrary.contains(callingAppId, targetAppId)) {
|
||||
if (DEBUG_LOGGING) {
|
||||
log(callingSetting, targetPkgSetting, "queryable for library users");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
|
||||
}
|
||||
|
||||
return true;
|
||||
} finally {
|
||||
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
|
||||
@@ -1394,6 +1439,8 @@ public class AppsFilter implements Watchable, Snappable {
|
||||
filteringAppId == null ? null : UserHandle.getUid(user, filteringAppId),
|
||||
mImplicitlyQueryable, " ", expandPackages);
|
||||
}
|
||||
pw.println(" queryable via uses-library:");
|
||||
dumpQueriesMap(pw, filteringAppId, mQueryableViaUsesLibrary, " ", expandPackages);
|
||||
}
|
||||
|
||||
private static void dumpQueriesMap(PrintWriter pw, @Nullable Integer filteringId,
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageParser;
|
||||
import android.content.pm.PackageParser.SigningDetails;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.pm.parsing.ParsingPackage;
|
||||
@@ -141,6 +142,10 @@ public class AppsFilterTest {
|
||||
return pkg(packageName).addReceiver(receiver);
|
||||
}
|
||||
|
||||
private static ParsingPackage pkgWithSharedLibrary(String packageName, String libName) {
|
||||
return pkg(packageName).addLibraryName(libName);
|
||||
}
|
||||
|
||||
private static ParsedActivity createActivity(String packageName, IntentFilter[] filters) {
|
||||
ParsedActivity activity = new ParsedActivity();
|
||||
activity.setPackageName(packageName);
|
||||
@@ -412,6 +417,118 @@ public class AppsFilterTest {
|
||||
SYSTEM_USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoUsesLibrary_Filters() throws Exception {
|
||||
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
|
||||
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
|
||||
mMockExecutor);
|
||||
|
||||
simulateAddBasicAndroid(appsFilter);
|
||||
appsFilter.onSystemReady();
|
||||
|
||||
final Signature mockSignature = Mockito.mock(Signature.class);
|
||||
final SigningDetails mockSigningDetails = new SigningDetails(
|
||||
new Signature[]{mockSignature},
|
||||
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
|
||||
|
||||
final PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
|
||||
DUMMY_TARGET_APPID,
|
||||
setting -> setting.setSigningDetails(mockSigningDetails)
|
||||
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
|
||||
final PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package"), DUMMY_CALLING_APPID);
|
||||
|
||||
assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
|
||||
SYSTEM_USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsesLibrary_DoesntFilter() throws Exception {
|
||||
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
|
||||
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
|
||||
mMockExecutor);
|
||||
|
||||
simulateAddBasicAndroid(appsFilter);
|
||||
appsFilter.onSystemReady();
|
||||
|
||||
final Signature mockSignature = Mockito.mock(Signature.class);
|
||||
final SigningDetails mockSigningDetails = new SigningDetails(
|
||||
new Signature[]{mockSignature},
|
||||
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
|
||||
|
||||
final PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
|
||||
DUMMY_TARGET_APPID,
|
||||
setting -> setting.setSigningDetails(mockSigningDetails)
|
||||
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
|
||||
final PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package").addUsesLibrary("com.some.shared_library"),
|
||||
DUMMY_CALLING_APPID);
|
||||
|
||||
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
|
||||
SYSTEM_USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsesOptionalLibrary_DoesntFilter() throws Exception {
|
||||
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
|
||||
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
|
||||
mMockExecutor);
|
||||
|
||||
simulateAddBasicAndroid(appsFilter);
|
||||
appsFilter.onSystemReady();
|
||||
|
||||
final Signature mockSignature = Mockito.mock(Signature.class);
|
||||
final SigningDetails mockSigningDetails = new SigningDetails(
|
||||
new Signature[]{mockSignature},
|
||||
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
|
||||
|
||||
final PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
|
||||
DUMMY_TARGET_APPID,
|
||||
setting -> setting.setSigningDetails(mockSigningDetails)
|
||||
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
|
||||
final PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package").addUsesOptionalLibrary("com.some.shared_library"),
|
||||
DUMMY_CALLING_APPID);
|
||||
|
||||
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
|
||||
SYSTEM_USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsesLibrary_ShareUid_DoesntFilter() throws Exception {
|
||||
final AppsFilter appsFilter = new AppsFilter(mStateProvider, mFeatureConfigMock,
|
||||
new String[]{}, /* systemAppsQueryable */ false, /* overlayProvider */ null,
|
||||
mMockExecutor);
|
||||
|
||||
simulateAddBasicAndroid(appsFilter);
|
||||
appsFilter.onSystemReady();
|
||||
|
||||
final Signature mockSignature = Mockito.mock(Signature.class);
|
||||
final SigningDetails mockSigningDetails = new SigningDetails(
|
||||
new Signature[]{mockSignature},
|
||||
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2);
|
||||
|
||||
final PackageSetting target = simulateAddPackage(appsFilter,
|
||||
pkgWithSharedLibrary("com.some.package", "com.some.shared_library"),
|
||||
DUMMY_TARGET_APPID,
|
||||
setting -> setting.setSigningDetails(mockSigningDetails)
|
||||
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
|
||||
final PackageSetting calling = simulateAddPackage(appsFilter,
|
||||
pkg("com.some.other.package_a").setSharedUserId("com.some.uid"),
|
||||
DUMMY_CALLING_APPID);
|
||||
simulateAddPackage(appsFilter, pkg("com.some.other.package_b")
|
||||
.setSharedUserId("com.some.uid").addUsesLibrary("com.some.shared_library"),
|
||||
DUMMY_CALLING_APPID);
|
||||
|
||||
// Although package_a doesn't use library, it should be granted visibility. It's because
|
||||
// package_a shares userId with package_b, and package_b uses that shared library.
|
||||
assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
|
||||
SYSTEM_USER));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testForceQueryable_SystemDoesntFilter() throws Exception {
|
||||
final AppsFilter appsFilter =
|
||||
|
||||
Reference in New Issue
Block a user