Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0446108e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Grant package visibility to dependent library" into sc-dev

parents 3e9d0bed e757ab24
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -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,
+117 −0
Original line number Diff line number Diff line
@@ -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 =