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

Commit c1cdfed2 authored by Tony Mak's avatar Tony Mak
Browse files

Add tests for FutureAppSearchSession

Flag: android.app.appfunctions.flags.enable_app_function_manager
Test: atest FrameworksAppFunctionsTests

Bug: 357551503
Change-Id: Icb45dbb800eebf979ba385e32cb58f9ae2f4a2b9
parent 32c3d5fe
Loading
Loading
Loading
Loading
+22 −6
Original line number Original line Diff line number Diff line
@@ -72,14 +72,32 @@ public class AppFunctionRuntimeMetadata extends GenericDocument {
     * we need to have per-package app function schemas.
     * we need to have per-package app function schemas.
     *
     *
     * <p>This schema should be set visible to callers from the package owner itself and for callers
     * <p>This schema should be set visible to callers from the package owner itself and for callers
     * with {@link android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
     * with {@link android.Manifest.permission#EXECUTE_APP_FUNCTIONS} or {@link
     * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
     * android.Manifest.permission#EXECUTE_APP_FUNCTIONS_TRUSTED} permissions.
     *
     *
     * @param packageName The package name to create a schema for.
     * @param packageName The package name to create a schema for.
     */
     */
    @NonNull
    @NonNull
    public static AppSearchSchema createAppFunctionRuntimeSchema(@NonNull String packageName) {
    public static AppSearchSchema createAppFunctionRuntimeSchema(@NonNull String packageName) {
        return new AppSearchSchema.Builder(getRuntimeSchemaNameForPackage(packageName))
        return getAppFunctionRuntimeSchemaBuilder(getRuntimeSchemaNameForPackage(packageName))
                .addParentType(RUNTIME_SCHEMA_TYPE)
                .build();
    }

    /**
     * Creates a parent schema for all app function runtime schemas.
     *
     * <p>This schema should be set visible to the owner itself and for callers with {@link
     * android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} or {@link
     * android.permission.EXECUTE_APP_FUNCTIONS} permissions.
     */
    public static AppSearchSchema createParentAppFunctionRuntimeSchema() {
        return getAppFunctionRuntimeSchemaBuilder(RUNTIME_SCHEMA_TYPE).build();
    }

    private static AppSearchSchema.Builder getAppFunctionRuntimeSchemaBuilder(
            @NonNull String schemaType) {
        return new AppSearchSchema.Builder(schemaType)
                .addProperty(
                .addProperty(
                        new AppSearchSchema.StringPropertyConfig.Builder(PROPERTY_FUNCTION_ID)
                        new AppSearchSchema.StringPropertyConfig.Builder(PROPERTY_FUNCTION_ID)
                                .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
                                .setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_OPTIONAL)
@@ -111,9 +129,7 @@ public class AppFunctionRuntimeMetadata extends GenericDocument {
                                .setJoinableValueType(
                                .setJoinableValueType(
                                        AppSearchSchema.StringPropertyConfig
                                        AppSearchSchema.StringPropertyConfig
                                                .JOINABLE_VALUE_TYPE_QUALIFIED_ID)
                                                .JOINABLE_VALUE_TYPE_QUALIFIED_ID)
                                .build())
                                .build());
                .addParentType(RUNTIME_SCHEMA_TYPE)
                .build();
    }
    }


    /** Returns the function id. This might look like "com.example.message#send_message". */
    /** Returns the function id. This might look like "com.example.message#send_message". */
+1 −4
Original line number Original line Diff line number Diff line
@@ -25,7 +25,6 @@ import android.app.appsearch.AppSearchManager;
import android.app.appsearch.AppSearchManager.SearchContext;
import android.app.appsearch.AppSearchManager.SearchContext;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSession;
import android.app.appsearch.AppSearchSession;
import android.app.appsearch.BatchResultCallback;
import android.app.appsearch.GetSchemaResponse;
import android.app.appsearch.GetSchemaResponse;
import android.app.appsearch.PutDocumentsRequest;
import android.app.appsearch.PutDocumentsRequest;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResult;
@@ -50,7 +49,6 @@ import java.util.concurrent.Executor;
public class FutureAppSearchSession implements Closeable {
public class FutureAppSearchSession implements Closeable {
    private static final String TAG = FutureAppSearchSession.class.getSimpleName();
    private static final String TAG = FutureAppSearchSession.class.getSimpleName();
    private final Executor mExecutor;
    private final Executor mExecutor;
    private final AppSearchManager mAppSearchManager;
    private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;
    private final AndroidFuture<AppSearchResult<AppSearchSession>> mSettableSessionFuture;


    public FutureAppSearchSession(
    public FutureAppSearchSession(
@@ -62,9 +60,8 @@ public class FutureAppSearchSession implements Closeable {
        Objects.requireNonNull(appSearchContext);
        Objects.requireNonNull(appSearchContext);


        mExecutor = executor;
        mExecutor = executor;
        mAppSearchManager = appSearchManager;
        mSettableSessionFuture = new AndroidFuture<>();
        mSettableSessionFuture = new AndroidFuture<>();
        mAppSearchManager.createSearchSession(
        appSearchManager.createSearchSession(
                appSearchContext, mExecutor, mSettableSessionFuture::complete);
                appSearchContext, mExecutor, mSettableSessionFuture::complete);
    }
    }


+1 −1
Original line number Original line Diff line number Diff line
@@ -37,7 +37,7 @@ android_test {
        "androidx.test.runner",
        "androidx.test.runner",
        "androidx.test.ext.truth",
        "androidx.test.ext.truth",
        "platform-test-annotations",
        "platform-test-annotations",
        "services.core",
        "services.appfunctions",
        "servicestests-core-utils",
        "servicestests-core-utils",
        "truth",
        "truth",
        "frameworks-base-testutils",
        "frameworks-base-testutils",
+131 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.server.appfunctions

import android.app.appfunctions.AppFunctionRuntimeMetadata
import android.app.appfunctions.AppFunctionRuntimeMetadata.createAppFunctionRuntimeSchema
import android.app.appfunctions.AppFunctionRuntimeMetadata.createParentAppFunctionRuntimeSchema
import android.app.appsearch.AppSearchManager
import android.app.appsearch.PutDocumentsRequest
import android.app.appsearch.SearchSpec
import android.app.appsearch.SetSchemaRequest
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@RunWith(JUnit4::class)
class FutureAppSearchSessionTest {
    private val context = InstrumentationRegistry.getInstrumentation().targetContext
    private val appSearchManager = context.getSystemService(AppSearchManager::class.java)
    private val testExecutor = MoreExecutors.directExecutor()

    @Before
    @After
    fun clearData() {
        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use {
            val setSchemaRequest = SetSchemaRequest.Builder().build()
            it.setSchema(setSchemaRequest)
        }
    }

    @Test
    fun setSchema() {
        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
            val setSchemaRequest =
                SetSchemaRequest.Builder()
                    .addSchemas(
                        createParentAppFunctionRuntimeSchema(),
                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
                    )
                    .build()

            val schema = session.setSchema(setSchemaRequest)

            assertThat(schema.get()).isNotNull()
        }
    }

    @Test
    fun put() {
        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
            val setSchemaRequest =
                SetSchemaRequest.Builder()
                    .addSchemas(
                        createParentAppFunctionRuntimeSchema(),
                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
                    )
                    .build()
            val schema = session.setSchema(setSchemaRequest)
            assertThat(schema.get()).isNotNull()
            val appFunctionRuntimeMetadata =
                AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
            val putDocumentsRequest: PutDocumentsRequest =
                PutDocumentsRequest.Builder()
                    .addGenericDocuments(appFunctionRuntimeMetadata)
                    .build()

            val putResult = session.put(putDocumentsRequest)

            assertThat(putResult.get().isSuccess).isTrue()
        }
    }

    @Test
    fun search() {
        val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build()
        FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { session ->
            val setSchemaRequest =
                SetSchemaRequest.Builder()
                    .addSchemas(
                        createParentAppFunctionRuntimeSchema(),
                        createAppFunctionRuntimeSchema(TEST_PACKAGE_NAME)
                    )
                    .build()
            val schema = session.setSchema(setSchemaRequest)
            assertThat(schema.get()).isNotNull()
            val appFunctionRuntimeMetadata =
                AppFunctionRuntimeMetadata.Builder(TEST_PACKAGE_NAME, TEST_FUNCTION_ID, "").build()
            val putDocumentsRequest: PutDocumentsRequest =
                PutDocumentsRequest.Builder()
                    .addGenericDocuments(appFunctionRuntimeMetadata)
                    .build()
            val putResult = session.put(putDocumentsRequest)
            assertThat(putResult.get().isSuccess).isTrue()

            val searchResult = session.search("", SearchSpec.Builder().build())

            val genericDocs =
                searchResult.get().nextPage.get().stream().map { it.genericDocument }.toList()
            assertThat(genericDocs).hasSize(1)
            val foundAppFunctionRuntimeMetadata = AppFunctionRuntimeMetadata(genericDocs[0])
            assertThat(foundAppFunctionRuntimeMetadata.functionId).isEqualTo(TEST_FUNCTION_ID)
        }
    }

    private companion object {
        const val TEST_DB: String = "test_db"
        const val TEST_PACKAGE_NAME: String = "test_pkg"
        const val TEST_FUNCTION_ID: String = "print"
    }
}