blob: 0b25057ccce89db062cb9f00a53767bd16814419 [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
Alexander Dorokhine872129a2022-02-22 16:36:36 -080021import static com.android.server.appsearch.util.ServiceImplHelper.invokeCallbackOnError;
22import static com.android.server.appsearch.util.ServiceImplHelper.invokeCallbackOnResult;
23
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080024import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080025import android.annotation.NonNull;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080026import android.annotation.WorkerThread;
Alexander Dorokhine18465842020-01-21 01:08:57 -080027import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080028import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080029import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070030import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070031import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070032import android.app.appsearch.GetSchemaResponse;
Terry Wang26b9e5c2020-10-23 02:05:01 -070033import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070034import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080035import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070036import android.app.appsearch.StorageInfo;
Terry Wang5b0c5612021-12-23 15:57:19 -080037import android.app.appsearch.VisibilityDocument;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070038import android.app.appsearch.aidl.AppSearchResultParcel;
39import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
40import android.app.appsearch.aidl.IAppSearchManager;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080041import android.app.appsearch.aidl.IAppSearchObserverProxy;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070042import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070043import android.app.appsearch.exceptions.AppSearchException;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080044import android.app.appsearch.observer.ObserverSpec;
Terry Wang70000152022-02-03 02:22:24 -080045import android.content.AttributionSource;
Terry Wang12dc6c02021-03-31 19:26:16 -070046import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070047import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070048import android.content.Intent;
49import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070050import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070051import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070052import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080053import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070054import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080055import android.os.ParcelFileDescriptor;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080056import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080057import android.os.UserHandle;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080058import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080059import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070060
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070061import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070062import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080063import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine14816e22021-07-12 10:53:24 -070064import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070065import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080066import com.android.server.appsearch.observer.AppSearchObserverProxy;
Xiaoyu Jin10329472021-06-23 16:50:03 -070067import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine872129a2022-02-22 16:36:36 -080068import com.android.server.appsearch.util.ExecutorManager;
69import com.android.server.appsearch.util.ServiceImplHelper;
Alexander Dorokhine655aec02022-02-07 17:24:01 -080070import com.android.server.appsearch.visibilitystore.FrameworkCallerAccess;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070071import com.android.server.usage.StorageStatsManagerLocal;
72import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080073
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070074import com.google.android.icing.proto.PersistType;
75
Terry Wang623e3b02021-02-02 20:27:33 -080076import java.io.DataInputStream;
77import java.io.DataOutputStream;
78import java.io.EOFException;
79import java.io.FileInputStream;
80import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080081import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080082import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080083import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080084import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080085import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070086import java.util.concurrent.Executor;
Alexander Dorokhine18465842020-01-21 01:08:57 -080087
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070088/**
89 * The main service implementation which contains AppSearch's platform functionality.
Yang Yuc047f7b2021-06-25 12:22:42 -070090 *
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070091 * @hide
92 */
Terry Wangfebbead2019-10-17 17:05:18 -070093public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070094 private static final String TAG = "AppSearchManagerService";
Alexander Dorokhine872129a2022-02-22 16:36:36 -080095
96 /**
97 * An executor for system activity not tied to any particular user.
98 *
99 * <p>NOTE: Never call shutdownNow(). AppSearchManagerService persists forever even as
100 * individual users are added and removed -- without this pool the service will be broken. And,
101 * clients waiting for callbacks will never receive anything and will hang.
102 */
103 private static final Executor SHARED_EXECUTOR = ExecutorManager.createDefaultExecutorService();
104
Terry Wang12dc6c02021-03-31 19:26:16 -0700105 private final Context mContext;
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800106 private final ExecutorManager mExecutorManager = new ExecutorManager();
107
Yang Yu0fcd51a2021-04-23 11:25:44 -0700108 private PackageManager mPackageManager;
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800109 private ServiceImplHelper mServiceImplHelper;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700110 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -0700111
112 public AppSearchManagerService(Context context) {
113 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700114 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700115 }
116
117 @Override
118 public void onStart() {
119 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700120 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800121 mServiceImplHelper = new ServiceImplHelper(mContext, mExecutorManager);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700122 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700123 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700124 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700125 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700126 }
127
Xiaoyu Jin10329472021-06-23 16:50:03 -0700128 @Override
129 public void onBootPhase(/* @BootPhase */ int phase) {
130 if (phase == PHASE_BOOT_COMPLETED) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800131 StatsCollector.getInstance(mContext, SHARED_EXECUTOR);
Xiaoyu Jin10329472021-06-23 16:50:03 -0700132 }
133 }
134
Terry Wang12dc6c02021-03-31 19:26:16 -0700135 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700136 mContext.registerReceiverForAllUsers(
137 new UserActionReceiver(),
138 new IntentFilter(Intent.ACTION_USER_REMOVED),
139 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700140 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700141
142 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
143 // broadcasts
144 IntentFilter packageChangedFilter = new IntentFilter();
145 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
146 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
147 packageChangedFilter.addDataScheme("package");
148 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700149 mContext.registerReceiverForAllUsers(
150 new PackageChangedReceiver(),
151 packageChangedFilter,
152 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700153 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700154 }
155
156 private class UserActionReceiver extends BroadcastReceiver {
157 @Override
158 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700159 Objects.requireNonNull(context);
160 Objects.requireNonNull(intent);
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800161 if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
162 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
163 if (userHandle == null) {
164 Log.e(TAG,
165 "Extra " + Intent.EXTRA_USER + " is missing in the intent: " + intent);
166 return;
167 }
168 // We can handle user removal the same way as user stopping: shut down the executor
169 // and close icing. The data of AppSearch is saved in the "credential encrypted"
170 // system directory of each user. That directory will be auto-deleted when a user is
171 // removed, so we don't need it handle it specially.
172 onUserStopping(userHandle);
173 } else {
174 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700175 }
176 }
177 }
178
Terry Wange201dc02021-04-16 01:03:20 -0700179 private class PackageChangedReceiver extends BroadcastReceiver {
180 @Override
181 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700182 Objects.requireNonNull(context);
183 Objects.requireNonNull(intent);
184
Terry Wange201dc02021-04-16 01:03:20 -0700185 switch (intent.getAction()) {
186 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
187 case Intent.ACTION_PACKAGE_DATA_CLEARED:
188 String packageName = intent.getData().getSchemeSpecificPart();
189 if (packageName == null) {
190 Log.e(TAG, "Package name is missing in the intent: " + intent);
191 return;
192 }
193 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
194 if (uid == INVALID_UID) {
195 Log.e(TAG, "uid is missing in the intent: " + intent);
196 return;
197 }
198 handlePackageRemoved(packageName, uid);
199 break;
200 default:
201 Log.e(TAG, "Received unknown intent: " + intent);
202 }
203 }
204 }
205
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700206 private void handlePackageRemoved(@NonNull String packageName, int uid) {
207 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700208 try {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800209 if (mServiceImplHelper.isUserLocked(userHandle)) {
210 // We cannot access a locked user's directory and remove package data from it.
Terry Wanga9e6e212021-04-23 15:51:37 -0700211 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700212 return;
213 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700214 // Only clear the package's data if AppSearch exists for this user.
Xiaoyu Jin8edf1be2022-02-23 01:04:45 +0000215 if (AppSearchModule.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700216 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700217 AppSearchUserInstance instance =
218 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800219 userContext,
220 userHandle,
221 AppSearchConfig.getInstance(SHARED_EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700222 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700223 instance.getAppSearchImpl().clearPackageData(packageName);
Alexander Dorokhine801f3212022-02-10 14:04:32 -0800224 dispatchChangeNotifications(instance);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700225 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700226 }
227 } catch (Throwable t) {
228 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700229 }
Terry Wangfebbead2019-10-17 17:05:18 -0700230 }
231
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800232 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700233 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700234 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700235 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800236 mServiceImplHelper.setUserIsLocked(userHandle, false);
237 mExecutorManager.getOrCreateUserExecutor(userHandle).execute(() -> {
Terry Wanga9e6e212021-04-23 15:51:37 -0700238 try {
239 // Only clear the package's data if AppSearch exists for this user.
Xiaoyu Jin8edf1be2022-02-23 01:04:45 +0000240 if (AppSearchModule.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700241 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700242 AppSearchUserInstance instance =
243 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800244 userContext,
245 userHandle,
246 AppSearchConfig.getInstance(SHARED_EXECUTOR));
Cassie Wang84e33a02021-06-18 14:13:31 -0700247 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700248 .getPackageManager()
249 .getInstalledPackages(/*flags=*/0);
250 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
251 for (int i = 0; i < installedPackageInfos.size(); i++) {
252 packagesToKeep.add(installedPackageInfos.get(i).packageName);
253 }
Terry Wang0be9c302022-01-21 14:36:18 -0800254 packagesToKeep.add(VisibilityStore.VISIBILITY_PACKAGE_NAME);
Terry Wanga9e6e212021-04-23 15:51:37 -0700255 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700256 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700257 }
258 } catch (Throwable t) {
259 Log.e(TAG, "Unable to prune packages for " + user, t);
260 }
261 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800262 }
263
Terry Wangde9f3382021-04-28 19:45:07 -0700264 @Override
265 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700266 Objects.requireNonNull(user);
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800267 onUserStopping(user.getUserHandle());
Terry Wangde9f3382021-04-28 19:45:07 -0700268 }
269
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800270 private void onUserStopping(@NonNull UserHandle userHandle) {
271 Objects.requireNonNull(userHandle);
272 Log.i(TAG, "Shutting down AppSearch for user " + userHandle);
273 try {
274 mExecutorManager.shutDownAndRemoveUserExecutor(userHandle);
275 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
276 mServiceImplHelper.setUserIsLocked(userHandle, true);
277 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
278 } catch (Throwable t) {
279 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700280 }
281 }
282
Terry Wangfebbead2019-10-17 17:05:18 -0700283 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800284 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800285 public void setSchema(
Terry Wang70000152022-02-03 02:22:24 -0800286 @NonNull AttributionSource callerAttributionSource,
Terry Wang6413aee2020-10-07 03:04:58 -0700287 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700288 @NonNull List<Bundle> schemaBundles,
Terry Wang5b0c5612021-12-23 15:57:19 -0800289 @NonNull List<Bundle> visibilityBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800290 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700291 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700292 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700293 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800294 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800295 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700296 Objects.requireNonNull(databaseName);
297 Objects.requireNonNull(schemaBundles);
Terry Wang5b0c5612021-12-23 15:57:19 -0800298 Objects.requireNonNull(visibilityBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700299 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700300 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700301
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700302 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800303 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
304 callerAttributionSource, userHandle, callback);
305 if (targetUser == null) {
306 return; // Verification failed; verifyIncomingCall triggered callback.
307 }
308 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700309 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700310 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700311 int operationSuccessCount = 0;
312 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700313 try {
Terry Wange04ceab2021-03-29 19:25:12 -0700314 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
315 for (int i = 0; i < schemaBundles.size(); i++) {
316 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800317 }
Terry Wang5b0c5612021-12-23 15:57:19 -0800318 List<VisibilityDocument> visibilityDocuments =
319 new ArrayList<>(visibilityBundles.size());
320 for (int i = 0; i < visibilityBundles.size(); i++) {
321 visibilityDocuments.add(
322 new VisibilityDocument(visibilityBundles.get(i)));
Terry Wange04ceab2021-03-29 19:25:12 -0700323 }
Cassie Wang2feb34d2021-07-22 18:55:19 +0000324 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700325 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700326 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wang70000152022-02-03 02:22:24 -0800327 callerAttributionSource.getPackageName(),
Terry Wange04ceab2021-03-29 19:25:12 -0700328 databaseName,
329 schemas,
Terry Wange15ea582021-10-21 18:59:21 -0700330 visibilityDocuments,
Terry Wange04ceab2021-03-29 19:25:12 -0700331 forceOverride,
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700332 schemaVersion,
333 /*setSchemaStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700334 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700335 invokeCallbackOnResult(callback,
336 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700337
Alexander Dorokhine801f3212022-02-10 14:04:32 -0800338 // Schedule a task to dispatch change notifications. See requirements for where
339 // the method is called documented in the method description.
340 dispatchChangeNotifications(instance);
341
Terry Wangf4d219b2021-07-01 19:11:39 -0700342 // setSchema will sync the schemas in the request to AppSearch, any existing
343 // schemas which is not included in the request will be delete if we force
344 // override incompatible schemas. And all documents of these types will be
345 // deleted as well. We should checkForOptimize for these deletion.
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800346 checkForOptimize(targetUser, instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700347 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700348 ++operationFailureCount;
349 statusCode = throwableToFailedResult(t).getResultCode();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800350 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700351 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700352 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700353 int estimatedBinderLatencyMillis =
354 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
355 int totalLatencyMillis =
356 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700357 instance.getLogger().logStats(new CallStats.Builder()
Terry Wang70000152022-02-03 02:22:24 -0800358 .setPackageName(callerAttributionSource.getPackageName())
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700359 .setDatabase(databaseName)
360 .setStatusCode(statusCode)
361 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700362 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
363 // TODO(b/173532925) check the existing binder call latency chart
364 // is good enough for us:
365 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
366 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
367 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700368 .setNumOperationsFailed(operationFailureCount)
369 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700370 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800371 }
Terry Wange04ceab2021-03-29 19:25:12 -0700372 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800373 }
374
375 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800376 public void getSchema(
Terry Wang70000152022-02-03 02:22:24 -0800377 @NonNull AttributionSource callerAttributionSource,
378 @NonNull String targetPackageName,
Terry Wang83a24932020-12-09 21:00:18 -0800379 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700380 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800381 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800382 Objects.requireNonNull(callerAttributionSource);
383 Objects.requireNonNull(targetPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700384 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700385 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700386 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700387
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800388 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
389 callerAttributionSource, userHandle, callback);
390 if (targetUser == null) {
391 return; // Verification failed; verifyIncomingCall triggered callback.
392 }
393 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -0700394 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700395 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000396 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang70000152022-02-03 02:22:24 -0800397
398 boolean callerHasSystemAccess = instance.getVisibilityChecker()
399 .doesCallerHaveSystemAccess(callerAttributionSource.getPackageName());
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700400 GetSchemaResponse response =
Alexander Dorokhined41def42022-01-25 15:45:34 -0800401 instance.getAppSearchImpl().getSchema(
Terry Wang70000152022-02-03 02:22:24 -0800402 targetPackageName,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800403 databaseName,
Terry Wang70000152022-02-03 02:22:24 -0800404 new FrameworkCallerAccess(callerAttributionSource,
405 callerHasSystemAccess));
Terry Wange04ceab2021-03-29 19:25:12 -0700406 invokeCallbackOnResult(
407 callback,
408 AppSearchResult.newSuccessfulResult(response.getBundle()));
409 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800410 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Terry Wange04ceab2021-03-29 19:25:12 -0700411 }
412 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700413 }
414
415 @Override
416 public void getNamespaces(
Terry Wang70000152022-02-03 02:22:24 -0800417 @NonNull AttributionSource callerAttributionSource,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700418 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700419 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700420 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800421 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700422 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700423 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700424 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700425
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800426 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
427 callerAttributionSource, userHandle, callback);
428 if (targetUser == null) {
429 return; // Verification failed; verifyIncomingCall triggered callback.
430 }
431 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -0700432 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700433 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000434 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700435 List<String> namespaces =
Terry Wang70000152022-02-03 02:22:24 -0800436 instance.getAppSearchImpl().getNamespaces(
437 callerAttributionSource.getPackageName(), databaseName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700438 invokeCallbackOnResult(
439 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700440 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800441 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Terry Wange04ceab2021-03-29 19:25:12 -0700442 }
443 });
Terry Wang83a24932020-12-09 21:00:18 -0800444 }
445
446 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800447 public void putDocuments(
Terry Wang70000152022-02-03 02:22:24 -0800448 @NonNull AttributionSource callerAttributionSource,
Terry Wang6413aee2020-10-07 03:04:58 -0700449 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700450 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700451 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800452 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800453 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800454 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700455 Objects.requireNonNull(databaseName);
456 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700457 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700458 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700459
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700460 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800461 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
462 callerAttributionSource, userHandle, callback);
463 if (targetUser == null) {
464 return; // Verification failed; verifyIncomingCall triggered callback.
465 }
466 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800467 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700468 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800469 int operationSuccessCount = 0;
470 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700471 try {
Terry Wange04ceab2021-03-29 19:25:12 -0700472 AppSearchBatchResult.Builder<String, Void> resultBuilder =
473 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000474 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700475 for (int i = 0; i < documentBundles.size(); i++) {
476 GenericDocument document = new GenericDocument(documentBundles.get(i));
477 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700478 instance.getAppSearchImpl().putDocument(
Terry Wang70000152022-02-03 02:22:24 -0800479 callerAttributionSource.getPackageName(),
480 databaseName,
481 document,
482 instance.getLogger());
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700483 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800484 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700485 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700486 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800487 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700488 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700489 // Since we can only include one status code in the atom,
490 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800491 statusCode = result.getResultCode();
492 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700493 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800494 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700495 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700496 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700497 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700498
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800499 // Schedule a task to dispatch change notifications. See requirements for where
500 // the method is called documented in the method description.
501 dispatchChangeNotifications(instance);
502
Terry Wangf4d219b2021-07-01 19:11:39 -0700503 // The existing documents with same ID will be deleted, so there may be some
504 // resources that could be released after optimize().
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800505 checkForOptimize(
506 targetUser, instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700507 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700508 ++operationFailureCount;
509 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700510 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800511 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700512 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700513 int estimatedBinderLatencyMillis =
514 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
515 int totalLatencyMillis =
516 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700517 instance.getLogger().logStats(new CallStats.Builder()
Terry Wang70000152022-02-03 02:22:24 -0800518 .setPackageName(callerAttributionSource.getPackageName())
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700519 .setDatabase(databaseName)
520 .setStatusCode(statusCode)
521 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800522 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
523 // TODO(b/173532925) check the existing binder call latency chart
524 // is good enough for us:
525 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700526 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800527 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700528 .setNumOperationsFailed(operationFailureCount)
529 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800530 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800531 }
Terry Wange04ceab2021-03-29 19:25:12 -0700532 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800533 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800534
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800535 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800536 public void getDocuments(
Terry Wang70000152022-02-03 02:22:24 -0800537 @NonNull AttributionSource callerAttributionSource,
Alex Saveliev87631932022-01-21 00:48:44 +0000538 @NonNull String targetPackageName,
Terry Wangf2093072020-11-30 04:47:19 -0800539 @NonNull String databaseName,
540 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700541 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800542 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700543 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700544 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800545 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800546 Objects.requireNonNull(callerAttributionSource);
Alex Saveliev87631932022-01-21 00:48:44 +0000547 Objects.requireNonNull(targetPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700548 Objects.requireNonNull(databaseName);
549 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700550 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700551 Objects.requireNonNull(typePropertyPaths);
552 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700553 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700554
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700555 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800556 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
557 callerAttributionSource, userHandle, callback);
558 if (targetUser == null) {
559 return; // Verification failed; verifyIncomingCall triggered callback.
560 }
561 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700562 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700563 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700564 int operationSuccessCount = 0;
565 int operationFailureCount = 0;
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800566 boolean global =
567 !callerAttributionSource.getPackageName().equals(targetPackageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700568 try {
Terry Wange04ceab2021-03-29 19:25:12 -0700569 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
570 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000571 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700572 for (int i = 0; i < ids.size(); i++) {
573 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700574 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000575 GenericDocument document;
576 if (global) {
Terry Wang70000152022-02-03 02:22:24 -0800577 boolean callerHasSystemAccess = instance.getVisibilityChecker()
578 .doesCallerHaveSystemAccess(callerAttributionSource
579 .getPackageName());
Alex Saveliev87631932022-01-21 00:48:44 +0000580 document = instance.getAppSearchImpl().globalGetDocument(
581 targetPackageName,
582 databaseName,
583 namespace,
584 id,
585 typePropertyPaths,
Terry Wang70000152022-02-03 02:22:24 -0800586 new FrameworkCallerAccess(callerAttributionSource,
587 callerHasSystemAccess));
Alex Saveliev87631932022-01-21 00:48:44 +0000588 } else {
589 document = instance.getAppSearchImpl().getDocument(
590 targetPackageName,
591 databaseName,
592 namespace,
593 id,
594 typePropertyPaths);
595 }
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700596 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700597 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700598 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700599 // Since we can only include one status code in the atom,
600 // for failures, we would just save the one for the last failure
601 AppSearchResult<Bundle> result = throwableToFailedResult(t);
602 resultBuilder.setResult(id, result);
603 statusCode = result.getResultCode();
604 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700605 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800606 }
Terry Wange04ceab2021-03-29 19:25:12 -0700607 invokeCallbackOnResult(callback, resultBuilder.build());
608 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700609 ++operationFailureCount;
610 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700611 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700612 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700613 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700614 int estimatedBinderLatencyMillis =
615 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
616 int totalLatencyMillis =
617 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alex Saveliev6af06242022-02-01 13:50:35 -0800618 int callType = global?
619 CallStats.CALL_TYPE_GLOBAL_GET_DOCUMENT_BY_ID:
620 CallStats.CALL_TYPE_GET_DOCUMENTS;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700621 instance.getLogger().logStats(new CallStats.Builder()
Alex Saveliev87631932022-01-21 00:48:44 +0000622 .setPackageName(targetPackageName)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700623 .setDatabase(databaseName)
624 .setStatusCode(statusCode)
625 .setTotalLatencyMillis(totalLatencyMillis)
Alex Saveliev6af06242022-02-01 13:50:35 -0800626 .setCallType(callType)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700627 // TODO(b/173532925) check the existing binder call latency chart
628 // is good enough for us:
629 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
630 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
631 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700632 .setNumOperationsFailed(operationFailureCount)
633 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700634 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800635 }
Terry Wange04ceab2021-03-29 19:25:12 -0700636 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800637 }
638
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800639 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800640 public void query(
Terry Wang70000152022-02-03 02:22:24 -0800641 @NonNull AttributionSource callerAttributionSource,
Terry Wang6413aee2020-10-07 03:04:58 -0700642 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700643 @NonNull String queryExpression,
644 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700645 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700646 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700647 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800648 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700649 Objects.requireNonNull(databaseName);
650 Objects.requireNonNull(queryExpression);
651 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700652 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700653 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700654
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700655 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800656 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
657 callerAttributionSource, userHandle, callback);
658 if (targetUser == null) {
659 return; // Verification failed; verifyIncomingCall triggered callback.
660 }
661 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700662 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700663 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700664 int operationSuccessCount = 0;
665 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700666 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000667 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700668 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wang70000152022-02-03 02:22:24 -0800669 callerAttributionSource.getPackageName(),
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700670 databaseName,
671 queryExpression,
672 new SearchSpec(searchSpecBundle),
673 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700674 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700675 invokeCallbackOnResult(
676 callback,
677 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
678 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700679 ++operationFailureCount;
680 statusCode = throwableToFailedResult(t).getResultCode();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800681 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700682 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700683 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700684 int estimatedBinderLatencyMillis =
685 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
686 int totalLatencyMillis =
687 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700688 instance.getLogger().logStats(new CallStats.Builder()
Terry Wang70000152022-02-03 02:22:24 -0800689 .setPackageName(callerAttributionSource.getPackageName())
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700690 .setDatabase(databaseName)
691 .setStatusCode(statusCode)
692 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700693 .setCallType(CallStats.CALL_TYPE_SEARCH)
694 // TODO(b/173532925) check the existing binder call latency chart
695 // is good enough for us:
696 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
697 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
698 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700699 .setNumOperationsFailed(operationFailureCount)
700 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700701 }
Terry Wange04ceab2021-03-29 19:25:12 -0700702 }
703 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700704 }
705
Terry Wangf2093072020-11-30 04:47:19 -0800706 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800707 public void globalQuery(
Terry Wang70000152022-02-03 02:22:24 -0800708 @NonNull AttributionSource callerAttributionSource,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800709 @NonNull String queryExpression,
710 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700711 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700712 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800713 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800714 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700715 Objects.requireNonNull(queryExpression);
716 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700717 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700718 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700719
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700720 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800721 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
722 callerAttributionSource, userHandle, callback);
723 if (targetUser == null) {
724 return; // Verification failed; verifyIncomingCall triggered callback.
725 }
726 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700727 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700728 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700729 int operationSuccessCount = 0;
730 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700731 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +0000732 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700733
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800734 boolean callerHasSystemAccess = instance.getVisibilityChecker()
Terry Wang70000152022-02-03 02:22:24 -0800735 .doesCallerHaveSystemAccess(callerAttributionSource.getPackageName());
736
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700737 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
738 queryExpression,
739 new SearchSpec(searchSpecBundle),
Terry Wang70000152022-02-03 02:22:24 -0800740 new FrameworkCallerAccess(callerAttributionSource,
Alexander Dorokhine72f5e372022-02-07 17:23:49 -0800741 callerHasSystemAccess),
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700742 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700743 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700744 invokeCallbackOnResult(
745 callback,
746 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700747 } catch (Throwable t) {
748 ++operationFailureCount;
749 statusCode = throwableToFailedResult(t).getResultCode();
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800750 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700751 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700752 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700753 int estimatedBinderLatencyMillis =
754 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
755 int totalLatencyMillis =
756 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700757 instance.getLogger().logStats(new CallStats.Builder()
Terry Wang70000152022-02-03 02:22:24 -0800758 .setPackageName(callerAttributionSource.getPackageName())
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700759 .setStatusCode(statusCode)
760 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700761 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
762 // TODO(b/173532925) check the existing binder call latency chart
763 // is good enough for us:
764 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
765 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
766 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700767 .setNumOperationsFailed(operationFailureCount)
768 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700769 }
Terry Wange04ceab2021-03-29 19:25:12 -0700770 }
771 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800772 }
773
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700774 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800775 public void getNextPage(
Terry Wang70000152022-02-03 02:22:24 -0800776 @NonNull AttributionSource callerAttributionSource,
Cassie Wang0c62d992021-01-15 14:39:30 -0800777 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700778 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700779 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800780 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700781 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700782 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700783
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800784 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
785 callerAttributionSource, userHandle, callback);
786 if (targetUser == null) {
787 return; // Verification failed; verifyIncomingCall triggered callback.
788 }
789 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -0700790 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700791 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000792 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700793 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700794 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700795 instance.getAppSearchImpl().getNextPage(
Terry Wang70000152022-02-03 02:22:24 -0800796 callerAttributionSource.getPackageName(), nextPageToken,
797 /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700798 invokeCallbackOnResult(
799 callback,
800 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
801 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800802 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Terry Wange04ceab2021-03-29 19:25:12 -0700803 }
804 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700805 }
806
807 @Override
Terry Wang70000152022-02-03 02:22:24 -0800808 public void invalidateNextPageToken(
809 @NonNull AttributionSource callerAttributionSource,
810 long nextPageToken,
Cassie Wang84e33a02021-06-18 14:13:31 -0700811 @NonNull UserHandle userHandle) {
Terry Wang70000152022-02-03 02:22:24 -0800812 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700813 Objects.requireNonNull(userHandle);
814
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800815 try {
816 UserHandle targetUser = mServiceImplHelper.verifyIncomingCall(
817 callerAttributionSource, userHandle);
818 mExecutorManager.getOrCreateUserExecutor(targetUser).execute(() -> {
819 try {
820 AppSearchUserInstance instance =
821 mAppSearchUserInstanceManager.getUserInstance(targetUser);
822 instance.getAppSearchImpl().invalidateNextPageToken(
823 callerAttributionSource.getPackageName(), nextPageToken);
824 } catch (Throwable t) {
825 Log.e(TAG, "Unable to invalidate the query page token", t);
826 }
827 });
828 } catch (Throwable t) {
829 Log.e(TAG, "Unable to invalidate the query page token", t);
830 }
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800831 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800832
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700833 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800834 public void writeQueryResultsToFile(
Terry Wang70000152022-02-03 02:22:24 -0800835 @NonNull AttributionSource callerAttributionSource,
Terry Wang623e3b02021-02-02 20:27:33 -0800836 @NonNull String databaseName,
837 @NonNull ParcelFileDescriptor fileDescriptor,
838 @NonNull String queryExpression,
839 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700840 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800841 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800842 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700843 Objects.requireNonNull(databaseName);
844 Objects.requireNonNull(fileDescriptor);
845 Objects.requireNonNull(queryExpression);
846 Objects.requireNonNull(searchSpecBundle);
847 Objects.requireNonNull(userHandle);
848 Objects.requireNonNull(callback);
849
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800850 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
851 callerAttributionSource, userHandle, callback);
852 if (targetUser == null) {
853 return; // Verification failed; verifyIncomingCall triggered callback.
854 }
855 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -0700856 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700857 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000858 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700859 // we don't need to append the file. The file is always brand new.
860 try (DataOutputStream outputStream = new DataOutputStream(
861 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700862 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wang70000152022-02-03 02:22:24 -0800863 callerAttributionSource.getPackageName(),
Terry Wange04ceab2021-03-29 19:25:12 -0700864 databaseName,
865 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700866 new SearchSpec(searchSpecBundle),
867 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700868 while (!searchResultPage.getResults().isEmpty()) {
869 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
870 AppSearchMigrationHelper.writeBundleToOutputStream(
871 outputStream, searchResultPage.getResults().get(i)
872 .getGenericDocument().getBundle());
873 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700874 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700875 searchResultPage = instance.getAppSearchImpl().getNextPage(
Terry Wang70000152022-02-03 02:22:24 -0800876 callerAttributionSource.getPackageName(),
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700877 searchResultPage.getNextPageToken(),
878 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800879 }
Terry Wang623e3b02021-02-02 20:27:33 -0800880 }
Terry Wange04ceab2021-03-29 19:25:12 -0700881 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
882 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800883 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Terry Wang623e3b02021-02-02 20:27:33 -0800884 }
Terry Wange04ceab2021-03-29 19:25:12 -0700885 });
Terry Wang623e3b02021-02-02 20:27:33 -0800886 }
887
888 @Override
889 public void putDocumentsFromFile(
Terry Wang70000152022-02-03 02:22:24 -0800890 @NonNull AttributionSource callerAttributionSource,
Terry Wang623e3b02021-02-02 20:27:33 -0800891 @NonNull String databaseName,
892 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700893 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800894 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800895 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700896 Objects.requireNonNull(databaseName);
897 Objects.requireNonNull(fileDescriptor);
898 Objects.requireNonNull(userHandle);
899 Objects.requireNonNull(callback);
900
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800901 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
902 callerAttributionSource, userHandle, callback);
903 if (targetUser == null) {
904 return; // Verification failed; verifyIncomingCall triggered callback.
905 }
906 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -0700907 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700908 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000909 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800910
Terry Wange04ceab2021-03-29 19:25:12 -0700911 GenericDocument document;
912 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
913 try (DataInputStream inputStream = new DataInputStream(
914 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
915 while (true) {
916 try {
917 document = AppSearchMigrationHelper
918 .readDocumentFromInputStream(inputStream);
919 } catch (EOFException e) {
920 // nothing wrong, we just finish the reading.
921 break;
922 }
923 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700924 instance.getAppSearchImpl().putDocument(
Terry Wang70000152022-02-03 02:22:24 -0800925 callerAttributionSource.getPackageName(),
926 databaseName,
927 document,
928 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700929 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700930 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
931 document.getNamespace(),
932 document.getId(),
933 document.getSchemaType(),
934 AppSearchResult.throwableToFailedResult(t))
935 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700936 }
Terry Wang623e3b02021-02-02 20:27:33 -0800937 }
938 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700939 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700940 invokeCallbackOnResult(callback,
941 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
942 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800943 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Terry Wang623e3b02021-02-02 20:27:33 -0800944 }
Terry Wange04ceab2021-03-29 19:25:12 -0700945 });
Terry Wang623e3b02021-02-02 20:27:33 -0800946 }
947
948 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800949 public void reportUsage(
Terry Wang70000152022-02-03 02:22:24 -0800950 @NonNull AttributionSource callerAttributionSource,
951 @NonNull String targetPackageName,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800952 @NonNull String databaseName,
953 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700954 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800955 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700956 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700957 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800958 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -0800959 Objects.requireNonNull(callerAttributionSource);
960 Objects.requireNonNull(targetPackageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800961 Objects.requireNonNull(databaseName);
962 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700963 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700964 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800965 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700966
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800967 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
968 callerAttributionSource, userHandle, callback);
969 if (targetUser == null) {
970 return; // Verification failed; verifyIncomingCall triggered callback.
971 }
972 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -0700973 try {
Terry Wang70000152022-02-03 02:22:24 -0800974 String callingPackageName = callerAttributionSource.getPackageName();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700975 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000976 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang70000152022-02-03 02:22:24 -0800977 if (systemUsage) {
978 if (!instance.getVisibilityChecker().doesCallerHaveSystemAccess(
979 callerAttributionSource.getPackageName())) {
980 throw new AppSearchException(AppSearchResult.RESULT_SECURITY_ERROR,
981 callingPackageName
982 + " does not have access to report system usage");
983 }
984 } else {
985 if (!callingPackageName.equals(targetPackageName)) {
986 throw new AppSearchException(AppSearchResult.RESULT_SECURITY_ERROR,
987 "Cannot report usage to different package: "
988 + targetPackageName + " from package: "
989 + callingPackageName);
990 }
Terry Wange04ceab2021-03-29 19:25:12 -0700991 }
992
Terry Wang70000152022-02-03 02:22:24 -0800993 instance.getAppSearchImpl().reportUsage(targetPackageName, databaseName,
994 namespace, documentId, usageTimeMillis, systemUsage);
Terry Wange04ceab2021-03-29 19:25:12 -0700995 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700996 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -0700997 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -0800998 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700999 }
Terry Wange04ceab2021-03-29 19:25:12 -07001000 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001001 }
1002
1003 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001004 public void removeByDocumentId(
Terry Wang70000152022-02-03 02:22:24 -08001005 @NonNull AttributionSource callerAttributionSource,
Terry Wangf2093072020-11-30 04:47:19 -08001006 @NonNull String databaseName,
1007 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001008 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001009 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001010 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001011 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -08001012 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001013 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001014 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001015 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001016 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001017 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001018
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001019 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001020 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
1021 callerAttributionSource, userHandle, callback);
1022 if (targetUser == null) {
1023 return; // Verification failed; verifyIncomingCall triggered callback.
1024 }
1025 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001026 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001027 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001028 int operationSuccessCount = 0;
1029 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001030 try {
Terry Wange04ceab2021-03-29 19:25:12 -07001031 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1032 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001033 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001034 for (int i = 0; i < ids.size(); i++) {
1035 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001036 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001037 instance.getAppSearchImpl().remove(
Terry Wang70000152022-02-03 02:22:24 -08001038 callerAttributionSource.getPackageName(),
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001039 databaseName,
1040 namespace,
1041 id,
1042 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001043 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001044 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001045 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001046 AppSearchResult<Void> result = throwableToFailedResult(t);
1047 resultBuilder.setResult(id, result);
1048 // Since we can only include one status code in the atom,
1049 // for failures, we would just save the one for the last failure
1050 statusCode = result.getResultCode();
1051 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001052 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001053 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001054 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001055 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001056 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001057
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001058 // Schedule a task to dispatch change notifications. See requirements for where
1059 // the method is called documented in the method description.
1060 dispatchChangeNotifications(instance);
1061
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001062 checkForOptimize(targetUser, instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001063 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001064 ++operationFailureCount;
1065 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001066 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001067 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001068 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001069 int estimatedBinderLatencyMillis =
1070 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1071 int totalLatencyMillis =
1072 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001073 instance.getLogger().logStats(new CallStats.Builder()
Terry Wang70000152022-02-03 02:22:24 -08001074 .setPackageName(callerAttributionSource.getPackageName())
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001075 .setDatabase(databaseName)
1076 .setStatusCode(statusCode)
1077 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001078 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1079 // TODO(b/173532925) check the existing binder call latency chart
1080 // is good enough for us:
1081 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1082 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1083 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001084 .setNumOperationsFailed(operationFailureCount)
1085 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001086 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001087 }
Terry Wange04ceab2021-03-29 19:25:12 -07001088 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001089 }
1090
1091 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001092 public void removeByQuery(
Terry Wang70000152022-02-03 02:22:24 -08001093 @NonNull AttributionSource callerAttributionSource,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001094 @NonNull String databaseName,
1095 @NonNull String queryExpression,
1096 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001097 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001098 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001099 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001100 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Terry Wang70000152022-02-03 02:22:24 -08001101 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001102 Objects.requireNonNull(databaseName);
1103 Objects.requireNonNull(queryExpression);
1104 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001105 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001106 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001107
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001108 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001109 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
1110 callerAttributionSource, userHandle, callback);
1111 if (targetUser == null) {
1112 return; // Verification failed; verifyIncomingCall triggered callback.
1113 }
1114 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001115 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001116 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001117 int operationSuccessCount = 0;
1118 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001119 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001120 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001121 instance.getAppSearchImpl().removeByQuery(
Terry Wang70000152022-02-03 02:22:24 -08001122 callerAttributionSource.getPackageName(),
Terry Wange04ceab2021-03-29 19:25:12 -07001123 databaseName,
1124 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001125 new SearchSpec(searchSpecBundle),
1126 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001127 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001128 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001129 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001130 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001131
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001132 // Schedule a task to dispatch change notifications. See requirements for where
1133 // the method is called documented in the method description.
1134 dispatchChangeNotifications(instance);
1135
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001136 checkForOptimize(targetUser, instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001137 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001138 ++operationFailureCount;
1139 statusCode = throwableToFailedResult(t).getResultCode();
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001140 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001141 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001142 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001143 int estimatedBinderLatencyMillis =
1144 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1145 int totalLatencyMillis =
1146 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001147 instance.getLogger().logStats(new CallStats.Builder()
Terry Wang70000152022-02-03 02:22:24 -08001148 .setPackageName(callerAttributionSource.getPackageName())
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001149 .setDatabase(databaseName)
1150 .setStatusCode(statusCode)
1151 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001152 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1153 // TODO(b/173532925) check the existing binder call latency chart
1154 // is good enough for us:
1155 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1156 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1157 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001158 .setNumOperationsFailed(operationFailureCount)
1159 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001160 }
Terry Wange04ceab2021-03-29 19:25:12 -07001161 }
1162 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001163 }
1164
Terry Wangdbd1dca2020-11-03 17:03:56 -08001165 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001166 public void getStorageInfo(
Terry Wang70000152022-02-03 02:22:24 -08001167 @NonNull AttributionSource callerAttributionSource,
Cassie Wang8f0df492021-03-24 09:23:18 -07001168 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001169 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001170 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -08001171 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001172 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001173 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001174 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001175
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001176 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
1177 callerAttributionSource, userHandle, callback);
1178 if (targetUser == null) {
1179 return; // Verification failed; verifyIncomingCall triggered callback.
1180 }
1181 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Terry Wange04ceab2021-03-29 19:25:12 -07001182 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001183 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001184 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang70000152022-02-03 02:22:24 -08001185 StorageInfo storageInfo = instance.getAppSearchImpl().getStorageInfoForDatabase(
1186 callerAttributionSource.getPackageName(), databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001187 Bundle storageInfoBundle = storageInfo.getBundle();
1188 invokeCallbackOnResult(
1189 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1190 } catch (Throwable t) {
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001191 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Terry Wange04ceab2021-03-29 19:25:12 -07001192 }
1193 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001194 }
1195
1196 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001197 public void persistToDisk(
Terry Wang70000152022-02-03 02:22:24 -08001198 @NonNull AttributionSource callerAttributionSource,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001199 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001200 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Terry Wang70000152022-02-03 02:22:24 -08001201 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001202 Objects.requireNonNull(userHandle);
1203
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001204 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001205 try {
1206 UserHandle targetUser = mServiceImplHelper.verifyIncomingCall(
1207 callerAttributionSource, userHandle);
1208 mExecutorManager.getOrCreateUserExecutor(targetUser).execute(() -> {
1209 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
1210 AppSearchUserInstance instance = null;
1211 int operationSuccessCount = 0;
1212 int operationFailureCount = 0;
1213 try {
1214 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
1215 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
1216 ++operationSuccessCount;
1217 } catch (Throwable t) {
1218 ++operationFailureCount;
1219 statusCode = throwableToFailedResult(t).getResultCode();
1220 Log.e(TAG, "Unable to persist the data to disk", t);
1221 } finally {
1222 if (instance != null) {
1223 int estimatedBinderLatencyMillis =
1224 2 * (int) (totalLatencyStartTimeMillis
1225 - binderCallStartTimeMillis);
1226 int totalLatencyMillis =
1227 (int) (SystemClock.elapsedRealtime()
1228 - totalLatencyStartTimeMillis);
1229 instance.getLogger().logStats(new CallStats.Builder()
1230 .setStatusCode(statusCode)
1231 .setTotalLatencyMillis(totalLatencyMillis)
1232 .setCallType(CallStats.CALL_TYPE_FLUSH)
1233 // TODO(b/173532925) check the existing binder call latency
1234 // chart is good enough for us:
1235 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1236 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1237 .setNumOperationsSucceeded(operationSuccessCount)
1238 .setNumOperationsFailed(operationFailureCount)
1239 .build());
1240 }
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001241 }
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001242 });
1243 } catch (Throwable t) {
1244 Log.e(TAG, "Unable to persist the data to disk", t);
1245 }
Terry Wang2da17852020-12-16 19:59:08 -08001246 }
1247
1248 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001249 public AppSearchResultParcel<Void> addObserver(
Terry Wang70000152022-02-03 02:22:24 -08001250 @NonNull AttributionSource callerAttributionSource,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001251 @NonNull String targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001252 @NonNull Bundle observerSpecBundle,
1253 @NonNull UserHandle userHandle,
1254 @NonNull IAppSearchObserverProxy observerProxyStub) {
Terry Wang70000152022-02-03 02:22:24 -08001255 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001256 Objects.requireNonNull(targetPackageName);
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001257 Objects.requireNonNull(observerSpecBundle);
1258 Objects.requireNonNull(userHandle);
1259 Objects.requireNonNull(observerProxyStub);
1260
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001261 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1262 try {
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001263 UserHandle targetUser = mServiceImplHelper.verifyIncomingCall(
1264 callerAttributionSource, userHandle);
1265 long callingIdentity = Binder.clearCallingIdentity();
1266 try {
1267 AppSearchUserInstance instance =
1268 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1269 boolean callerHasSystemAccess = instance.getVisibilityChecker()
1270 .doesCallerHaveSystemAccess(callerAttributionSource.getPackageName());
1271 instance.getAppSearchImpl().addObserver(
1272 new FrameworkCallerAccess(
1273 callerAttributionSource, callerHasSystemAccess),
1274 targetPackageName,
1275 new ObserverSpec(observerSpecBundle),
1276 mExecutorManager.getOrCreateUserExecutor(targetUser),
1277 new AppSearchObserverProxy(observerProxyStub));
1278 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1279 } finally {
1280 Binder.restoreCallingIdentity(callingIdentity);
1281 }
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001282 } catch (Throwable t) {
1283 return new AppSearchResultParcel<>(throwableToFailedResult(t));
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001284 }
1285 }
1286
1287 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001288 public AppSearchResultParcel<Void> removeObserver(
Terry Wang70000152022-02-03 02:22:24 -08001289 @NonNull AttributionSource callerAttributionSource,
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001290 @NonNull String observedPackage,
1291 @NonNull UserHandle userHandle,
1292 @NonNull IAppSearchObserverProxy observerProxyStub) {
Terry Wang70000152022-02-03 02:22:24 -08001293 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001294 Objects.requireNonNull(observedPackage);
1295 Objects.requireNonNull(userHandle);
1296 Objects.requireNonNull(observerProxyStub);
1297
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001298 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1299 try {
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001300 UserHandle targetUser = mServiceImplHelper.verifyIncomingCall(
1301 callerAttributionSource, userHandle);
1302 long callingIdentity = Binder.clearCallingIdentity();
1303 try {
1304 AppSearchUserInstance instance =
1305 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1306 instance.getAppSearchImpl().removeObserver(
1307 observedPackage,
1308 new AppSearchObserverProxy(observerProxyStub));
1309 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1310 } finally {
1311 Binder.restoreCallingIdentity(callingIdentity);
1312 }
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001313 } catch (Throwable t) {
1314 return new AppSearchResultParcel<>(throwableToFailedResult(t));
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001315 }
1316 }
1317
1318 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001319 public void initialize(
Terry Wang70000152022-02-03 02:22:24 -08001320 @NonNull AttributionSource callerAttributionSource,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001321 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001322 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1323 @NonNull IAppSearchResultCallback callback) {
Terry Wang70000152022-02-03 02:22:24 -08001324 Objects.requireNonNull(callerAttributionSource);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001325 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001326 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001327
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001328 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001329 UserHandle targetUser = mServiceImplHelper.verifyIncomingCallWithCallback(
1330 callerAttributionSource, userHandle, callback);
1331 if (targetUser == null) {
1332 return; // Verification failed; verifyIncomingCall triggered callback.
1333 }
1334 mServiceImplHelper.executeLambdaForUserAsync(targetUser, callback, () -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001335 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001336 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001337 int operationSuccessCount = 0;
1338 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001339 try {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001340 Context targetUserContext = mContext.createContextAsUser(targetUser,
1341 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001342 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001343 targetUserContext,
1344 targetUser,
1345 AppSearchConfig.getInstance(SHARED_EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001346 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001347 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1348 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001349 ++operationFailureCount;
1350 statusCode = throwableToFailedResult(t).getResultCode();
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001351 invokeCallbackOnResult(callback, throwableToFailedResult(t));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001352 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001353 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001354 int estimatedBinderLatencyMillis =
1355 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1356 int totalLatencyMillis =
1357 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001358 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001359 .setStatusCode(statusCode)
1360 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001361 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1362 // TODO(b/173532925) check the existing binder call latency chart
1363 // is good enough for us:
1364 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1365 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1366 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001367 .setNumOperationsFailed(operationFailureCount)
1368 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001369 }
Terry Wange04ceab2021-03-29 19:25:12 -07001370 }
1371 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001372 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001373 }
1374
Yang Yu0fcd51a2021-04-23 11:25:44 -07001375 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1376 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001377 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001378 @NonNull PackageStats stats,
1379 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001380 @NonNull UserHandle userHandle,
1381 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001382 Objects.requireNonNull(stats);
1383 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001384 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001385
Yang Yu0fcd51a2021-04-23 11:25:44 -07001386 try {
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001387 mServiceImplHelper.verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001388 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001389 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1390 if (instance == null) {
1391 // augment storage info from file
1392 UserStorageInfo userStorageInfo =
1393 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1394 userHandle);
1395 stats.dataSize +=
1396 userStorageInfo.getSizeBytesForPackage(packageName);
1397 } else {
1398 stats.dataSize += instance.getAppSearchImpl()
1399 .getStorageInfoForPackage(packageName).getSizeBytes();
1400 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001401 } catch (Throwable t) {
1402 Log.e(
1403 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001404 "Unable to augment storage stats for "
1405 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001406 + " packageName "
1407 + packageName,
1408 t);
1409 }
1410 }
1411
1412 @Override
1413 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001414 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001415 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001416
1417 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001418 try {
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001419 mServiceImplHelper.verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001420 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1421 if (packagesForUid == null) {
1422 return;
1423 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001424 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001425 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1426 if (instance == null) {
1427 // augment storage info from file
1428 UserStorageInfo userStorageInfo =
1429 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1430 userHandle);
1431 for (int i = 0; i < packagesForUid.length; i++) {
1432 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1433 packagesForUid[i]);
1434 }
1435 } else {
1436 for (int i = 0; i < packagesForUid.length; i++) {
1437 stats.dataSize += instance.getAppSearchImpl()
1438 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1439 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001440 }
1441 } catch (Throwable t) {
1442 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1443 }
1444 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001445
1446 @Override
1447 public void augmentStatsForUser(
1448 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1449 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1450 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1451 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1452 Objects.requireNonNull(stats);
1453 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001454
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001455 try {
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001456 mServiceImplHelper.verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001457 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001458 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1459 if (instance == null) {
1460 // augment storage info from file
1461 UserStorageInfo userStorageInfo =
1462 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1463 userHandle);
1464 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1465 } else {
1466 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1467 /*flags=*/0, userHandle.getIdentifier());
1468 if (packagesForUser != null) {
1469 for (int i = 0; i < packagesForUser.size(); i++) {
1470 String packageName = packagesForUser.get(i).packageName;
1471 stats.dataSize += instance.getAppSearchImpl()
1472 .getStorageInfoForPackage(packageName).getSizeBytes();
1473 }
1474 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001475 }
1476 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001477 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001478 }
1479 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001480 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001481
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001482 /**
1483 * Dispatches change notifications if there are any to dispatch.
1484 *
1485 * <p>This method is async; notifications are dispatched onto their own registered executors.
1486 *
1487 * <p>IMPORTANT: You must always call this within the background task that contains the
1488 * operation that mutated the index. If you called it outside of that task, it could start
1489 * before the task completes, causing notifications to be missed.
1490 */
1491 @WorkerThread
1492 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1493 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1494 }
1495
1496 @WorkerThread
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001497 private void checkForOptimize(
1498 @NonNull UserHandle targetUser,
1499 @NonNull AppSearchUserInstance instance,
1500 int mutateBatchSize) {
1501 mExecutorManager.getOrCreateUserExecutor(targetUser).execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001502 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1503 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001504 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001505 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001506 } catch (AppSearchException e) {
1507 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001508 } finally {
1509 OptimizeStats oStats = builder
1510 .setTotalLatencyMillis(
1511 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1512 .build();
1513 if (oStats.getOriginalDocumentCount() > 0) {
1514 // see if optimize has been run by checking originalDocumentCount
1515 instance.getLogger().logStats(oStats);
1516 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001517 }
1518 });
1519 }
1520
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001521 @WorkerThread
Alexander Dorokhine872129a2022-02-22 16:36:36 -08001522 private void checkForOptimize(
1523 @NonNull UserHandle targetUser,
1524 @NonNull AppSearchUserInstance instance) {
1525 mExecutorManager.getOrCreateUserExecutor(targetUser).execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001526 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1527 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001528 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001529 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001530 } catch (AppSearchException e) {
1531 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001532 } finally {
1533 OptimizeStats oStats = builder
1534 .setTotalLatencyMillis(
1535 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1536 .build();
1537 if (oStats.getOriginalDocumentCount() > 0) {
1538 // see if optimize has been run by checking originalDocumentCount
1539 instance.getLogger().logStats(oStats);
1540 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001541 }
1542 });
1543 }
Terry Wangfebbead2019-10-17 17:05:18 -07001544}