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

Commit 97844f31 authored by Terry Wang's avatar Terry Wang
Browse files

Add background executor to AppSearchManagerService.

The background executor could release binder thread earlier and
reduce work load of binder threads.

Bug: 173451571
Test: presubmit
Change-Id: I2ca247c8c396095f6975c335cf8327b0792ae956
parent 02841faa
Loading
Loading
Loading
Loading
+330 −330
Original line number Diff line number Diff line
@@ -68,6 +68,10 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/** TODO(b/142567528): add comments when implement this class */
public class AppSearchManagerService extends SystemService {
@@ -77,6 +81,14 @@ public class AppSearchManagerService extends SystemService {
    private ImplInstanceManager mImplInstanceManager;
    private UserManager mUserManager;

    // Never call shutdownNow(). It will cancel the futures it's returned. And since
    // Executor#execute won't return anything, we will hang forever waiting for the execution.
    // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
    // mutate requests will need to gain write lock and query requests need to gain read lock.
    private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
            Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
            new SynchronousQueue<Runnable>());

    // Cache of unlocked user ids so we don't have to query UserManager service each time. The
    // "locked" suffix refers to the fact that access to the field should be locked; unrelated to
    // the unlocked status of user ids.
@@ -166,7 +178,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -181,7 +193,8 @@ public class AppSearchManagerService extends SystemService {
                        List<PackageIdentifier> packageIdentifiers =
                                new ArrayList<>(entry.getValue().size());
                        for (int i = 0; i < entry.getValue().size(); i++) {
                        packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
                            packageIdentifiers.add(
                                    new PackageIdentifier(entry.getValue().get(i)));
                        }
                        schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
                    }
@@ -198,9 +211,8 @@ public class AppSearchManagerService extends SystemService {
                            AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -214,7 +226,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -222,12 +234,12 @@ public class AppSearchManagerService extends SystemService {
                            mImplInstanceManager.getAppSearchImpl(callingUserId);
                    GetSchemaResponse response = impl.getSchema(packageName, databaseName);
                    invokeCallbackOnResult(
                        callback, AppSearchResult.newSuccessfulResult(response.getBundle()));
                            callback,
                            AppSearchResult.newSuccessfulResult(response.getBundle()));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -241,19 +253,19 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
                    AppSearchImpl impl =
                            mImplInstanceManager.getAppSearchImpl(callingUserId);
                    List<String> namespaces = impl.getNamespaces(packageName, databaseName);
                invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(namespaces));
                    invokeCallbackOnResult(callback,
                            AppSearchResult.newSuccessfulResult(namespaces));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -269,7 +281,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -280,20 +292,19 @@ public class AppSearchManagerService extends SystemService {
                    for (int i = 0; i < documentBundles.size(); i++) {
                        GenericDocument document = new GenericDocument(documentBundles.get(i));
                        try {
                        // TODO(b/173451571): reduce burden of binder thread by enqueue request onto
                        // a separate thread.
                        impl.putDocument(packageName, databaseName, document, /*logger=*/ null);
                            impl.putDocument(packageName, databaseName, document,
                                    /*logger=*/ null);
                            resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
                        } catch (Throwable t) {
                        resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
                            resultBuilder.setResult(document.getUri(),
                                    throwableToFailedResult(t));
                        }
                    }
                    invokeCallbackOnResult(callback, resultBuilder.build());
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -312,7 +323,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -338,12 +349,10 @@ public class AppSearchManagerService extends SystemService {
                    invokeCallbackOnResult(callback, resultBuilder.build());
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        // TODO(sidchhabra): Do this in a threadpool.
        @Override
        public void query(
                @NonNull String packageName,
@@ -359,7 +368,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -376,9 +385,8 @@ public class AppSearchManagerService extends SystemService {
                            AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -394,7 +402,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -411,9 +419,8 @@ public class AppSearchManagerService extends SystemService {
                            AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
                }  catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -424,9 +431,9 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
            // opened it
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    AppSearchImpl impl =
@@ -437,16 +444,15 @@ public class AppSearchManagerService extends SystemService {
                            AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
        public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    AppSearchImpl impl =
@@ -454,9 +460,8 @@ public class AppSearchManagerService extends SystemService {
                    impl.invalidateNextPageToken(nextPageToken);
                } catch (Throwable t) {
                    Log.e(TAG, "Unable to invalidate the query page token", t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -470,7 +475,7 @@ public class AppSearchManagerService extends SystemService {
                @NonNull IAppSearchResultCallback callback) {
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyCallingPackage(callingUid, packageName);
                    AppSearchImpl impl =
@@ -489,15 +494,15 @@ public class AppSearchManagerService extends SystemService {
                                        outputStream, searchResultPage.getResults().get(i)
                                                .getGenericDocument().getBundle());
                            }
                        searchResultPage = impl.getNextPage(searchResultPage.getNextPageToken());
                            searchResultPage = impl.getNextPage(
                                    searchResultPage.getNextPageToken());
                        }
                    }
                    invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -509,7 +514,7 @@ public class AppSearchManagerService extends SystemService {
                @NonNull IAppSearchResultCallback callback) {
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyCallingPackage(callingUid, packageName);
                    AppSearchImpl impl =
@@ -528,15 +533,16 @@ public class AppSearchManagerService extends SystemService {
                                break;
                            }
                            try {
                            impl.putDocument(packageName, databaseName, document, /*logger=*/ null);
                                impl.putDocument(packageName, databaseName, document,
                                        /*logger=*/ null);
                            } catch (Throwable t) {
                                migrationFailureBundles.add(
                                        new SetSchemaResponse.MigrationFailure.Builder()
                                                .setNamespace(document.getNamespace())
                                                .setSchemaType(document.getSchemaType())
                                                .setUri(document.getUri())
                                            .setAppSearchResult(
                                                    AppSearchResult.throwableToFailedResult(t))
                                                .setAppSearchResult(AppSearchResult
                                                        .throwableToFailedResult(t))
                                                .build().getBundle());
                            }
                        }
@@ -546,9 +552,8 @@ public class AppSearchManagerService extends SystemService {
                            AppSearchResult.newSuccessfulResult(migrationFailureBundles));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -567,7 +572,7 @@ public class AppSearchManagerService extends SystemService {
            Objects.requireNonNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);

@@ -584,9 +589,8 @@ public class AppSearchManagerService extends SystemService {
                            callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -603,7 +607,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -623,9 +627,8 @@ public class AppSearchManagerService extends SystemService {
                    invokeCallbackOnResult(callback, resultBuilder.build());
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -643,7 +646,7 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
@@ -657,9 +660,8 @@ public class AppSearchManagerService extends SystemService {
                    invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -673,28 +675,28 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    verifyCallingPackage(callingUid, packageName);
                    AppSearchImpl impl =
                            mImplInstanceManager.getAppSearchImpl(callingUserId);
                StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName, databaseName);
                    StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
                            databaseName);
                    Bundle storageInfoBundle = storageInfo.getBundle();
                    invokeCallbackOnResult(
                            callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
        public void persistToDisk(@UserIdInt int userId) {
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    AppSearchImpl impl =
@@ -702,9 +704,8 @@ public class AppSearchManagerService extends SystemService {
                    impl.persistToDisk();
                } catch (Throwable t) {
                    Log.e(TAG, "Unable to persist the data to disk", t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        @Override
@@ -712,16 +713,15 @@ public class AppSearchManagerService extends SystemService {
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUid();
            int callingUserId = handleIncomingUser(userId, callingUid);
            final long callingIdentity = Binder.clearCallingIdentity();
            EXECUTOR.execute(() -> {
                try {
                    verifyUserUnlocked(callingUserId);
                    mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
                    invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
                } catch (Throwable t) {
                    invokeCallbackOnError(callback, t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
                }
            });
        }

        private void verifyUserUnlocked(int callingUserId) {