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

Commit 8e5ad5d4 authored by Alexander Dorokhine's avatar Alexander Dorokhine
Browse files

Sync framework from jetpack.

Included changes:
* 31866d: Migrate VisibilityStore to a no-op.

Bug: 169883602
Test: Presubmit
Change-Id: I9a4abbf64d29a248a0d04e883961f1a6da556802
parent 17e406e2
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ public final class ImplInstanceManager {
    private static AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId)
            throws AppSearchException {
        File appSearchDir = getAppSearchDir(context, userId);
        return AppSearchImpl.create(appSearchDir, context, /*globalQuerierPackage=*/"");
        return AppSearchImpl.create(appSearchDir, context, userId, /*globalQuerierPackage=*/"");
    }

    private static File getAppSearchDir(@NonNull Context context, @UserIdInt int userId) {
+0 −0

File moved.

+13 −4
Original line number Diff line number Diff line
@@ -160,18 +160,25 @@ public final class AppSearchImpl {
     */
    @NonNull
    public static AppSearchImpl create(
            @NonNull File icingDir, @NonNull Context context, @NonNull String globalQuerierPackage)
            @NonNull File icingDir,
            @NonNull Context context,
            int userId,
            @NonNull String globalQuerierPackage)
            throws AppSearchException {
        Preconditions.checkNotNull(icingDir);
        Preconditions.checkNotNull(context);
        Preconditions.checkNotNull(globalQuerierPackage);
        AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, context, globalQuerierPackage);
        AppSearchImpl appSearchImpl =
                new AppSearchImpl(icingDir, context, userId, globalQuerierPackage);
        appSearchImpl.initializeVisibilityStore();
        return appSearchImpl;
    }

    private AppSearchImpl(
            @NonNull File icingDir, @NonNull Context context, @NonNull String globalQuerierPackage)
            @NonNull File icingDir,
            @NonNull Context context,
            int userId,
            @NonNull String globalQuerierPackage)
            throws AppSearchException {
        mReadWriteLock.writeLock().lock();

@@ -184,7 +191,8 @@ public final class AppSearchImpl {
                            .build();
            mIcingSearchEngineLocked = new IcingSearchEngine(options);

            mVisibilityStoreLocked = new VisibilityStore(this, context, globalQuerierPackage);
            mVisibilityStoreLocked =
                    new VisibilityStore(this, context, globalQuerierPackage);

            InitializeResultProto initializeResultProto = mIcingSearchEngineLocked.initialize();
            SchemaProto schemaProto;
@@ -1350,6 +1358,7 @@ public final class AppSearchImpl {
    }

    @GuardedBy("mReadWriteLock")
    @NonNull
    @VisibleForTesting
    VisibilityStore getVisibilityStoreLocked() {
        return mVisibilityStoreLocked;
+1 −1
Original line number Diff line number Diff line
Iff96eae150c7cdd281c9ecb5d93f4ef697e89f1a
I03df55376689c1557c651d5b9671c40da1c35955
+14 −389
Original line number Diff line number Diff line
@@ -22,14 +22,12 @@ import static org.testng.Assert.expectThrows;

import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.util.ArraySet;

import androidx.test.core.app.ApplicationProvider;

@@ -46,7 +44,6 @@ import com.android.server.appsearch.proto.StringIndexingConfig;
import com.android.server.appsearch.proto.TermMatchType;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;

import org.junit.Before;
@@ -57,33 +54,23 @@ import org.junit.rules.TemporaryFolder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class AppSearchImplTest {
    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
    private MockPackageManager mMockPackageManager = new MockPackageManager();
    private Context mContext;
    private AppSearchImpl mAppSearchImpl;
    private int mGlobalQuerierUid;

    @Before
    public void setUp() throws Exception {
        Context context = ApplicationProvider.getApplicationContext();
        mContext =
                new ContextWrapper(context) {
                    @Override
                    public PackageManager getPackageManager() {
                        return mMockPackageManager.getMockPackageManager();
                    }
                };

        // Give ourselves global query permissions
        mAppSearchImpl =
                AppSearchImpl.create(
                        mTemporaryFolder.newFolder(),
                        mContext,
                        /*globalQuerierPackage=*/ mContext.getPackageName());
        mGlobalQuerierUid =
                mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
                        context,
                        /*userId=*/-1,
                        /*globalQuerierPackage
                        =*/ context.getPackageName());
    }

    // TODO(b/175430168) add test to verify reset is working properly.
@@ -702,125 +689,10 @@ public class AppSearchImplTest {
                new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
        SearchResultPage searchResultPage =
                mAppSearchImpl.globalQuery(
                        "", searchSpec, mContext.getPackageName(), /*callerUid=*/ 0);
                        "", searchSpec, /*callerPackageName=*/ "", /*callerUid=*/ 0);
        assertThat(searchResultPage.getResults()).isEmpty();
    }

    /**
     * TODO(b/169883602): This should be an integration test at the cts-level. This is a short-term
     * test until we have official support for multiple-apps indexing at once.
     */
    @Test
    public void testGlobalQueryWithMultiplePackages_noPackageFilters() throws Exception {
        // Insert package1 schema
        List<AppSearchSchema> schema1 =
                ImmutableList.of(new AppSearchSchema.Builder("schema1").build());
        mAppSearchImpl.setSchema(
                "package1",
                "database1",
                schema1,
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);

        // Insert package2 schema
        List<AppSearchSchema> schema2 =
                ImmutableList.of(new AppSearchSchema.Builder("schema2").build());
        mAppSearchImpl.setSchema(
                "package2",
                "database2",
                schema2,
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);

        // Insert package1 document
        GenericDocument document1 =
                new GenericDocument.Builder<>("uri", "schema1").setNamespace("namespace").build();
        mAppSearchImpl.putDocument("package1", "database1", document1);

        // Insert package2 document
        GenericDocument document2 =
                new GenericDocument.Builder<>("uri", "schema2").setNamespace("namespace").build();
        mAppSearchImpl.putDocument("package2", "database2", document2);

        // No query filters specified, global query can retrieve all documents.
        SearchSpec searchSpec =
                new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
        SearchResultPage searchResultPage =
                mAppSearchImpl.globalQuery(
                        "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid);
        assertThat(searchResultPage.getResults()).hasSize(2);

        // Document2 will be first since it got indexed later and has a "better", aka more recent
        // score.
        assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document2);
        assertThat(searchResultPage.getResults().get(1).getDocument()).isEqualTo(document1);
    }

    /**
     * TODO(b/169883602): This should be an integration test at the cts-level. This is a short-term
     * test until we have official support for multiple-apps indexing at once.
     */
    @Test
    public void testGlobalQueryWithMultiplePackages_withPackageFilters() throws Exception {
        // Insert package1 schema
        List<AppSearchSchema> schema1 =
                ImmutableList.of(new AppSearchSchema.Builder("schema1").build());
        mAppSearchImpl.setSchema(
                "package1",
                "database1",
                schema1,
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);

        // Insert package2 schema
        List<AppSearchSchema> schema2 =
                ImmutableList.of(new AppSearchSchema.Builder("schema2").build());
        mAppSearchImpl.setSchema(
                "package2",
                "database2",
                schema2,
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);

        // Insert package1 document
        GenericDocument document1 =
                new GenericDocument.Builder<>("uri", "schema1").setNamespace("namespace").build();
        mAppSearchImpl.putDocument("package1", "database1", document1);

        // Insert package2 document
        GenericDocument document2 =
                new GenericDocument.Builder<>("uri", "schema2").setNamespace("namespace").build();
        mAppSearchImpl.putDocument("package2", "database2", document2);

        // "package1" filter specified
        SearchSpec searchSpec =
                new SearchSpec.Builder()
                        .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
                        .addFilterPackageNames("package1")
                        .build();
        SearchResultPage searchResultPage =
                mAppSearchImpl.globalQuery(
                        "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid);
        assertThat(searchResultPage.getResults()).hasSize(1);
        assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document1);

        // "package2" filter specified
        searchSpec =
                new SearchSpec.Builder()
                        .setTermMatch(TermMatchType.Code.PREFIX_VALUE)
                        .addFilterPackageNames("package2")
                        .build();
        searchResultPage =
                mAppSearchImpl.globalQuery(
                        "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid);
        assertThat(searchResultPage.getResults()).hasSize(1);
        assertThat(searchResultPage.getResults().get(0).getDocument()).isEqualTo(document2);
    }

    @Test
    public void testRemoveEmptyDatabase_noExceptionThrown() throws Exception {
        SearchSpec searchSpec =
@@ -873,82 +745,6 @@ public class AppSearchImplTest {
                .containsExactlyElementsIn(expectedTypes);
    }

    @Test
    public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception {
        // Values for a "foo" client
        String packageNameFoo = "packageFoo";
        byte[] sha256CertFoo = new byte[] {10};
        int uidFoo = 1;

        // Make sure foo package will pass package manager checks.
        mMockPackageManager.mockGetPackageUid(packageNameFoo, uidFoo);
        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);

        // Set schema1
        String prefix = AppSearchImpl.createPrefix("package", "database");
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
                /*schemasPackageAccessible=*/ ImmutableMap.of(
                        "schema1",
                        ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
                /*forceOverride=*/ false);

        // "schema1" is platform hidden now and package visible to package1
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "schema1", mGlobalQuerierUid))
                .isFalse();
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "schema1", uidFoo))
                .isTrue();

        // Add a new schema, and include the already-existing "schema1"
        mAppSearchImpl.setSchema(
                "package",
                "database",
                ImmutableList.of(
                        new AppSearchSchema.Builder("schema1").build(),
                        new AppSearchSchema.Builder("schema2").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
                /*schemasPackageAccessible=*/ ImmutableMap.of(
                        "schema1",
                        ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
                /*forceOverride=*/ false);

        // Check that "schema1" still has the same visibility settings
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "schema1", mGlobalQuerierUid))
                .isFalse();
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "schema1", uidFoo))
                .isTrue();

        // "schema2" has default visibility settings
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "schema2", mGlobalQuerierUid))
                .isTrue();
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "schema2", uidFoo))
                .isFalse();
    }

    @Test
    public void testRemoveSchema() throws Exception {
        List<SchemaTypeConfigProto> existingSchemas =
@@ -1120,167 +916,6 @@ public class AppSearchImplTest {
                .containsExactlyElementsIn(expectedTypes);
    }

    @Test
    public void testRemoveSchema_removedFromVisibilityStore() throws Exception {
        // Values for a "foo" client
        String packageNameFoo = "packageFoo";
        byte[] sha256CertFoo = new byte[] {10};
        int uidFoo = 1;

        // Make sure foo package will pass package manager checks.
        mMockPackageManager.mockGetPackageUid(packageNameFoo, uidFoo);
        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);

        String prefix = AppSearchImpl.createPrefix("package", "database");
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
                /*schemasPackageAccessible=*/ ImmutableMap.of(
                        "schema1",
                        ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
                /*forceOverride=*/ false);

        // "schema1" is platform hidden now and package accessible
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "schema1", mGlobalQuerierUid))
                .isFalse();
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "schema1", uidFoo))
                .isTrue();

        // Remove "schema1" by force overriding
        mAppSearchImpl.setSchema(
                "package",
                "database",
                /*schemas=*/ Collections.emptyList(),
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ true);

        // Check that "schema1" is no longer considered platform hidden or package accessible
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "schema1", mGlobalQuerierUid))
                .isTrue();
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "schema1", uidFoo))
                .isFalse();

        // Add "schema1" back, it gets default visibility settings which means it's not platform
        // hidden and not package accessible
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "schema1", mGlobalQuerierUid))
                .isTrue();
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "schema1", uidFoo))
                .isFalse();
    }

    @Test
    public void testSetSchema_defaultPlatformVisible() throws Exception {
        String prefix = AppSearchImpl.createPrefix("package", "database");
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "Schema", mGlobalQuerierUid))
                .isTrue();
    }

    @Test
    public void testSetSchema_platformHidden() throws Exception {
        String prefix = AppSearchImpl.createPrefix("package", "database");
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "Schema", mGlobalQuerierUid))
                .isFalse();
    }

    @Test
    public void testSetSchema_defaultNotPackageAccessible() throws Exception {
        String prefix = AppSearchImpl.createPrefix("package", "database");
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(
                                        prefix, prefix + "Schema", /*callerUid=*/ 42))
                .isFalse();
    }

    @Test
    public void testSetSchema_packageAccessible() throws Exception {
        // Values for a "foo" client
        String packageNameFoo = "packageFoo";
        byte[] sha256CertFoo = new byte[] {10};
        int uidFoo = 1;

        // Make sure foo package will pass package manager checks.
        mMockPackageManager.mockGetPackageUid(packageNameFoo, uidFoo);
        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);

        String prefix = AppSearchImpl.createPrefix("package", "database");
        mAppSearchImpl.setSchema(
                "package",
                "database",
                Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ ImmutableMap.of(
                        "Schema",
                        ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))),
                /*forceOverride=*/ false);
        assertThat(
                        mAppSearchImpl
                                .getVisibilityStoreLocked()
                                .isSchemaSearchableByCaller(prefix, prefix + "Schema", uidFoo))
                .isTrue();
    }

    @Test
    public void testHasSchemaType() throws Exception {
        // Nothing exists yet
@@ -1300,14 +935,12 @@ public class AppSearchImplTest {
    }

    @Test
    public void testGetDatabases() throws Exception {
        // No client databases exist yet, but the VisibilityStore's does
        assertThat(mAppSearchImpl.getPrefixesLocked())
                .containsExactly(
                        AppSearchImpl.createPrefix(
                                VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME));
    public void testGetPrefixes() throws Exception {
        Set<String> existingPrefixes = mAppSearchImpl.getPrefixesLocked();

        // Has database1
        Set<String> expectedPrefixes = new ArraySet<>(existingPrefixes);
        expectedPrefixes.add(AppSearchImpl.createPrefix("package", "database1"));
        mAppSearchImpl.setSchema(
                "package",
                "database1",
@@ -1315,13 +948,10 @@ public class AppSearchImplTest {
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);
        assertThat(mAppSearchImpl.getPrefixesLocked())
                .containsExactly(
                        AppSearchImpl.createPrefix(
                                VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME),
                        AppSearchImpl.createPrefix("package", "database1"));
        assertThat(mAppSearchImpl.getPrefixesLocked()).containsExactlyElementsIn(expectedPrefixes);

        // Has both databases
        expectedPrefixes.add(AppSearchImpl.createPrefix("package", "database2"));
        mAppSearchImpl.setSchema(
                "package",
                "database2",
@@ -1329,12 +959,7 @@ public class AppSearchImplTest {
                /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
                /*schemasPackageAccessible=*/ Collections.emptyMap(),
                /*forceOverride=*/ false);
        assertThat(mAppSearchImpl.getPrefixesLocked())
                .containsExactly(
                        AppSearchImpl.createPrefix(
                                VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME),
                        AppSearchImpl.createPrefix("package", "database1"),
                        AppSearchImpl.createPrefix("package", "database2"));
        assertThat(mAppSearchImpl.getPrefixesLocked()).containsExactlyElementsIn(expectedPrefixes);
    }

    @Test
Loading