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

Commit b95b3b96 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add retry to mitigate the pagination issue" into main

parents fb252b43 44712fea
Loading
Loading
Loading
Loading
+71 −10
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
@@ -71,6 +72,9 @@ public class MetadataSyncAdapter {
    private final AppSearchManager mAppSearchManager;
    private final PackageManager mPackageManager;
    private final Object mLock = new Object();
    private static final int DEFAULT_RESULT_COUNT_PER_PAGE =
            new SearchSpec.Builder().build().getResultCountPerPage();
    private static final int RETRY_RESULT_COUNT_PER_PAGE = 200;

    @GuardedBy("mLock")
    private Future<?> mCurrentSyncTask;
@@ -148,13 +152,13 @@ public class MetadataSyncAdapter {
            @NonNull FutureAppSearchSession runtimeMetadataSearchSession)
            throws ExecutionException, InterruptedException {
        ArrayMap<String, ArraySet<String>> staticPackageToFunctionMap =
                getPackageToFunctionIdMap(
                getPackageToFunctionIdMapWithRetry(
                        staticMetadataSearchSession,
                        AppFunctionStaticMetadataHelper.STATIC_SCHEMA_TYPE,
                        AppFunctionStaticMetadataHelper.PROPERTY_FUNCTION_ID,
                        AppFunctionStaticMetadataHelper.PROPERTY_PACKAGE_NAME);
        ArrayMap<String, ArraySet<String>> runtimePackageToFunctionMap =
                getPackageToFunctionIdMap(
                getPackageToFunctionIdMapWithRetry(
                        runtimeMetadataSearchSession,
                        RUNTIME_SCHEMA_TYPE,
                        AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID,
@@ -395,6 +399,51 @@ public class MetadataSyncAdapter {
        return diffMap;
    }


    /**
     * This method returns a map of package names to a set of function ids from the AppFunction
     * metadata.
     *
     * @param searchSession The {@link FutureAppSearchSession} to search the AppFunction metadata.
     * @param schemaType The schema type of the AppFunction metadata.
     * @param propertyFunctionId The property name of the function id in the AppFunction metadata.
     * @param propertyPackageName The property name of the package name in the AppFunction metadata.
     * @return A map of package names to a set of function ids from the AppFunction metadata.
     */
    @NonNull
    @VisibleForTesting
    @WorkerThread
    static ArrayMap<String, ArraySet<String>> getPackageToFunctionIdMapWithRetry(
            @NonNull FutureAppSearchSession searchSession,
            @NonNull String schemaType,
            @NonNull String propertyFunctionId,
            @NonNull String propertyPackageName) throws ExecutionException, InterruptedException {
        ArrayMap<String, ArraySet<String>> packageToFunctionIdMap = getPackageToFunctionIdMap(
                searchSession, schemaType, propertyFunctionId,
                propertyPackageName, DEFAULT_RESULT_COUNT_PER_PAGE);
        int functionIdCount = countTotalStringsInValueSets(packageToFunctionIdMap);
        if (functionIdCount == DEFAULT_RESULT_COUNT_PER_PAGE) {
            // We might run into b/400670498 where only the first page is returned while there
            // are more. This could be a false positive if we happen to have
            // DEFAULT_RESULT_COUNT_PER_PAGE AppFunctions. Retry with a higher page count.
            Slog.d(TAG,
                    "b/400587895: getPackageToFunctionIdMapWithRetry is retrying for schemaType = "
                            + schemaType);
            packageToFunctionIdMap = getPackageToFunctionIdMap(
                    searchSession, schemaType, propertyFunctionId,
                    propertyPackageName, RETRY_RESULT_COUNT_PER_PAGE);
            int retryFunctionIdCount = countTotalStringsInValueSets(packageToFunctionIdMap);
            if (retryFunctionIdCount != DEFAULT_RESULT_COUNT_PER_PAGE) {
                // This is likely we did hit the bug. But if the diff is small, it could be
                // just there were indeed changes in # of app functions during the two searches.
                Slog.d(TAG, "b/400587895: First search yields " + functionIdCount
                        + " results, but the second one with higher page size yields "
                        + retryFunctionIdCount + " results. schemaType = " + schemaType);
            }
        }
        return packageToFunctionIdMap;
    }

    /**
     * This method returns a map of package names to a set of function ids from the AppFunction
     * metadata.
@@ -412,7 +461,8 @@ public class MetadataSyncAdapter {
            @NonNull FutureAppSearchSession searchSession,
            @NonNull String schemaType,
            @NonNull String propertyFunctionId,
            @NonNull String propertyPackageName)
            @NonNull String propertyPackageName,
            int resultCountPerPage)
            throws ExecutionException, InterruptedException {
        Objects.requireNonNull(schemaType);
        Objects.requireNonNull(propertyFunctionId);
@@ -424,7 +474,8 @@ public class MetadataSyncAdapter {
                             .search(
                                     "",
                                     buildMetadataSearchSpec(
                                        schemaType, propertyFunctionId, propertyPackageName))
                                             schemaType, propertyFunctionId, propertyPackageName,
                                             resultCountPerPage))
                             .get();) {
            List<SearchResult> searchResultsList = futureSearchResults.getNextPage().get();
            // TODO(b/357551503): This could be expensive if we have more functions
@@ -458,12 +509,14 @@ public class MetadataSyncAdapter {
    private static SearchSpec buildMetadataSearchSpec(
            @NonNull String schemaType,
            @NonNull String propertyFunctionId,
            @NonNull String propertyPackageName) {
            @NonNull String propertyPackageName,
            int resultCountPerPage) {
        Objects.requireNonNull(schemaType);
        Objects.requireNonNull(propertyFunctionId);
        Objects.requireNonNull(propertyPackageName);
        return new SearchSpec.Builder()
                .addFilterSchemas(schemaType)
                .setResultCountPerPage(resultCountPerPage)
                .addProjectionPaths(
                        schemaType,
                        List.of(
@@ -508,4 +561,12 @@ public class MetadataSyncAdapter {
        md.update(signatures[0].toByteArray());
        return md.digest();
    }

    private static int countTotalStringsInValueSets(Map<String, ArraySet<String>> map) {
        int totalCount = 0;
        for (ArraySet<String> stringSet : map.values()) {
            totalCount += stringSet.size();
        }
        return totalCount;
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ class MetadataSyncAdapterTest {
        searchSession.put(putDocumentsRequest).get()

        val packageToFunctionIdMap =
            MetadataSyncAdapter.getPackageToFunctionIdMap(
            MetadataSyncAdapter.getPackageToFunctionIdMapWithRetry(
                searchSession,
                "fakeSchema",
                AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID,
@@ -90,7 +90,7 @@ class MetadataSyncAdapterTest {
        searchSession.put(putDocumentsRequest).get()

        val packageToFunctionIdMap =
            MetadataSyncAdapter.getPackageToFunctionIdMap(
            MetadataSyncAdapter.getPackageToFunctionIdMapWithRetry(
                searchSession,
                AppFunctionRuntimeMetadata.RUNTIME_SCHEMA_TYPE,
                AppFunctionRuntimeMetadata.PROPERTY_FUNCTION_ID,