Prepare AppsIndexer CTS Tests for GMS-AppSearch.
- Rename AppIndexerCtsTest to AppsIndexerCtsTest
- Move AppFunction tests to AppFunctionCtsTest
- Move all common utils to AppsIndexerTestUtils
Bug: 413737868
Flag: EXEMPT TEST_ONLY
Test: Presubmits
Change-Id: Idb1896030e9b97facf24353debc6d7b5ee91b5e5
diff --git a/tests/appsearch/indexer-test-app/AndroidManifest_A_v1.xml b/tests/appsearch/indexer-test-app/AndroidManifest_A_v1.xml
index f84efa1..c6ebf50 100644
--- a/tests/appsearch/indexer-test-app/AndroidManifest_A_v1.xml
+++ b/tests/appsearch/indexer-test-app/AndroidManifest_A_v1.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
~ Copyright (C) 2021 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,18 @@
~ 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.
- -->
+-->
+<!-- Manifest for App A v1 with label "App A [V1]" and MainActivity. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.appsearch.indexertestapp.a">
+ <!-- TODO: b/413737868 - Lower minSdkVersion to 24 once the remaining GMS Core
+ targets are supported. -->
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="34" />
+
<application android:label="App A [v1]">
- <activity android:name="com.android.cts.appsearch.helper.MainActivity"
+ <activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tests/appsearch/indexer-test-app/AndroidManifest_A_v2.xml b/tests/appsearch/indexer-test-app/AndroidManifest_A_v2.xml
index eb4e971..aaca59d 100644
--- a/tests/appsearch/indexer-test-app/AndroidManifest_A_v2.xml
+++ b/tests/appsearch/indexer-test-app/AndroidManifest_A_v2.xml
@@ -1,4 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?><!--
+<?xml version="1.0" encoding="utf-8"?>
+<!--
~ Copyright (C) 2024 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
@@ -12,13 +13,18 @@
~ 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.
- -->
+-->
+<!-- Manifest for App A v2 with label "App A [V2]" and an added AppFunctionService. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.appsearch.indexertestapp.a">
+ <!-- TODO: b/413737868 - Lower minSdkVersion to 24 once the remaining GMS Core
+ targets are supported. -->
+ <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="34" />
+
<application android:label="App A [v2]">
- <activity android:name="com.android.cts.appsearch.helper.MainActivity"
+ <activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -27,7 +33,7 @@
</activity>
<service
- android:name="com.android.cts.appsearch.helper.AppFunctionService"
+ android:name=".AppFunctionService"
android:exported="true">
<property
android:name="android.app.appfunctions"
@@ -37,4 +43,4 @@
</intent-filter>
</service>
</application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/appsearch/src/com/android/cts/appsearch/appindexer/AppIndexerCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/appsindexer/AppFunctionCtsTest.java
similarity index 70%
rename from tests/appsearch/src/com/android/cts/appsearch/appindexer/AppIndexerCtsTest.java
rename to tests/appsearch/src/com/android/cts/appsearch/appsindexer/AppFunctionCtsTest.java
index 9dadd4f3..cd79915 100644
--- a/tests/appsearch/src/com/android/cts/appsearch/appindexer/AppIndexerCtsTest.java
+++ b/tests/appsearch/src/com/android/cts/appsearch/appsindexer/AppFunctionCtsTest.java
@@ -13,41 +13,57 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.app.appsearch.cts.appindexer;
+package android.app.appsearch.cts.appsindexer;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PRINT_APP_FUNCTION;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_COMMON_SCHEMA_METADATA;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PRINT_APP_FUNCTION;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_A_DYNAMIC_SCHEMA_PRINT_APP_FUNCTION;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_A_V2_PRINT_APP_FUNCTION;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_B_DYNAMIC_SCHEMA_PRINT_APP_FUNCTION;
-import static android.app.appsearch.testutil.AppFunctionConstants.APP_B_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_COMMON_SCHEMA_METADATA;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_A_DYNAMIC_SCHEMA_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_A_V2_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_B_DYNAMIC_SCHEMA_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_B_PRINT_APP_FUNCTION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_DISPLAY_NAME_STRING_RES;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_ENABLED_BY_DEFAULT;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_FUNCTION_ID;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_PACKAGE_NAME;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_RESTRICT_CALLERS_WITH_EXECUTE_APP_FUNCTIONS;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_SCHEMA_CATEGORY;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_SCHEMA_NAME;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.PROPERTY_SCHEMA_VERSION;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_APP_FUNCTION_SERVICE_DISABLED;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_DYNAMIC_SCHEMA_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_PKG;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_V1_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_V2_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_V3_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_B_DYNAMIC_SCHEMA_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_B_PKG;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_B_V1_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.clearTimestampsAndParentTypesInDocument;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.installPackage;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.retryAssert;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.searchAppFunctionDocumentsIntoMap;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.searchAppFunctionsWithPackageName;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.searchMobileApplicationWithId;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.uninstallPackage;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.updateAppFunctionServiceEnabledState;
import static com.google.common.truth.Truth.assertThat;
-import android.Manifest;
import android.app.appsearch.GenericDocument;
-import android.app.appsearch.GlobalSearchSessionShim;
-import android.app.appsearch.SearchResult;
-import android.app.appsearch.SearchResultsShim;
-import android.app.appsearch.SearchSpec;
import android.app.appsearch.testutil.AppSearchTestUtils;
-import android.app.appsearch.testutil.GlobalSearchSessionShimImpl;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
-import android.util.ArrayMap;
-import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SdkSuppress;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.appsearch.flags.Flags;
-import com.android.compatibility.common.util.SystemUtil;
import org.junit.After;
import org.junit.Before;
@@ -58,53 +74,13 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutionException;
@RequiresFlagsEnabled(Flags.FLAG_APPS_INDEXER_ENABLED)
-public class AppIndexerCtsTest {
- public static final String INDEXER_PACKAGE_NAME = "android";
+public class AppFunctionCtsTest {
@Rule public final RuleChain mRuleChain = AppSearchTestUtils.createCommonTestRules();
private final Context mContext = ApplicationProvider.getApplicationContext();
- private static final String TEST_APP_ROOT_FOLDER = "/data/local/tmp/cts/appsearch/";
- private static final String TEST_APP_A_V1_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAV1.apk";
- private static final String TEST_APP_A_V2_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAV2.apk";
- private static final String TEST_APP_A_V3_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAV3.apk";
- private static final String TEST_APP_B_V1_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppBV1.apk";
- private static final String TEST_APP_A_DYNAMIC_SCHEMA_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppADynamicSchema.apk";
- private static final String TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppADynamicSchemaFewerTypes.apk";
- private static final String TEST_APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PATH =
- TEST_APP_ROOT_FOLDER
- + "CtsAppSearchIndexerTestAppADynamicSchemaMultipleRootSchemas.apk";
- private static final String TEST_APP_B_DYNAMIC_SCHEMA_PATH =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppBDynamicSchema.apk";
-
- private static final String TEST_APP_A_APP_FUNCTION_SERVICE_DISABLED =
- TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAAppFunctionServiceDisabled.apk";
- private static final String TEST_APP_A_PKG = "com.android.cts.appsearch.indexertestapp.a";
- private static final String TEST_APP_B_PKG = "com.android.cts.appsearch.indexertestapp.b";
- private static final String NAMESPACE_MOBILE_APPLICATION = "apps";
- private static final String NAMESPACE_APP_FUNCTIONS = "app_functions";
- private static final String APP_PROPERTY_DISPLAY_NAME = "displayName";
- private static final String PROPERTY_FUNCTION_ID = "functionId";
- private static final String PROPERTY_PACKAGE_NAME = "packageName";
- private static final String PROPERTY_SCHEMA_NAME = "schemaName";
- private static final String PROPERTY_SCHEMA_VERSION = "schemaVersion";
- private static final String PROPERTY_SCHEMA_CATEGORY = "schemaCategory";
- private static final String PROPERTY_DISPLAY_NAME_STRING_RES = "displayNameStringRes";
- private static final String PROPERTY_ENABLED_BY_DEFAULT = "enabledByDefault";
- private static final String PROPERTY_RESTRICT_CALLERS_WITH_EXECUTE_APP_FUNCTIONS =
- "restrictCallersWithExecuteAppFunctions";
-
- private static final long RETRY_CHECK_INTERVAL_MILLIS = 500;
- private static final long RETRY_MAX_INTERVALS = 10;
@Before
@After
@@ -120,53 +96,10 @@
}
@Test
- public void indexMobileApplications_packageChanges() throws Throwable {
- {
- // Install a new app
- installPackage(TEST_APP_A_V1_PATH);
-
- retryAssert(
- () -> {
- GenericDocument mobileApplication =
- searchMobileApplicationWithId(TEST_APP_A_PKG);
- assertThat(mobileApplication).isNotNull();
- assertThat(mobileApplication.getPropertyString(APP_PROPERTY_DISPLAY_NAME))
- .isEqualTo("App A [v1]");
- });
- }
-
- {
- // Update it
- installPackage(TEST_APP_A_V2_PATH);
-
- retryAssert(
- () -> {
- GenericDocument mobileApplication =
- searchMobileApplicationWithId(TEST_APP_A_PKG);
- assertThat(mobileApplication).isNotNull();
- assertThat(mobileApplication.getPropertyString(APP_PROPERTY_DISPLAY_NAME))
- .isEqualTo("App A [v2]");
- });
- }
-
- {
- // Uninstall it
- uninstallPackage(TEST_APP_A_PKG);
-
- retryAssert(
- () -> {
- GenericDocument mobileApplication =
- searchMobileApplicationWithId(TEST_APP_A_PKG);
- assertThat(mobileApplication).isNull();
- });
- }
- }
-
- @Test
public void indexAppFunctions_packageChanges() throws Throwable {
{
// Install A V1 which does not have app functions.
- installPackage(TEST_APP_A_V1_PATH);
+ installPackage(mContext, TEST_APP_A_V1_PATH);
retryAssert(
() -> {
@@ -178,7 +111,7 @@
{
// Update to v2 which has one app function
- installPackage(TEST_APP_A_V2_PATH);
+ installPackage(mContext, TEST_APP_A_V2_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctions =
@@ -194,7 +127,7 @@
{
// Update to v3 which no longer has print1 but has print2 and print3.
- installPackage(TEST_APP_A_V3_PATH);
+ installPackage(mContext, TEST_APP_A_V3_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctions =
@@ -231,7 +164,7 @@
public void indexAppFunctions_fullXml() throws Throwable {
// The XML in A v2 has the full XML which specifies all the properties. Here we verify
// all the properties are being indexed properly.
- installPackage(TEST_APP_A_V2_PATH);
+ installPackage(mContext, TEST_APP_A_V2_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctions =
@@ -262,7 +195,7 @@
public void indexAppFunctions_defaultValue() throws Throwable {
// The XML in B V1 only have functionId, schema_name, schema_version and schema_category.
// Here, we check the default value of the optional properties are set properly.
- installPackage(TEST_APP_B_V1_PATH);
+ installPackage(mContext, TEST_APP_B_V1_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctions =
@@ -285,7 +218,7 @@
throws Throwable {
// Install the test app B V1 which has one app function. That function should be indexed.
{
- installPackage(TEST_APP_B_V1_PATH);
+ installPackage(mContext, TEST_APP_B_V1_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctions =
@@ -300,7 +233,7 @@
// Install test app A v1 which does not have any app function. The functions from B
// should be retained.
{
- installPackage(TEST_APP_A_V1_PATH);
+ installPackage(mContext, TEST_APP_A_V1_PATH);
retryAssert(
() -> {
// Ensure the app A is indexed before checking if the function is retained.
@@ -324,7 +257,7 @@
public void indexAppFunctionsFromTwoApps() throws Throwable {
// Install the test app B V1 which has one app function. That function should be indexed.
{
- installPackage(TEST_APP_B_V1_PATH);
+ installPackage(mContext, TEST_APP_B_V1_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctions =
@@ -339,7 +272,7 @@
// Install test app A v2 which also has one app function. The function from B should be
// retained and the new function from A should be indexed.
{
- installPackage(TEST_APP_A_V2_PATH);
+ installPackage(mContext, TEST_APP_A_V2_PATH);
retryAssert(
() -> {
List<GenericDocument> appFunctionsFromB =
@@ -363,7 +296,7 @@
public void indexMobileApplicationAndAppFunction_withoutLauncherIcon() throws Throwable {
{
// Install B V1 which does not have a launcher icon but have app functions.
- installPackage(TEST_APP_B_V1_PATH);
+ installPackage(mContext, TEST_APP_B_V1_PATH);
retryAssert(
() -> {
@@ -388,7 +321,7 @@
@Test
public void indexAppWithDynamicSchema_dynamicSchemasDisabled_indexesPredefinedSchemaFieldsOnly()
throws Throwable {
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -411,7 +344,7 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test
public void indexAppWithDynamicSchema() throws Throwable {
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -434,7 +367,7 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test
public void indexAppWithDynamicSchema_multipleRootSchemas() throws Throwable {
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -463,8 +396,8 @@
@Test
public void indexMultipleAppsWithDynamicSchema() throws Throwable {
- installPackage(TEST_APP_B_DYNAMIC_SCHEMA_PATH);
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_B_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
retryAssert(
() -> {
@@ -495,8 +428,8 @@
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test
public void indexAppsWithAndWithoutDynamicSchema() throws Throwable {
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
- installPackage(TEST_APP_B_V1_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_B_V1_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -525,7 +458,7 @@
@Test
public void indexApp_updateToDynamicSchema() throws Throwable {
{
- installPackage(TEST_APP_A_V2_PATH);
+ installPackage(mContext, TEST_APP_A_V2_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -544,7 +477,7 @@
}
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -568,7 +501,7 @@
@Test
public void indexApp_updateToWithoutDynamicSchema() throws Throwable {
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -589,7 +522,7 @@
}
{
- installPackage(TEST_APP_A_V2_PATH);
+ installPackage(mContext, TEST_APP_A_V2_PATH);
// Retry till the indexer has completed another run.
retryAssert(
@@ -612,7 +545,7 @@
@Test
public void indexApp_updateToDynamicSchemaWithFewerTypes() throws Throwable {
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -633,7 +566,7 @@
}
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH);
// Retry till the indexer has completed another run.
retryAssert(
@@ -656,7 +589,7 @@
@Test
public void indexApp_updateToDynamicSchemaWithMoreTypesThanBefore() throws Throwable {
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -677,7 +610,7 @@
}
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed another run.
retryAssert(
@@ -700,8 +633,8 @@
@Test
public void indexApp_appFunctionServiceEnabledInRuntime_functionsIndexed() throws Throwable {
{
- installPackage(TEST_APP_A_APP_FUNCTION_SERVICE_DISABLED);
- installPackage(TEST_APP_B_V1_PATH);
+ installPackage(mContext, TEST_APP_A_APP_FUNCTION_SERVICE_DISABLED);
+ installPackage(mContext, TEST_APP_B_V1_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -719,7 +652,7 @@
{
updateAppFunctionServiceEnabledState(
- TEST_APP_A_PKG, PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+ mContext, TEST_APP_A_PKG, PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
// Retry till the indexer has completed another run.
retryAssert(
@@ -732,28 +665,12 @@
}
}
- private void updateAppFunctionServiceEnabledState(String packageName, int newState) {
- InstrumentationRegistry.getInstrumentation()
- .getUiAutomation()
- .adoptShellPermissionIdentity(Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
-
- mContext.getPackageManager()
- .setComponentEnabledSetting(
- new ComponentName(
- packageName, "com.android.cts.appsearch.helper.AppFunctionService"),
- newState,
- /* flags= */ 0);
- InstrumentationRegistry.getInstrumentation()
- .getUiAutomation()
- .dropShellPermissionIdentity();
- }
-
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_INDEXER_RUN_ON_APP_FUNCTION_COMPONENT_CHANGE)
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@Test
public void indexApp_appFunctionServiceDisabledInRuntime_functionsRemoved() throws Throwable {
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -767,7 +684,7 @@
{
updateAppFunctionServiceEnabledState(
- TEST_APP_A_PKG, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+ mContext, TEST_APP_A_PKG, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
// Retry till the indexer has completed another run.
retryAssert(
@@ -787,7 +704,7 @@
indexApp_compChangeFlagDisabled_appFunctionServiceDisabledInRuntime_functionNotRemoved()
throws Throwable {
{
- installPackage(TEST_APP_A_DYNAMIC_SCHEMA_PATH);
+ installPackage(mContext, TEST_APP_A_DYNAMIC_SCHEMA_PATH);
// Retry till the indexer has completed a run.
retryAssert(
@@ -801,7 +718,7 @@
{
updateAppFunctionServiceEnabledState(
- TEST_APP_A_PKG, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
+ mContext, TEST_APP_A_PKG, PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
// Retry till the indexer has completed another run.
retryAssert(
@@ -814,127 +731,4 @@
});
}
}
-
- private GenericDocument clearTimestampsAndParentTypesInDocument(
- @NonNull GenericDocument document) {
- GenericDocument.Builder<?> builder =
- new GenericDocument.Builder<>(document)
- .setCreationTimestampMillis(0)
- // GenericDocument#PARENT_TYPES_SYNTHETIC_PROPERTY is hidden
- .clearProperty("$$__AppSearch__parentTypes");
-
- for (String propertyName : document.getPropertyNames()) {
- Object property = document.getProperty(propertyName);
- if (property instanceof GenericDocument[] nestedDocuments) {
- GenericDocument[] clearedNestedDocuments =
- new GenericDocument[nestedDocuments.length];
-
- for (int i = 0; i < nestedDocuments.length; i++) {
- clearedNestedDocuments[i] =
- clearTimestampsAndParentTypesInDocument(nestedDocuments[i]);
- }
-
- builder.setPropertyDocument(propertyName, clearedNestedDocuments);
- }
- }
-
- return builder.build();
- }
-
- private GenericDocument searchMobileApplicationWithId(String id)
- throws ExecutionException, InterruptedException {
- GlobalSearchSessionShim globalSearchSession =
- GlobalSearchSessionShimImpl.createGlobalSearchSessionAsync().get();
-
- SearchResultsShim searchResults =
- globalSearchSession.search(
- "",
- new SearchSpec.Builder()
- .addFilterNamespaces(NAMESPACE_MOBILE_APPLICATION)
- .addFilterPackageNames(INDEXER_PACKAGE_NAME)
- .build());
- List<GenericDocument> genericDocuments = collectAllResults(searchResults);
- for (int i = 0; i < genericDocuments.size(); i++) {
- GenericDocument genericDocument = genericDocuments.get(i);
- if (genericDocument.getId().equals(id)) {
- return genericDocument;
- }
- }
- return null;
- }
-
- private List<GenericDocument> searchAppFunctionsWithPackageName(String packageName)
- throws ExecutionException, InterruptedException {
- GlobalSearchSessionShim globalSearchSession =
- GlobalSearchSessionShimImpl.createGlobalSearchSessionAsync().get();
-
- SearchResultsShim searchResults =
- globalSearchSession.search(
- String.format("packageName:\"%s\"", packageName),
- new SearchSpec.Builder()
- .addFilterNamespaces(NAMESPACE_APP_FUNCTIONS)
- .addFilterPackageNames(INDEXER_PACKAGE_NAME)
- .setVerbatimSearchEnabled(true)
- .build());
- return collectAllResults(searchResults);
- }
-
- private Map<String, GenericDocument> searchAppFunctionDocumentsIntoMap(String packageName)
- throws ExecutionException, InterruptedException {
- Map<String, GenericDocument> appFns = new ArrayMap<>();
- for (GenericDocument document : searchAppFunctionsWithPackageName(packageName)) {
- appFns.put(document.getId(), document);
- }
-
- return appFns;
- }
-
- private List<GenericDocument> collectAllResults(SearchResultsShim searchResults)
- throws ExecutionException, InterruptedException {
- List<GenericDocument> documents = new ArrayList<>();
- List<SearchResult> results;
- do {
- results = searchResults.getNextPageAsync().get();
- for (SearchResult result : results) {
- documents.add(result.getGenericDocument());
- }
- } while (results.size() > 0);
- return documents;
- }
-
- private void installPackage(@NonNull String path) {
- assertThat(
- SystemUtil.runShellCommand(
- String.format(
- "pm install -r -i %s -t -g %s",
- mContext.getPackageName(), path)))
- .isEqualTo("Success\n");
- }
-
- private void uninstallPackage(@NonNull String packageName) {
- SystemUtil.runShellCommand("pm uninstall " + packageName);
- }
-
- /** Retries an assertion with a delay between attempts. */
- private static void retryAssert(ThrowRunnable runnable) throws Throwable {
- Throwable lastError = null;
-
- for (int attempt = 0; attempt < RETRY_MAX_INTERVALS; attempt++) {
- try {
- runnable.run();
- return;
- } catch (Throwable e) {
- lastError = e;
- if (attempt < RETRY_MAX_INTERVALS) {
- Thread.sleep(RETRY_CHECK_INTERVAL_MILLIS);
- }
- }
- }
- throw lastError;
- }
-
- /** Runnable that throws. */
- public interface ThrowRunnable {
- void run() throws Throwable;
- }
}
diff --git a/tests/appsearch/src/com/android/cts/appsearch/appsindexer/AppsIndexerCtsTest.java b/tests/appsearch/src/com/android/cts/appsearch/appsindexer/AppsIndexerCtsTest.java
new file mode 100644
index 0000000..4afdb15
--- /dev/null
+++ b/tests/appsearch/src/com/android/cts/appsearch/appsindexer/AppsIndexerCtsTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 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 android.app.appsearch.cts.appsindexer;
+
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.APP_PROPERTY_DISPLAY_NAME;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_PKG;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_V1_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.TEST_APP_A_V2_PATH;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.installPackage;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.retryAssert;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.searchMobileApplicationWithId;
+import static android.app.appsearch.testutil.AppsIndexerTestUtils.uninstallPackage;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.testutil.AppSearchTestUtils;
+import android.content.Context;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.appsearch.flags.Flags;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+
+@RequiresFlagsEnabled(Flags.FLAG_APPS_INDEXER_ENABLED)
+public class AppsIndexerCtsTest {
+
+ @Rule public final RuleChain mRuleChain = AppSearchTestUtils.createCommonTestRules();
+
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+
+ @Before
+ @After
+ public void uninstallTestApks() throws Throwable {
+ uninstallPackage(TEST_APP_A_PKG);
+
+ retryAssert(
+ () -> {
+ assertThat(searchMobileApplicationWithId(TEST_APP_A_PKG)).isNull();
+ });
+ }
+
+ @Test
+ public void indexMobileApplications_packageChanges() throws Throwable {
+ {
+ // Install a new app
+ installPackage(mContext, TEST_APP_A_V1_PATH);
+
+ retryAssert(
+ () -> {
+ GenericDocument mobileApplication =
+ searchMobileApplicationWithId(TEST_APP_A_PKG);
+ assertThat(mobileApplication).isNotNull();
+ assertThat(mobileApplication.getPropertyString(APP_PROPERTY_DISPLAY_NAME))
+ .isEqualTo("App A [v1]");
+ });
+ }
+
+ {
+ // Update it
+ installPackage(mContext, TEST_APP_A_V2_PATH);
+
+ retryAssert(
+ () -> {
+ GenericDocument mobileApplication =
+ searchMobileApplicationWithId(TEST_APP_A_PKG);
+ assertThat(mobileApplication).isNotNull();
+ assertThat(mobileApplication.getPropertyString(APP_PROPERTY_DISPLAY_NAME))
+ .isEqualTo("App A [v2]");
+ });
+ }
+
+ {
+ // Uninstall it
+ uninstallPackage(TEST_APP_A_PKG);
+
+ retryAssert(
+ () -> {
+ GenericDocument mobileApplication =
+ searchMobileApplicationWithId(TEST_APP_A_PKG);
+ assertThat(mobileApplication).isNull();
+ });
+ }
+ }
+}
diff --git a/tests/appsearch/testutils/Android.bp b/tests/appsearch/testutils/Android.bp
index 3a67c7a..3b03650 100644
--- a/tests/appsearch/testutils/Android.bp
+++ b/tests/appsearch/testutils/Android.bp
@@ -26,13 +26,14 @@
libs: [
"androidx.test.ext.junit",
"appsearch_flags_java_lib",
+ "compatibility-device-util-axt",
"framework-annotations-lib",
"framework-appsearch.impl",
"guava",
"service-appsearch-for-tests",
"truth",
],
- sdk_version: "system_server_current",
+ platform_apis: true,
visibility: [
"//cts/hostsidetests/appsearch",
"//cts/tests:__subpackages__",
diff --git a/tests/appsearch/testutils/src/android/app/appsearch/testutil/AppFunctionConstants.java b/tests/appsearch/testutils/src/android/app/appsearch/testutil/AppsIndexerTestUtils.java
similarity index 63%
rename from tests/appsearch/testutils/src/android/app/appsearch/testutil/AppFunctionConstants.java
rename to tests/appsearch/testutils/src/android/app/appsearch/testutil/AppsIndexerTestUtils.java
index 92379b4..389dad6 100644
--- a/tests/appsearch/testutils/src/android/app/appsearch/testutil/AppFunctionConstants.java
+++ b/tests/appsearch/testutils/src/android/app/appsearch/testutil/AppsIndexerTestUtils.java
@@ -16,13 +16,71 @@
package android.app.appsearch.testutil;
-import android.app.appsearch.GenericDocument;
+import static com.google.common.truth.Truth.assertThat;
-/** Constants for AppFunction indexer tests. */
-public final class AppFunctionConstants {
+import android.Manifest;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GlobalSearchSessionShim;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchResultsShim;
+import android.app.appsearch.SearchSpec;
+import android.content.ComponentName;
+import android.content.Context;
+import android.util.ArrayMap;
+
+import androidx.annotation.NonNull;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.SystemUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+
+/** Utility class providing constants and helper methods for AppsIndexer tests. */
+public final class AppsIndexerTestUtils {
+ private static final String INDEXER_PACKAGE_NAME = "android";
+ private static final String TEST_APP_ROOT_FOLDER = "/data/local/tmp/cts/appsearch/";
+ private static final String NAMESPACE_MOBILE_APPLICATION = "apps";
private static final String NAMESPACE_APP_FUNCTIONS = "app_functions";
- private static final String TEST_APP_A_PKG = "com.android.cts.appsearch.indexertestapp.a";
- private static final String TEST_APP_B_PKG = "com.android.cts.appsearch.indexertestapp.b";
+
+ private static final long RETRY_CHECK_INTERVAL_MILLIS = 500;
+ private static final long RETRY_MAX_INTERVALS = 10;
+
+ public static final String TEST_APP_A_V1_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAV1.apk";
+ public static final String TEST_APP_A_V2_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAV2.apk";
+ public static final String TEST_APP_A_V3_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAV3.apk";
+ public static final String TEST_APP_B_V1_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppBV1.apk";
+ public static final String TEST_APP_A_DYNAMIC_SCHEMA_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppADynamicSchema.apk";
+ public static final String TEST_APP_A_DYNAMIC_SCHEMA_FEWER_TYPES_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppADynamicSchemaFewerTypes.apk";
+ public static final String TEST_APP_A_DYNAMIC_SCHEMA_MULTIPLE_ROOT_SCHEMAS_PATH =
+ TEST_APP_ROOT_FOLDER
+ + "CtsAppSearchIndexerTestAppADynamicSchemaMultipleRootSchemas.apk";
+ public static final String TEST_APP_B_DYNAMIC_SCHEMA_PATH =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppBDynamicSchema.apk";
+ public static final String TEST_APP_A_APP_FUNCTION_SERVICE_DISABLED =
+ TEST_APP_ROOT_FOLDER + "CtsAppSearchIndexerTestAppAAppFunctionServiceDisabled.apk";
+
+ public static final String TEST_APP_A_PKG = "com.android.cts.appsearch.indexertestapp.a";
+ public static final String TEST_APP_B_PKG = "com.android.cts.appsearch.indexertestapp.b";
+
+ public static final String APP_PROPERTY_DISPLAY_NAME = "displayName";
+ public static final String PROPERTY_FUNCTION_ID = "functionId";
+ public static final String PROPERTY_PACKAGE_NAME = "packageName";
+ public static final String PROPERTY_SCHEMA_NAME = "schemaName";
+ public static final String PROPERTY_SCHEMA_VERSION = "schemaVersion";
+ public static final String PROPERTY_SCHEMA_CATEGORY = "schemaCategory";
+ public static final String PROPERTY_DISPLAY_NAME_STRING_RES = "displayNameStringRes";
+ public static final String PROPERTY_ENABLED_BY_DEFAULT = "enabledByDefault";
+ public static final String PROPERTY_RESTRICT_CALLERS_WITH_EXECUTE_APP_FUNCTIONS =
+ "restrictCallersWithExecuteAppFunctions";
/** Print app function generic document as defined in the appfunctions.xml of App A V2. */
public static final GenericDocument APP_A_V2_PRINT_APP_FUNCTION =
@@ -120,6 +178,148 @@
public static final GenericDocument APP_B_DYNAMIC_SCHEMA_PRINT_APP_FUNCTION =
buildPrintAppFunctionDocument(TEST_APP_B_PKG);
+ /** Updates the enabled state of the AppFunctionService for a given package. */
+ public static void updateAppFunctionServiceEnabledState(
+ Context context, String packageName, int newState) {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity(Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
+
+ context.getPackageManager()
+ .setComponentEnabledSetting(
+ new ComponentName(
+ packageName, "com.android.cts.appsearch.helper.AppFunctionService"),
+ newState,
+ /* flags= */ 0);
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ /** Recursively removes timestamps and parent types from a document. */
+ public static GenericDocument clearTimestampsAndParentTypesInDocument(
+ @NonNull GenericDocument document) {
+ GenericDocument.Builder<?> builder =
+ new GenericDocument.Builder<>(document)
+ .setCreationTimestampMillis(0)
+ // GenericDocument#PARENT_TYPES_SYNTHETIC_PROPERTY is hidden
+ .clearProperty("$$__AppSearch__parentTypes");
+
+ for (String propertyName : document.getPropertyNames()) {
+ Object property = document.getProperty(propertyName);
+ if (property instanceof GenericDocument[] nestedDocuments) {
+ GenericDocument[] clearedNestedDocuments =
+ new GenericDocument[nestedDocuments.length];
+
+ for (int i = 0; i < nestedDocuments.length; i++) {
+ clearedNestedDocuments[i] =
+ clearTimestampsAndParentTypesInDocument(nestedDocuments[i]);
+ }
+
+ builder.setPropertyDocument(propertyName, clearedNestedDocuments);
+ }
+ }
+
+ return builder.build();
+ }
+
+ /** Queries GlobalSearchSession for a MobileApplication by its document ID. */
+ public static GenericDocument searchMobileApplicationWithId(String id)
+ throws ExecutionException, InterruptedException {
+ GlobalSearchSessionShim globalSearchSession =
+ GlobalSearchSessionShimImpl.createGlobalSearchSessionAsync().get();
+
+ SearchResultsShim searchResults =
+ globalSearchSession.search(
+ "",
+ new SearchSpec.Builder()
+ .addFilterNamespaces(NAMESPACE_MOBILE_APPLICATION)
+ .addFilterPackageNames(INDEXER_PACKAGE_NAME)
+ .build());
+ List<GenericDocument> genericDocuments = collectAllResults(searchResults);
+ for (int i = 0; i < genericDocuments.size(); i++) {
+ GenericDocument genericDocument = genericDocuments.get(i);
+ if (genericDocument.getId().equals(id)) {
+ return genericDocument;
+ }
+ }
+ return null;
+ }
+
+ /** Queries GlobalSearchSession for AppFunction documents by package name. */
+ public static List<GenericDocument> searchAppFunctionsWithPackageName(String packageName)
+ throws ExecutionException, InterruptedException {
+ GlobalSearchSessionShim globalSearchSession =
+ GlobalSearchSessionShimImpl.createGlobalSearchSessionAsync().get();
+
+ SearchResultsShim searchResults =
+ globalSearchSession.search(
+ String.format("packageName:\"%s\"", packageName),
+ new SearchSpec.Builder()
+ .addFilterNamespaces(NAMESPACE_APP_FUNCTIONS)
+ .addFilterPackageNames(INDEXER_PACKAGE_NAME)
+ .setVerbatimSearchEnabled(true)
+ .build());
+ return collectAllResults(searchResults);
+ }
+
+ /** Returns a map of AppFunction documents for a package name keyed by the document ID. */
+ public static Map<String, GenericDocument> searchAppFunctionDocumentsIntoMap(String packageName)
+ throws ExecutionException, InterruptedException {
+ Map<String, GenericDocument> appFns = new ArrayMap<>();
+ for (GenericDocument document : searchAppFunctionsWithPackageName(packageName)) {
+ appFns.put(document.getId(), document);
+ }
+
+ return appFns;
+ }
+
+ /** Installs an APK from a given path and asserts success. */
+ public static void installPackage(@NonNull Context context, @NonNull String path) {
+ assertThat(
+ SystemUtil.runShellCommand(
+ String.format(
+ "pm install -r -i %s -t -g %s",
+ context.getPackageName(), path)))
+ .isEqualTo("Success\n");
+ }
+
+ /** Uninstalls an Android package by package name. */
+ public static void uninstallPackage(@NonNull String packageName) {
+ SystemUtil.runShellCommand("pm uninstall " + packageName);
+ }
+
+ /** Retries an assertion with a delay between attempts. */
+ public static void retryAssert(ThrowRunnable runnable) throws Throwable {
+ Throwable lastError = null;
+
+ for (int attempt = 0; attempt < RETRY_MAX_INTERVALS; attempt++) {
+ try {
+ runnable.run();
+ return;
+ } catch (Throwable e) {
+ lastError = e;
+ if (attempt < RETRY_MAX_INTERVALS) {
+ Thread.sleep(RETRY_CHECK_INTERVAL_MILLIS);
+ }
+ }
+ }
+ throw lastError;
+ }
+
+ private static List<GenericDocument> collectAllResults(SearchResultsShim searchResults)
+ throws ExecutionException, InterruptedException {
+ List<GenericDocument> documents = new ArrayList<>();
+ List<SearchResult> results;
+ do {
+ results = searchResults.getNextPageAsync().get();
+ for (SearchResult result : results) {
+ documents.add(result.getGenericDocument());
+ }
+ } while (!results.isEmpty());
+ return documents;
+ }
+
/**
* Builds the generic document for print app function defined in app A with dynamic schema.
*
@@ -294,7 +494,8 @@
new GenericDocument.Builder<>(
NAMESPACE_APP_FUNCTIONS,
packageName
- + "/com.example.utils#print/response/schema/properties0/schema",
+ + "/com.example.utils#print/response"
+ + "/schema/properties0/schema",
"AppFunctionSchema-" + packageName)
.setCreationTimestampMillis(0)
.setPropertyLong("dataType", 8)
@@ -338,7 +539,8 @@
new GenericDocument.Builder<>(
NAMESPACE_APP_FUNCTIONS,
packageName
- + "/com.example.utils#print/components0/schema/properties0/schema",
+ + "/com.example.utils#print/components0"
+ + "/schema/properties0/schema",
"AppFunctionSchema-" + packageName)
.setCreationTimestampMillis(0)
.setPropertyLong("dataType", 8)
@@ -381,5 +583,11 @@
return builder.build();
}
- private AppFunctionConstants() {}
+ /** Runnable that throws. */
+ public interface ThrowRunnable {
+ /** Executes the action. */
+ void run() throws Throwable;
+ }
+
+ private AppsIndexerTestUtils() {}
}