blob: 6a4f4db5ef2461c6e022eb0b1a33240e2aa11df9 [file] [log] [blame]
Terry Wangfebbead2019-10-17 17:05:18 -07001/*
sidchhabraa7c8f8a2020-01-16 18:38:17 -08002 * Copyright (C) 2020 The Android Open Source Project
Terry Wangfebbead2019-10-17 17:05:18 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.appsearch;
17
Terry Wangdbd1dca2020-11-03 17:03:56 -080018import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
Terry Wange201dc02021-04-16 01:03:20 -070019import static android.os.Process.INVALID_UID;
Terry Wangdbd1dca2020-11-03 17:03:56 -080020
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080021import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080022import android.annotation.NonNull;
Alexander Dorokhine18465842020-01-21 01:08:57 -080023import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080024import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080025import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070026import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070027import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070028import android.app.appsearch.GetSchemaResponse;
Alexander Dorokhineab789062021-01-11 21:00:00 -080029import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070030import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070031import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080032import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070033import android.app.appsearch.StorageInfo;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070034import android.app.appsearch.aidl.AppSearchBatchResultParcel;
35import android.app.appsearch.aidl.AppSearchResultParcel;
36import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
37import android.app.appsearch.aidl.IAppSearchManager;
38import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070039import android.app.appsearch.exceptions.AppSearchException;
Terry Wang12dc6c02021-03-31 19:26:16 -070040import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070041import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070042import android.content.Intent;
43import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070044import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070045import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070046import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080047import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070048import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080049import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080050import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080051import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080052import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070053import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080054import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080055import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080056import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070057
Cassie Wang15c86972021-02-09 13:43:25 -080058import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070059import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070060import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080061import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine14816e22021-07-12 10:53:24 -070062import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070063import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Xiaoyu Jin10329472021-06-23 16:50:03 -070064import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070065import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070066import com.android.server.usage.StorageStatsManagerLocal;
67import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080068
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070069import com.google.android.icing.proto.PersistType;
70
Terry Wang623e3b02021-02-02 20:27:33 -080071import java.io.DataInputStream;
72import java.io.DataOutputStream;
73import java.io.EOFException;
74import java.io.FileInputStream;
75import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080076import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080077import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080078import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080079import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080080import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070081import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070082import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070083import java.util.concurrent.ThreadPoolExecutor;
84import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080085
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070086/**
87 * The main service implementation which contains AppSearch's platform functionality.
88 * @hide
89 */
Terry Wangfebbead2019-10-17 17:05:18 -070090public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070091 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070092 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070093 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070094 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070095 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -070096
Terry Wange04ceab2021-03-29 19:25:12 -070097 // Never call shutdownNow(). It will cancel the futures it's returned. And since
98 // Executor#execute won't return anything, we will hang forever waiting for the execution.
99 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
100 // mutate requests will need to gain write lock and query requests need to gain read lock.
101 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
102 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700103 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700104
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700105 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
106 // suffix refers to the fact that access to the field should be locked; unrelated to the
107 // unlocked status of users.
108 @GuardedBy("mUnlockedUsersLocked")
109 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800110
Terry Wangfebbead2019-10-17 17:05:18 -0700111 public AppSearchManagerService(Context context) {
112 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700113 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700114 }
115
116 @Override
117 public void onStart() {
118 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700119 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700120 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700121 mUserManager = mContext.getSystemService(UserManager.class);
122 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700123 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700124 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700125 }
126
Xiaoyu Jin10329472021-06-23 16:50:03 -0700127 @Override
128 public void onBootPhase(/* @BootPhase */ int phase) {
129 if (phase == PHASE_BOOT_COMPLETED) {
130 StatsCollector.getInstance(mContext, EXECUTOR);
131 }
132 }
133
Terry Wang12dc6c02021-03-31 19:26:16 -0700134 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700135 mContext.registerReceiverForAllUsers(
136 new UserActionReceiver(),
137 new IntentFilter(Intent.ACTION_USER_REMOVED),
138 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700139 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700140
141 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
142 // broadcasts
143 IntentFilter packageChangedFilter = new IntentFilter();
144 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
145 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
146 packageChangedFilter.addDataScheme("package");
147 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700148 mContext.registerReceiverForAllUsers(
149 new PackageChangedReceiver(),
150 packageChangedFilter,
151 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700152 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700153 }
154
155 private class UserActionReceiver extends BroadcastReceiver {
156 @Override
157 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700158 Objects.requireNonNull(context);
159 Objects.requireNonNull(intent);
160
Terry Wang12dc6c02021-03-31 19:26:16 -0700161 switch (intent.getAction()) {
162 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700163 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
164 if (userHandle == null) {
165 Log.e(TAG, "Extra "
166 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700167 return;
168 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700169 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700170 break;
171 default:
Terry Wange201dc02021-04-16 01:03:20 -0700172 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700173 }
174 }
175 }
176
177 /**
178 * Handles user removed action.
179 *
180 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
181 * "credential encrypted" system directory of each user. That directory will be auto-deleted
182 * when a user is removed.
183 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700184 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700185 *
186 * @see android.os.Environment#getDataSystemCeDirectory
187 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700188 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700189 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700190 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700191 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700192 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700193 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700194 }
195 }
196
197 private class PackageChangedReceiver extends BroadcastReceiver {
198 @Override
199 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700200 Objects.requireNonNull(context);
201 Objects.requireNonNull(intent);
202
Terry Wange201dc02021-04-16 01:03:20 -0700203 switch (intent.getAction()) {
204 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
205 case Intent.ACTION_PACKAGE_DATA_CLEARED:
206 String packageName = intent.getData().getSchemeSpecificPart();
207 if (packageName == null) {
208 Log.e(TAG, "Package name is missing in the intent: " + intent);
209 return;
210 }
211 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
212 if (uid == INVALID_UID) {
213 Log.e(TAG, "uid is missing in the intent: " + intent);
214 return;
215 }
216 handlePackageRemoved(packageName, uid);
217 break;
218 default:
219 Log.e(TAG, "Received unknown intent: " + intent);
220 }
221 }
222 }
223
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700224 private void handlePackageRemoved(@NonNull String packageName, int uid) {
225 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700226 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700227 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700228 // We cannot access a locked user's directry and remove package data from it.
229 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700230 return;
231 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700232 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700233 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700234 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700235 AppSearchUserInstance instance =
236 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700237 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700238 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700239 instance.getAppSearchImpl().clearPackageData(packageName);
240 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700241 }
242 } catch (Throwable t) {
243 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700244 }
Terry Wangfebbead2019-10-17 17:05:18 -0700245 }
246
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800247 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700248 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700249 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700250 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700251 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700252 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800253 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700254 EXECUTOR.execute(() -> {
255 try {
256 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700257 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700258 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700259 AppSearchUserInstance instance =
260 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700261 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
262 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700263 .getPackageManager()
264 .getInstalledPackages(/*flags=*/0);
265 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
266 for (int i = 0; i < installedPackageInfos.size(); i++) {
267 packagesToKeep.add(installedPackageInfos.get(i).packageName);
268 }
269 packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
270 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700271 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700272 }
273 } catch (Throwable t) {
274 Log.e(TAG, "Unable to prune packages for " + user, t);
275 }
276 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800277 }
278
Terry Wangde9f3382021-04-28 19:45:07 -0700279 @Override
280 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700281 Objects.requireNonNull(user);
282
283 synchronized (mUnlockedUsersLocked) {
284 UserHandle userHandle = user.getUserHandle();
285 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700286 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700287 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700288 } catch (Throwable t) {
289 Log.e(TAG, "Error handling user stopping.", t);
290 }
291 }
292 }
293
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700294 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
295 if (isUserLocked(callingUser)) {
296 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700297 }
298 }
299
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700300 private boolean isUserLocked(@NonNull UserHandle callingUser) {
301 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700302 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700303 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700304 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700305 }
306 // If the local copy says the user is locked, check with UM for the actual state,
307 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700308 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700309 }
310 }
311
Terry Wangfebbead2019-10-17 17:05:18 -0700312 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800313 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800314 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800315 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700316 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700317 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800318 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700319 @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800320 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700321 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700322 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700323 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800324 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700325 Objects.requireNonNull(packageName);
326 Objects.requireNonNull(databaseName);
327 Objects.requireNonNull(schemaBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700328 Objects.requireNonNull(schemasNotDisplayedBySystem);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700329 Objects.requireNonNull(schemasVisibleToPackagesBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700330 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700331 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700332
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700333 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800334 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000335 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700336 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700337 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700338 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700339 int operationSuccessCount = 0;
340 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700341 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000342 Context targetUserContext = mContext.createContextAsUser(targetUser,
343 /*flags=*/ 0);
344 verifyUserUnlocked(targetUser);
345 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
346 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
347 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
348 verifyNotInstantApp(targetUserContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700349 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
350 for (int i = 0; i < schemaBundles.size(); i++) {
351 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800352 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700353 Map<String, List<PackageIdentifier>> schemasVisibleToPackages =
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700354 new ArrayMap<>(schemasVisibleToPackagesBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700355 for (Map.Entry<String, List<Bundle>> entry :
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700356 schemasVisibleToPackagesBundles.entrySet()) {
Terry Wange04ceab2021-03-29 19:25:12 -0700357 List<PackageIdentifier> packageIdentifiers =
358 new ArrayList<>(entry.getValue().size());
359 for (int i = 0; i < entry.getValue().size(); i++) {
360 packageIdentifiers.add(
361 new PackageIdentifier(entry.getValue().get(i)));
362 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700363 schemasVisibleToPackages.put(entry.getKey(), packageIdentifiers);
Terry Wange04ceab2021-03-29 19:25:12 -0700364 }
Cassie Wang2feb34d2021-07-22 18:55:19 +0000365 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700366 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700367 packageName,
368 databaseName,
369 schemas,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700370 instance.getVisibilityStore(),
Terry Wange04ceab2021-03-29 19:25:12 -0700371 schemasNotDisplayedBySystem,
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700372 schemasVisibleToPackages,
Terry Wange04ceab2021-03-29 19:25:12 -0700373 forceOverride,
374 schemaVersion);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700375 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700376 invokeCallbackOnResult(callback,
377 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700378
379 // setSchema will sync the schemas in the request to AppSearch, any existing
380 // schemas which is not included in the request will be delete if we force
381 // override incompatible schemas. And all documents of these types will be
382 // deleted as well. We should checkForOptimize for these deletion.
383 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700384 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700385 ++operationFailureCount;
386 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700387 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700388 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700389 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700390 int estimatedBinderLatencyMillis =
391 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
392 int totalLatencyMillis =
393 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700394 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700395 .setPackageName(packageName)
396 .setDatabase(databaseName)
397 .setStatusCode(statusCode)
398 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700399 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
400 // TODO(b/173532925) check the existing binder call latency chart
401 // is good enough for us:
402 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
403 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
404 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700405 .setNumOperationsFailed(operationFailureCount)
406 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700407 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800408 }
Terry Wange04ceab2021-03-29 19:25:12 -0700409 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800410 }
411
412 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800413 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800414 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800415 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700416 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800417 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700418 Objects.requireNonNull(packageName);
419 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700420 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700421 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700422
Cassie Wangb0d60122021-03-30 12:38:46 -0700423 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000424 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700425 EXECUTOR.execute(() -> {
426 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000427 Context targetUserContext = mContext.createContextAsUser(targetUser,
428 /*flags=*/ 0);
429 verifyUserUnlocked(targetUser);
430 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
431 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
432 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
433 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700434 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000435 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700436 GetSchemaResponse response =
437 instance.getAppSearchImpl().getSchema(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700438 invokeCallbackOnResult(
439 callback,
440 AppSearchResult.newSuccessfulResult(response.getBundle()));
441 } catch (Throwable t) {
442 invokeCallbackOnError(callback, t);
443 }
444 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700445 }
446
447 @Override
448 public void getNamespaces(
449 @NonNull String packageName,
450 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700451 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700452 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700453 Objects.requireNonNull(packageName);
454 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700455 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700456 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700457
Cassie Wangb0d60122021-03-30 12:38:46 -0700458 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000459 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700460 EXECUTOR.execute(() -> {
461 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000462 Context targetUserContext = mContext.createContextAsUser(targetUser,
463 /*flags=*/ 0);
464 verifyUserUnlocked(targetUser);
465 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
466 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
467 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
468 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700469 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000470 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700471 List<String> namespaces =
472 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
473 invokeCallbackOnResult(
474 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700475 } catch (Throwable t) {
476 invokeCallbackOnError(callback, t);
477 }
478 });
Terry Wang83a24932020-12-09 21:00:18 -0800479 }
480
481 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800482 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800483 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700484 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700485 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700486 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800487 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800488 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700489 Objects.requireNonNull(packageName);
490 Objects.requireNonNull(databaseName);
491 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700492 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700493 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700494
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700495 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800496 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000497 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700498 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800499 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700500 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800501 int operationSuccessCount = 0;
502 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700503 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000504 Context targetUserContext = mContext.createContextAsUser(targetUser,
505 /*flags=*/ 0);
506 verifyUserUnlocked(targetUser);
507 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
508 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
509 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
510 verifyNotInstantApp(targetUserContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700511 AppSearchBatchResult.Builder<String, Void> resultBuilder =
512 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000513 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700514 for (int i = 0; i < documentBundles.size(); i++) {
515 GenericDocument document = new GenericDocument(documentBundles.get(i));
516 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700517 instance.getAppSearchImpl().putDocument(
518 packageName, databaseName, document, instance.getLogger());
519 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800520 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700521 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700522 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800523 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700524 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700525 // Since we can only include one status code in the atom,
526 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800527 statusCode = result.getResultCode();
528 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700529 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800530 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700531 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700532 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700533 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700534
535 // The existing documents with same ID will be deleted, so there may be some
536 // resources that could be released after optimize().
537 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700538 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700539 ++operationFailureCount;
540 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700541 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800542 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700543 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700544 int estimatedBinderLatencyMillis =
545 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
546 int totalLatencyMillis =
547 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700548 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700549 .setPackageName(packageName)
550 .setDatabase(databaseName)
551 .setStatusCode(statusCode)
552 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800553 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
554 // TODO(b/173532925) check the existing binder call latency chart
555 // is good enough for us:
556 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700557 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800558 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700559 .setNumOperationsFailed(operationFailureCount)
560 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800561 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800562 }
Terry Wange04ceab2021-03-29 19:25:12 -0700563 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800564 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800565
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800566 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800567 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800568 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800569 @NonNull String databaseName,
570 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700571 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800572 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700573 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700574 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800575 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700576 Objects.requireNonNull(packageName);
577 Objects.requireNonNull(databaseName);
578 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700579 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700580 Objects.requireNonNull(typePropertyPaths);
581 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700582 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700583
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700584 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800585 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000586 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700587 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700588 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700589 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700590 int operationSuccessCount = 0;
591 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700592 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000593 Context targetUserContext = mContext.createContextAsUser(targetUser,
594 /*flags=*/ 0);
595 verifyUserUnlocked(targetUser);
596 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
597 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
598 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
599 verifyNotInstantApp(targetUserContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700600 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
601 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000602 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700603 for (int i = 0; i < ids.size(); i++) {
604 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700605 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700606 GenericDocument document = instance.getAppSearchImpl().getDocument(
607 packageName,
608 databaseName,
609 namespace,
610 id,
611 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700612 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700613 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700614 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700615 // Since we can only include one status code in the atom,
616 // for failures, we would just save the one for the last failure
617 AppSearchResult<Bundle> result = throwableToFailedResult(t);
618 resultBuilder.setResult(id, result);
619 statusCode = result.getResultCode();
620 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700621 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800622 }
Terry Wange04ceab2021-03-29 19:25:12 -0700623 invokeCallbackOnResult(callback, resultBuilder.build());
624 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700625 ++operationFailureCount;
626 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700627 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700628 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700629 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700630 int estimatedBinderLatencyMillis =
631 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
632 int totalLatencyMillis =
633 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700634 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700635 .setPackageName(packageName)
636 .setDatabase(databaseName)
637 .setStatusCode(statusCode)
638 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700639 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
640 // TODO(b/173532925) check the existing binder call latency chart
641 // is good enough for us:
642 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
643 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
644 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700645 .setNumOperationsFailed(operationFailureCount)
646 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700647 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800648 }
Terry Wange04ceab2021-03-29 19:25:12 -0700649 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800650 }
651
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800652 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800653 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800654 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700655 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700656 @NonNull String queryExpression,
657 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700658 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700659 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700660 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700661 Objects.requireNonNull(packageName);
662 Objects.requireNonNull(databaseName);
663 Objects.requireNonNull(queryExpression);
664 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700665 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700666 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700667
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700668 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800669 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000670 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700671 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700672 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700673 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700674 int operationSuccessCount = 0;
675 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700676 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000677 Context targetUserContext = mContext.createContextAsUser(targetUser,
678 /*flags=*/ 0);
679 verifyUserUnlocked(targetUser);
680 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
681 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
682 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
683 verifyNotInstantApp(targetUserContext, packageName);
684 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700685 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
686 packageName,
687 databaseName,
688 queryExpression,
689 new SearchSpec(searchSpecBundle),
690 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700691 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700692 invokeCallbackOnResult(
693 callback,
694 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
695 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700696 ++operationFailureCount;
697 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700698 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700699 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700700 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700701 int estimatedBinderLatencyMillis =
702 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
703 int totalLatencyMillis =
704 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700705 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700706 .setPackageName(packageName)
707 .setDatabase(databaseName)
708 .setStatusCode(statusCode)
709 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700710 .setCallType(CallStats.CALL_TYPE_SEARCH)
711 // TODO(b/173532925) check the existing binder call latency chart
712 // is good enough for us:
713 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
714 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
715 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700716 .setNumOperationsFailed(operationFailureCount)
717 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700718 }
Terry Wange04ceab2021-03-29 19:25:12 -0700719 }
720 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700721 }
722
Terry Wangf2093072020-11-30 04:47:19 -0800723 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800724 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800725 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800726 @NonNull String queryExpression,
727 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700728 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700729 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800730 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700731 Objects.requireNonNull(packageName);
732 Objects.requireNonNull(queryExpression);
733 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700734 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700735 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700736
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700737 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800738 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000739 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700740 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700741 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700742 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700743 int operationSuccessCount = 0;
744 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700745 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000746 Context targetUserContext = mContext.createContextAsUser(targetUser,
747 /*flags=*/ 0);
748 verifyUserUnlocked(targetUser);
749 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
750 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
751 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
752 verifyNotInstantApp(targetUserContext, packageName);
753 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700754
755 boolean callerHasSystemAccess =
756 instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
757 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
758 queryExpression,
759 new SearchSpec(searchSpecBundle),
760 packageName,
761 instance.getVisibilityStore(),
762 callingUid,
763 callerHasSystemAccess,
764 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700765 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700766 invokeCallbackOnResult(
767 callback,
768 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700769 } catch (Throwable t) {
770 ++operationFailureCount;
771 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700772 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700773 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700774 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700775 int estimatedBinderLatencyMillis =
776 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
777 int totalLatencyMillis =
778 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700779 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700780 .setPackageName(packageName)
781 .setStatusCode(statusCode)
782 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700783 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
784 // TODO(b/173532925) check the existing binder call latency chart
785 // is good enough for us:
786 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
787 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
788 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700789 .setNumOperationsFailed(operationFailureCount)
790 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700791 }
Terry Wange04ceab2021-03-29 19:25:12 -0700792 }
793 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800794 }
795
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700796 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800797 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700798 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800799 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700800 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700801 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700802 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700803 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700804 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700805
Terry Wangf2093072020-11-30 04:47:19 -0800806 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000807 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700808 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
809 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700810 EXECUTOR.execute(() -> {
811 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000812 Context targetUserContext = mContext.createContextAsUser(targetUser,
813 /*flags=*/ 0);
814 verifyUserUnlocked(targetUser);
815 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
816 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
817 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
818 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700819 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000820 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700821 SearchResultPage searchResultPage =
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700822 instance.getAppSearchImpl().getNextPage(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700823 invokeCallbackOnResult(
824 callback,
825 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
826 } catch (Throwable t) {
827 invokeCallbackOnError(callback, t);
828 }
829 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700830 }
831
832 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700833 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
834 @NonNull UserHandle userHandle) {
835 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700836 Objects.requireNonNull(userHandle);
837
Terry Wangf2093072020-11-30 04:47:19 -0800838 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000839 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700840 EXECUTOR.execute(() -> {
841 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000842 Context targetUserContext = mContext.createContextAsUser(targetUser,
843 /*flags=*/ 0);
844 verifyUserUnlocked(targetUser);
845 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
846 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
847 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
848 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700849 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000850 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700851 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700852 } catch (Throwable t) {
853 Log.e(TAG, "Unable to invalidate the query page token", t);
854 }
855 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800856 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800857
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700858 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800859 public void writeQueryResultsToFile(
860 @NonNull String packageName,
861 @NonNull String databaseName,
862 @NonNull ParcelFileDescriptor fileDescriptor,
863 @NonNull String queryExpression,
864 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700865 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800866 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700867 Objects.requireNonNull(packageName);
868 Objects.requireNonNull(databaseName);
869 Objects.requireNonNull(fileDescriptor);
870 Objects.requireNonNull(queryExpression);
871 Objects.requireNonNull(searchSpecBundle);
872 Objects.requireNonNull(userHandle);
873 Objects.requireNonNull(callback);
874
Terry Wang623e3b02021-02-02 20:27:33 -0800875 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000876 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700877 EXECUTOR.execute(() -> {
878 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000879 Context targetUserContext = mContext.createContextAsUser(targetUser,
880 /*flags=*/ 0);
881 verifyUserUnlocked(targetUser);
882 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
883 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
884 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
885 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700886 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000887 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700888 // we don't need to append the file. The file is always brand new.
889 try (DataOutputStream outputStream = new DataOutputStream(
890 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700891 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700892 packageName,
893 databaseName,
894 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700895 new SearchSpec(searchSpecBundle),
896 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700897 while (!searchResultPage.getResults().isEmpty()) {
898 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
899 AppSearchMigrationHelper.writeBundleToOutputStream(
900 outputStream, searchResultPage.getResults().get(i)
901 .getGenericDocument().getBundle());
902 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700903 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700904 packageName, searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800905 }
Terry Wang623e3b02021-02-02 20:27:33 -0800906 }
Terry Wange04ceab2021-03-29 19:25:12 -0700907 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
908 } catch (Throwable t) {
909 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800910 }
Terry Wange04ceab2021-03-29 19:25:12 -0700911 });
Terry Wang623e3b02021-02-02 20:27:33 -0800912 }
913
914 @Override
915 public void putDocumentsFromFile(
916 @NonNull String packageName,
917 @NonNull String databaseName,
918 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700919 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800920 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700921 Objects.requireNonNull(packageName);
922 Objects.requireNonNull(databaseName);
923 Objects.requireNonNull(fileDescriptor);
924 Objects.requireNonNull(userHandle);
925 Objects.requireNonNull(callback);
926
Terry Wang623e3b02021-02-02 20:27:33 -0800927 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000928 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700929 EXECUTOR.execute(() -> {
930 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000931 Context targetUserContext = mContext.createContextAsUser(targetUser,
932 /*flags=*/ 0);
933 verifyUserUnlocked(targetUser);
934 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
935 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
936 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
937 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700938 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000939 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800940
Terry Wange04ceab2021-03-29 19:25:12 -0700941 GenericDocument document;
942 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
943 try (DataInputStream inputStream = new DataInputStream(
944 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
945 while (true) {
946 try {
947 document = AppSearchMigrationHelper
948 .readDocumentFromInputStream(inputStream);
949 } catch (EOFException e) {
950 // nothing wrong, we just finish the reading.
951 break;
952 }
953 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700954 instance.getAppSearchImpl().putDocument(
955 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700956 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700957 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
958 document.getNamespace(),
959 document.getId(),
960 document.getSchemaType(),
961 AppSearchResult.throwableToFailedResult(t))
962 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700963 }
Terry Wang623e3b02021-02-02 20:27:33 -0800964 }
965 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700966 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700967 invokeCallbackOnResult(callback,
968 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
969 } catch (Throwable t) {
970 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800971 }
Terry Wange04ceab2021-03-29 19:25:12 -0700972 });
Terry Wang623e3b02021-02-02 20:27:33 -0800973 }
974
975 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800976 public void reportUsage(
977 @NonNull String packageName,
978 @NonNull String databaseName,
979 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700980 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800981 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700982 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700983 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800984 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700985 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800986 Objects.requireNonNull(databaseName);
987 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700988 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700989 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800990 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700991
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800992 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000993 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700994 EXECUTOR.execute(() -> {
995 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000996 Context targetUserContext = mContext.createContextAsUser(targetUser,
997 /*flags=*/ 0);
998 verifyUserUnlocked(targetUser);
999 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
1000 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
1001 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
1002 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001003 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001004 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001005
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001006 if (systemUsage
1007 && !instance.getVisibilityStore()
1008 .doesCallerHaveSystemAccess(packageName)) {
1009 throw new AppSearchException(
1010 AppSearchResult.RESULT_SECURITY_ERROR,
1011 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001012 }
1013
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001014 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001015 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001016 usageTimeMillis, systemUsage);
1017 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001018 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001019 } catch (Throwable t) {
1020 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001021 }
Terry Wange04ceab2021-03-29 19:25:12 -07001022 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001023 }
1024
1025 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001026 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001027 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001028 @NonNull String databaseName,
1029 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001030 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001031 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001032 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001033 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001034 Objects.requireNonNull(packageName);
1035 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001036 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001037 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001038 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001039 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001040
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001041 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001042 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001043 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001044 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001045 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001046 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001047 int operationSuccessCount = 0;
1048 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001049 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001050 Context targetUserContext = mContext.createContextAsUser(targetUser,
1051 /*flags=*/ 0);
1052 verifyUserUnlocked(targetUser);
1053 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
1054 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
1055 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
1056 verifyNotInstantApp(targetUserContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -07001057 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1058 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001059 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001060 for (int i = 0; i < ids.size(); i++) {
1061 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001062 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001063 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001064 packageName,
1065 databaseName,
1066 namespace,
1067 id,
1068 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001069 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001070 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001071 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001072 AppSearchResult<Void> result = throwableToFailedResult(t);
1073 resultBuilder.setResult(id, result);
1074 // Since we can only include one status code in the atom,
1075 // for failures, we would just save the one for the last failure
1076 statusCode = result.getResultCode();
1077 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001078 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001079 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001080 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001081 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001082 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001083
1084 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001085 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001086 ++operationFailureCount;
1087 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001088 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001089 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001090 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001091 int estimatedBinderLatencyMillis =
1092 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1093 int totalLatencyMillis =
1094 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001095 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001096 .setPackageName(packageName)
1097 .setDatabase(databaseName)
1098 .setStatusCode(statusCode)
1099 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001100 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1101 // TODO(b/173532925) check the existing binder call latency chart
1102 // is good enough for us:
1103 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1104 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1105 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001106 .setNumOperationsFailed(operationFailureCount)
1107 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001108 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001109 }
Terry Wange04ceab2021-03-29 19:25:12 -07001110 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001111 }
1112
1113 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001114 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001115 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001116 @NonNull String databaseName,
1117 @NonNull String queryExpression,
1118 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001119 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001120 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001121 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001122 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001123 Objects.requireNonNull(packageName);
1124 Objects.requireNonNull(databaseName);
1125 Objects.requireNonNull(queryExpression);
1126 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001127 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001128 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001129
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001130 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001131 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001132 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001133 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001134 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001135 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001136 int operationSuccessCount = 0;
1137 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001138 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001139 Context targetUserContext = mContext.createContextAsUser(targetUser,
1140 /*flags=*/ 0);
1141 verifyUserUnlocked(targetUser);
1142 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
1143 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
1144 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
1145 verifyNotInstantApp(targetUserContext, packageName);
1146 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001147 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001148 packageName,
1149 databaseName,
1150 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001151 new SearchSpec(searchSpecBundle),
1152 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001153 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001154 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001155 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001156 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001157
1158 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001159 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001160 ++operationFailureCount;
1161 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001162 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001163 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001164 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001165 int estimatedBinderLatencyMillis =
1166 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1167 int totalLatencyMillis =
1168 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001169 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001170 .setPackageName(packageName)
1171 .setDatabase(databaseName)
1172 .setStatusCode(statusCode)
1173 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001174 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1175 // TODO(b/173532925) check the existing binder call latency chart
1176 // is good enough for us:
1177 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1178 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1179 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001180 .setNumOperationsFailed(operationFailureCount)
1181 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001182 }
Terry Wange04ceab2021-03-29 19:25:12 -07001183 }
1184 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001185 }
1186
Terry Wangdbd1dca2020-11-03 17:03:56 -08001187 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001188 public void getStorageInfo(
1189 @NonNull String packageName,
1190 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001191 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001192 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001193 Objects.requireNonNull(packageName);
1194 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001195 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001196 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001197
Cassie Wang8f0df492021-03-24 09:23:18 -07001198 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001199 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001200 EXECUTOR.execute(() -> {
1201 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001202 Context targetUserContext = mContext.createContextAsUser(targetUser,
1203 /*flags=*/ 0);
1204 verifyUserUnlocked(targetUser);
1205 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
1206 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
1207 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
1208 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001209 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001210 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001211 StorageInfo storageInfo = instance.getAppSearchImpl()
1212 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001213 Bundle storageInfoBundle = storageInfo.getBundle();
1214 invokeCallbackOnResult(
1215 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1216 } catch (Throwable t) {
1217 invokeCallbackOnError(callback, t);
1218 }
1219 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001220 }
1221
1222 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001223 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001224 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001225 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001226 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001227 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001228 Objects.requireNonNull(userHandle);
1229
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001230 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wangb0d60122021-03-30 12:38:46 -07001231 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001232 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001233 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001234 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001235 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001236 int operationSuccessCount = 0;
1237 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001238 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001239 Context targetUserContext = mContext.createContextAsUser(targetUser,
1240 /*flags=*/ 0);
1241 verifyUserUnlocked(targetUser);
1242 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
1243 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
1244 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
1245 verifyNotInstantApp(targetUserContext, packageName);
1246 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001247 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001248 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001249 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001250 ++operationFailureCount;
1251 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001252 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001253 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001254 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001255 int estimatedBinderLatencyMillis =
1256 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1257 int totalLatencyMillis =
1258 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001259 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001260 .setStatusCode(statusCode)
1261 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001262 .setCallType(CallStats.CALL_TYPE_FLUSH)
1263 // TODO(b/173532925) check the existing binder call latency chart
1264 // is good enough for us:
1265 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1266 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1267 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001268 .setNumOperationsFailed(operationFailureCount)
1269 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001270 }
Terry Wange04ceab2021-03-29 19:25:12 -07001271 }
1272 });
Terry Wang2da17852020-12-16 19:59:08 -08001273 }
1274
1275 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001276 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001277 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001278 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001279 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1280 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001281 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001282 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001283 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001284
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001285 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001286 int callingUid = Binder.getCallingUid();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001287 UserHandle targetUser = handleIncomingUser(userHandle, callingUid);
Cassie Wang84e33a02021-06-18 14:13:31 -07001288
Terry Wange04ceab2021-03-29 19:25:12 -07001289 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001290 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001291 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001292 int operationSuccessCount = 0;
1293 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001294 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001295 Context targetUserContext = mContext.createContextAsUser(targetUser,
1296 /*flags=*/ 0);
1297 verifyUserUnlocked(targetUser);
1298 // TODO(b/193902620): Pass in the callingUser and not the targetUser.
1299 verifyCallingPackage(targetUserContext, targetUser, callingUid, packageName);
1300 // TODO(b/194939218): Pass in the callingUser and not the targetUser.
1301 verifyNotInstantApp(targetUserContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001302 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001303 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001304 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001305 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1306 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001307 ++operationFailureCount;
1308 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001309 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001310 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001311 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001312 int estimatedBinderLatencyMillis =
1313 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1314 int totalLatencyMillis =
1315 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001316 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001317 .setStatusCode(statusCode)
1318 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001319 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1320 // TODO(b/173532925) check the existing binder call latency chart
1321 // is good enough for us:
1322 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1323 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1324 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001325 .setNumOperationsFailed(operationFailureCount)
1326 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001327 }
Terry Wange04ceab2021-03-29 19:25:12 -07001328 }
1329 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001330 }
1331
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001332 private void verifyCallingPackage(
Cassie Wang84e33a02021-06-18 14:13:31 -07001333 @NonNull Context userContext,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001334 @NonNull UserHandle actualCallingUser,
1335 int actualCallingUid,
1336 @NonNull String claimedCallingPackage) {
1337 Objects.requireNonNull(actualCallingUser);
1338 Objects.requireNonNull(claimedCallingPackage);
1339
Cassie Wang84e33a02021-06-18 14:13:31 -07001340 int claimedCallingUid = PackageUtil.getPackageUid(
1341 userContext, claimedCallingPackage);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001342 if (claimedCallingUid == INVALID_UID) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001343 throw new SecurityException(
1344 "Specified calling package [" + claimedCallingPackage + "] not found");
1345 }
1346 if (claimedCallingUid != actualCallingUid) {
Cassie Wang0c62d992021-01-15 14:39:30 -08001347 throw new SecurityException(
1348 "Specified calling package ["
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001349 + claimedCallingPackage
Cassie Wang0c62d992021-01-15 14:39:30 -08001350 + "] does not match the calling uid "
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001351 + actualCallingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001352 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001353 }
1354
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001355 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001356 private void invokeCallbackOnResult(
1357 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001358 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001359 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001360 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001361 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001362 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001363 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001364
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001365 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001366 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001367 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001368 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001369 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001370 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001371 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001372 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001373 }
1374
1375 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001376 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001377 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001378 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001379 */
1380 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001381 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001382 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001383 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001384 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001385 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001386 }
1387 }
1388
1389 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001390 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001391 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001392 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001393 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001394 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001395 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001396 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001397 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001398 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001399 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001400 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001401 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001402 }
Terry Wangfebbead2019-10-17 17:05:18 -07001403 }
Terry Wangf2093072020-11-30 04:47:19 -08001404
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001405 /**
1406 * Helper for dealing with incoming user arguments to system service calls.
1407 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001408 * @param targetUserHandle The user which the caller is requesting to execute as.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001409 * @param callingUid The actual uid of the caller as determined by Binder.
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001410 * @return the user handle that the call should run as. Will always be a concrete user.
1411 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001412 @NonNull
Cassie Wang2feb34d2021-07-22 18:55:19 +00001413 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingUid) {
1414 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1415 if (callingUserHandle.equals(targetUserHandle)) {
1416 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001417 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001418
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001419 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001420 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001421 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001422 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001423 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001424
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001425 throw new SecurityException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001426 "Requested user, " + targetUserHandle + ", is not the same as the calling user, "
1427 + callingUserHandle + ".");
Terry Wangf2093072020-11-30 04:47:19 -08001428 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001429
Cassie Wang84e33a02021-06-18 14:13:31 -07001430 /**
1431 * Helper for ensuring instant apps can't make calls to AppSearch.
1432 *
1433 * @param userContext Context of the user making the call.
1434 * @param packageName Package name of the caller.
1435 * @throws SecurityException if the caller is an instant app.
1436 */
1437 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1438 PackageManager callingPackageManager = userContext.getPackageManager();
1439 if (callingPackageManager.isInstantApp(packageName)) {
1440 throw new SecurityException("Caller not allowed to create AppSearch session"
1441 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1442 }
1443 }
1444
Yang Yu0fcd51a2021-04-23 11:25:44 -07001445 // TODO(b/179160886): Cache the previous storage stats.
1446 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1447 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001448 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001449 @NonNull PackageStats stats,
1450 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001451 @NonNull UserHandle userHandle,
1452 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001453 Objects.requireNonNull(stats);
1454 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001455 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001456
Yang Yu0fcd51a2021-04-23 11:25:44 -07001457 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001458 verifyUserUnlocked(userHandle);
Cassie Wang84e33a02021-06-18 14:13:31 -07001459 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001460 AppSearchUserInstance instance =
1461 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001462 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001463 stats.dataSize += instance.getAppSearchImpl()
1464 .getStorageInfoForPackage(packageName).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001465 } catch (Throwable t) {
1466 Log.e(
1467 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001468 "Unable to augment storage stats for "
1469 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001470 + " packageName "
1471 + packageName,
1472 t);
1473 }
1474 }
1475
1476 @Override
1477 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001478 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001479 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001480
1481 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001482 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001483 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001484 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1485 if (packagesForUid == null) {
1486 return;
1487 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001488 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001489 AppSearchUserInstance instance =
1490 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001491 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001492 for (int i = 0; i < packagesForUid.length; i++) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001493 stats.dataSize += instance.getAppSearchImpl()
1494 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001495 }
1496 } catch (Throwable t) {
1497 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1498 }
1499 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001500
1501 @Override
1502 public void augmentStatsForUser(
1503 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1504 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1505 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1506 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1507 Objects.requireNonNull(stats);
1508 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001509
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001510 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001511 verifyUserUnlocked(userHandle);
1512 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1513 /*flags=*/0, userHandle.getIdentifier());
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001514 if (packagesForUser == null) {
1515 return;
1516 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001517 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001518 AppSearchUserInstance instance =
1519 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001520 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001521 for (int i = 0; i < packagesForUser.size(); i++) {
1522 String packageName = packagesForUser.get(i).packageName;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001523 stats.dataSize += instance.getAppSearchImpl()
1524 .getStorageInfoForPackage(packageName).getSizeBytes();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001525 }
1526 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001527 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001528 }
1529 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001530 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001531
1532 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1533 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001534 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1535 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001536 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001537 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001538 } catch (AppSearchException e) {
1539 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001540 } finally {
1541 OptimizeStats oStats = builder
1542 .setTotalLatencyMillis(
1543 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1544 .build();
1545 if (oStats.getOriginalDocumentCount() > 0) {
1546 // see if optimize has been run by checking originalDocumentCount
1547 instance.getLogger().logStats(oStats);
1548 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001549 }
1550 });
1551 }
1552
1553 private void checkForOptimize(AppSearchUserInstance instance) {
1554 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001555 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1556 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001557 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001558 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001559 } catch (AppSearchException e) {
1560 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001561 } finally {
1562 OptimizeStats oStats = builder
1563 .setTotalLatencyMillis(
1564 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1565 .build();
1566 if (oStats.getOriginalDocumentCount() > 0) {
1567 // see if optimize has been run by checking originalDocumentCount
1568 instance.getLogger().logStats(oStats);
1569 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001570 }
1571 });
1572 }
Terry Wangfebbead2019-10-17 17:05:18 -07001573}