blob: 666d49770a707c3cd512cbf1229c2e387e3bc9c0 [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 Dorokhine5c416772021-06-04 09:05:00 -070021import android.Manifest;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080022import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080023import android.annotation.NonNull;
Alexander Dorokhine18465842020-01-21 01:08:57 -080024import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080025import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080026import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070027import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070028import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070029import android.app.appsearch.GetSchemaResponse;
Alexander Dorokhineab789062021-01-11 21:00:00 -080030import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070031import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070032import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080033import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070034import android.app.appsearch.StorageInfo;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070035import android.app.appsearch.aidl.AppSearchBatchResultParcel;
36import android.app.appsearch.aidl.AppSearchResultParcel;
37import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
38import android.app.appsearch.aidl.IAppSearchManager;
39import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070040import android.app.appsearch.exceptions.AppSearchException;
Terry Wang12dc6c02021-03-31 19:26:16 -070041import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070042import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070043import android.content.Intent;
44import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070045import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070046import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070047import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080048import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070049import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080050import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080051import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080052import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080053import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070054import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080055import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080056import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080057import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070058
Cassie Wang15c86972021-02-09 13:43:25 -080059import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070060import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070061import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080062import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070063import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Xiaoyu Jin10329472021-06-23 16:50:03 -070064import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070065import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070066import com.android.server.usage.StorageStatsManagerLocal;
67import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080068
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070069import com.google.android.icing.proto.PersistType;
70
Terry Wang623e3b02021-02-02 20:27:33 -080071import java.io.DataInputStream;
72import java.io.DataOutputStream;
73import java.io.EOFException;
74import java.io.FileInputStream;
75import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080076import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080077import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080078import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080079import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080080import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070081import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070082import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070083import java.util.concurrent.ThreadPoolExecutor;
84import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080085
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070086/**
87 * The main service implementation which contains AppSearch's platform functionality.
88 * @hide
89 */
Terry Wangfebbead2019-10-17 17:05:18 -070090public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070091 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070092 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070093 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070094 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070095 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -070096
Terry Wange04ceab2021-03-29 19:25:12 -070097 // Never call shutdownNow(). It will cancel the futures it's returned. And since
98 // Executor#execute won't return anything, we will hang forever waiting for the execution.
99 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
100 // mutate requests will need to gain write lock and query requests need to gain read lock.
101 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
102 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700103 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700104
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700105 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
106 // suffix refers to the fact that access to the field should be locked; unrelated to the
107 // unlocked status of users.
108 @GuardedBy("mUnlockedUsersLocked")
109 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800110
Terry Wangfebbead2019-10-17 17:05:18 -0700111 public AppSearchManagerService(Context context) {
112 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700113 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700114 }
115
116 @Override
117 public void onStart() {
118 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700119 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700120 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700121 mUserManager = mContext.getSystemService(UserManager.class);
122 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700123 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700124 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700125 }
126
Xiaoyu Jin10329472021-06-23 16:50:03 -0700127 @Override
128 public void onBootPhase(/* @BootPhase */ int phase) {
129 if (phase == PHASE_BOOT_COMPLETED) {
130 StatsCollector.getInstance(mContext, EXECUTOR);
131 }
132 }
133
Terry Wang12dc6c02021-03-31 19:26:16 -0700134 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700135 mContext.registerReceiverForAllUsers(
136 new UserActionReceiver(),
137 new IntentFilter(Intent.ACTION_USER_REMOVED),
138 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700139 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700140
141 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
142 // broadcasts
143 IntentFilter packageChangedFilter = new IntentFilter();
144 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
145 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
146 packageChangedFilter.addDataScheme("package");
147 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700148 mContext.registerReceiverForAllUsers(
149 new PackageChangedReceiver(),
150 packageChangedFilter,
151 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700152 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700153 }
154
155 private class UserActionReceiver extends BroadcastReceiver {
156 @Override
157 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700158 Objects.requireNonNull(context);
159 Objects.requireNonNull(intent);
160
Terry Wang12dc6c02021-03-31 19:26:16 -0700161 switch (intent.getAction()) {
162 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700163 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
164 if (userHandle == null) {
165 Log.e(TAG, "Extra "
166 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700167 return;
168 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700169 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700170 break;
171 default:
Terry Wange201dc02021-04-16 01:03:20 -0700172 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700173 }
174 }
175 }
176
177 /**
178 * Handles user removed action.
179 *
180 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
181 * "credential encrypted" system directory of each user. That directory will be auto-deleted
182 * when a user is removed.
183 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700184 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700185 *
186 * @see android.os.Environment#getDataSystemCeDirectory
187 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700188 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700189 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700190 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700191 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700192 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700193 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700194 }
195 }
196
197 private class PackageChangedReceiver extends BroadcastReceiver {
198 @Override
199 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700200 Objects.requireNonNull(context);
201 Objects.requireNonNull(intent);
202
Terry Wange201dc02021-04-16 01:03:20 -0700203 switch (intent.getAction()) {
204 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
205 case Intent.ACTION_PACKAGE_DATA_CLEARED:
206 String packageName = intent.getData().getSchemeSpecificPart();
207 if (packageName == null) {
208 Log.e(TAG, "Package name is missing in the intent: " + intent);
209 return;
210 }
211 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
212 if (uid == INVALID_UID) {
213 Log.e(TAG, "uid is missing in the intent: " + intent);
214 return;
215 }
216 handlePackageRemoved(packageName, uid);
217 break;
218 default:
219 Log.e(TAG, "Received unknown intent: " + intent);
220 }
221 }
222 }
223
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700224 private void handlePackageRemoved(@NonNull String packageName, int uid) {
225 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700226 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700227 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700228 // We cannot access a locked user's directry and remove package data from it.
229 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700230 return;
231 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700232 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700233 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700234 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700235 AppSearchUserInstance instance =
236 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700237 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700238 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700239 instance.getAppSearchImpl().clearPackageData(packageName);
240 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700241 }
242 } catch (Throwable t) {
243 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700244 }
Terry Wangfebbead2019-10-17 17:05:18 -0700245 }
246
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800247 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700248 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700249 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700250 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700251 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700252 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800253 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700254 EXECUTOR.execute(() -> {
255 try {
256 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700257 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700258 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700259 AppSearchUserInstance instance =
260 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700261 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
262 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700263 .getPackageManager()
264 .getInstalledPackages(/*flags=*/0);
265 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
266 for (int i = 0; i < installedPackageInfos.size(); i++) {
267 packagesToKeep.add(installedPackageInfos.get(i).packageName);
268 }
269 packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
270 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700271 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700272 }
273 } catch (Throwable t) {
274 Log.e(TAG, "Unable to prune packages for " + user, t);
275 }
276 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800277 }
278
Terry Wangde9f3382021-04-28 19:45:07 -0700279 @Override
280 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700281 Objects.requireNonNull(user);
282
283 synchronized (mUnlockedUsersLocked) {
284 UserHandle userHandle = user.getUserHandle();
285 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700286 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700287 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700288 } catch (Throwable t) {
289 Log.e(TAG, "Error handling user stopping.", t);
290 }
291 }
292 }
293
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700294 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
295 if (isUserLocked(callingUser)) {
296 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700297 }
298 }
299
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700300 private boolean isUserLocked(@NonNull UserHandle callingUser) {
301 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700302 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700303 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700304 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700305 }
306 // If the local copy says the user is locked, check with UM for the actual state,
307 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700308 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700309 }
310 }
311
Terry Wangfebbead2019-10-17 17:05:18 -0700312 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800313 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800314 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800315 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700316 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700317 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800318 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700319 @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800320 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700321 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700322 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700323 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800324 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700325 Objects.requireNonNull(packageName);
326 Objects.requireNonNull(databaseName);
327 Objects.requireNonNull(schemaBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700328 Objects.requireNonNull(schemasNotDisplayedBySystem);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700329 Objects.requireNonNull(schemasVisibleToPackagesBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700330 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700331 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700332
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700333 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800334 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700335 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700336 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700337 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700338 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700339 int operationSuccessCount = 0;
340 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700341 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700342 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700343 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700344 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
345 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700346 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
347 for (int i = 0; i < schemaBundles.size(); i++) {
348 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800349 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700350 Map<String, List<PackageIdentifier>> schemasVisibleToPackages =
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700351 new ArrayMap<>(schemasVisibleToPackagesBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700352 for (Map.Entry<String, List<Bundle>> entry :
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700353 schemasVisibleToPackagesBundles.entrySet()) {
Terry Wange04ceab2021-03-29 19:25:12 -0700354 List<PackageIdentifier> packageIdentifiers =
355 new ArrayList<>(entry.getValue().size());
356 for (int i = 0; i < entry.getValue().size(); i++) {
357 packageIdentifiers.add(
358 new PackageIdentifier(entry.getValue().get(i)));
359 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700360 schemasVisibleToPackages.put(entry.getKey(), packageIdentifiers);
Terry Wange04ceab2021-03-29 19:25:12 -0700361 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700362 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
363 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700364 packageName,
365 databaseName,
366 schemas,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700367 instance.getVisibilityStore(),
Terry Wange04ceab2021-03-29 19:25:12 -0700368 schemasNotDisplayedBySystem,
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700369 schemasVisibleToPackages,
Terry Wange04ceab2021-03-29 19:25:12 -0700370 forceOverride,
371 schemaVersion);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700372 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700373 invokeCallbackOnResult(callback,
374 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700375
376 // setSchema will sync the schemas in the request to AppSearch, any existing
377 // schemas which is not included in the request will be delete if we force
378 // override incompatible schemas. And all documents of these types will be
379 // deleted as well. We should checkForOptimize for these deletion.
380 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700381 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700382 ++operationFailureCount;
383 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700384 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700385 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700386 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700387 int estimatedBinderLatencyMillis =
388 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
389 int totalLatencyMillis =
390 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700391 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700392 .setPackageName(packageName)
393 .setDatabase(databaseName)
394 .setStatusCode(statusCode)
395 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700396 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
397 // TODO(b/173532925) check the existing binder call latency chart
398 // is good enough for us:
399 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
400 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
401 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700402 .setNumOperationsFailed(operationFailureCount)
403 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700404 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800405 }
Terry Wange04ceab2021-03-29 19:25:12 -0700406 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800407 }
408
409 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800410 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800411 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800412 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700413 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800414 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700415 Objects.requireNonNull(packageName);
416 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700417 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700418 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700419
Cassie Wangb0d60122021-03-30 12:38:46 -0700420 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700421 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700422 EXECUTOR.execute(() -> {
423 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700424 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700425 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700426 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
427 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700428 AppSearchUserInstance instance =
429 mAppSearchUserInstanceManager.getUserInstance(callingUser);
430 GetSchemaResponse response =
431 instance.getAppSearchImpl().getSchema(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700432 invokeCallbackOnResult(
433 callback,
434 AppSearchResult.newSuccessfulResult(response.getBundle()));
435 } catch (Throwable t) {
436 invokeCallbackOnError(callback, t);
437 }
438 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700439 }
440
441 @Override
442 public void getNamespaces(
443 @NonNull String packageName,
444 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700445 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700446 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700447 Objects.requireNonNull(packageName);
448 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700449 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700450 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700451
Cassie Wangb0d60122021-03-30 12:38:46 -0700452 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700453 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700454 EXECUTOR.execute(() -> {
455 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700456 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700457 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700458 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
459 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700460 AppSearchUserInstance instance =
461 mAppSearchUserInstanceManager.getUserInstance(callingUser);
462 List<String> namespaces =
463 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
464 invokeCallbackOnResult(
465 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700466 } catch (Throwable t) {
467 invokeCallbackOnError(callback, t);
468 }
469 });
Terry Wang83a24932020-12-09 21:00:18 -0800470 }
471
472 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800473 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800474 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700475 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700476 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700477 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800478 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800479 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700480 Objects.requireNonNull(packageName);
481 Objects.requireNonNull(databaseName);
482 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700483 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700484 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700485
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700486 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800487 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700488 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700489 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800490 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700491 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800492 int operationSuccessCount = 0;
493 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700494 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700495 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700496 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700497 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
498 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700499 AppSearchBatchResult.Builder<String, Void> resultBuilder =
500 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700501 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700502 for (int i = 0; i < documentBundles.size(); i++) {
503 GenericDocument document = new GenericDocument(documentBundles.get(i));
504 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700505 instance.getAppSearchImpl().putDocument(
506 packageName, databaseName, document, instance.getLogger());
507 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800508 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700509 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700510 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800511 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700512 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700513 // Since we can only include one status code in the atom,
514 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800515 statusCode = result.getResultCode();
516 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700517 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800518 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700519 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700520 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700521 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700522
523 // The existing documents with same ID will be deleted, so there may be some
524 // resources that could be released after optimize().
525 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700526 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700527 ++operationFailureCount;
528 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700529 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800530 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700531 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700532 int estimatedBinderLatencyMillis =
533 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
534 int totalLatencyMillis =
535 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700536 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700537 .setPackageName(packageName)
538 .setDatabase(databaseName)
539 .setStatusCode(statusCode)
540 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800541 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
542 // TODO(b/173532925) check the existing binder call latency chart
543 // is good enough for us:
544 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700545 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800546 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700547 .setNumOperationsFailed(operationFailureCount)
548 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800549 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800550 }
Terry Wange04ceab2021-03-29 19:25:12 -0700551 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800552 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800553
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800554 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800555 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800556 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800557 @NonNull String databaseName,
558 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700559 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800560 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700561 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700562 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800563 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700564 Objects.requireNonNull(packageName);
565 Objects.requireNonNull(databaseName);
566 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700567 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700568 Objects.requireNonNull(typePropertyPaths);
569 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700570 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700571
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700572 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800573 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700574 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700575 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700576 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700577 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700578 int operationSuccessCount = 0;
579 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700580 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700581 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700582 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700583 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
584 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700585 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
586 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700587 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700588 for (int i = 0; i < ids.size(); i++) {
589 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700590 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700591 GenericDocument document = instance.getAppSearchImpl().getDocument(
592 packageName,
593 databaseName,
594 namespace,
595 id,
596 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700597 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700598 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700599 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700600 // Since we can only include one status code in the atom,
601 // for failures, we would just save the one for the last failure
602 AppSearchResult<Bundle> result = throwableToFailedResult(t);
603 resultBuilder.setResult(id, result);
604 statusCode = result.getResultCode();
605 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700606 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800607 }
Terry Wange04ceab2021-03-29 19:25:12 -0700608 invokeCallbackOnResult(callback, resultBuilder.build());
609 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700610 ++operationFailureCount;
611 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700612 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700613 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700614 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700615 int estimatedBinderLatencyMillis =
616 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
617 int totalLatencyMillis =
618 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700619 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700620 .setPackageName(packageName)
621 .setDatabase(databaseName)
622 .setStatusCode(statusCode)
623 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700624 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
625 // TODO(b/173532925) check the existing binder call latency chart
626 // is good enough for us:
627 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
628 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
629 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700630 .setNumOperationsFailed(operationFailureCount)
631 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700632 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800633 }
Terry Wange04ceab2021-03-29 19:25:12 -0700634 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800635 }
636
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800637 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800638 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800639 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700640 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700641 @NonNull String queryExpression,
642 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700643 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700644 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700645 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700646 Objects.requireNonNull(packageName);
647 Objects.requireNonNull(databaseName);
648 Objects.requireNonNull(queryExpression);
649 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700650 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700651 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700652
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700653 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800654 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700655 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700656 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700657 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700658 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700659 int operationSuccessCount = 0;
660 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700661 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700662 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700663 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700664 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
665 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700666 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
667 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
668 packageName,
669 databaseName,
670 queryExpression,
671 new SearchSpec(searchSpecBundle),
672 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700673 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700674 invokeCallbackOnResult(
675 callback,
676 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
677 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700678 ++operationFailureCount;
679 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700680 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700681 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700682 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700683 int estimatedBinderLatencyMillis =
684 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
685 int totalLatencyMillis =
686 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700687 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700688 .setPackageName(packageName)
689 .setDatabase(databaseName)
690 .setStatusCode(statusCode)
691 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700692 .setCallType(CallStats.CALL_TYPE_SEARCH)
693 // TODO(b/173532925) check the existing binder call latency chart
694 // is good enough for us:
695 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
696 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
697 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700698 .setNumOperationsFailed(operationFailureCount)
699 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700700 }
Terry Wange04ceab2021-03-29 19:25:12 -0700701 }
702 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700703 }
704
Terry Wangf2093072020-11-30 04:47:19 -0800705 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800706 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800707 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800708 @NonNull String queryExpression,
709 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700710 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700711 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800712 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700713 Objects.requireNonNull(packageName);
714 Objects.requireNonNull(queryExpression);
715 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700716 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700717 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700718
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700719 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800720 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700721 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700722 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700723 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700724 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700725 int operationSuccessCount = 0;
726 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700727 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700728 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700729 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700730 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
731 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700732 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
733
734 boolean callerHasSystemAccess =
735 instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
736 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
737 queryExpression,
738 new SearchSpec(searchSpecBundle),
739 packageName,
740 instance.getVisibilityStore(),
741 callingUid,
742 callerHasSystemAccess,
743 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700744 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700745 invokeCallbackOnResult(
746 callback,
747 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700748 } catch (Throwable t) {
749 ++operationFailureCount;
750 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700751 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700752 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700753 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700754 int estimatedBinderLatencyMillis =
755 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
756 int totalLatencyMillis =
757 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700758 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700759 .setPackageName(packageName)
760 .setStatusCode(statusCode)
761 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700762 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
763 // TODO(b/173532925) check the existing binder call latency chart
764 // is good enough for us:
765 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
766 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
767 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700768 .setNumOperationsFailed(operationFailureCount)
769 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700770 }
Terry Wange04ceab2021-03-29 19:25:12 -0700771 }
772 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800773 }
774
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700775 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800776 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700777 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800778 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700779 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700780 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700781 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700782 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700783 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700784
Terry Wangf2093072020-11-30 04:47:19 -0800785 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700786 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700787 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
788 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700789 EXECUTOR.execute(() -> {
790 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700791 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700792 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700793 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
794 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700795 AppSearchUserInstance instance =
796 mAppSearchUserInstanceManager.getUserInstance(callingUser);
797 SearchResultPage searchResultPage =
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700798 instance.getAppSearchImpl().getNextPage(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700799 invokeCallbackOnResult(
800 callback,
801 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
802 } catch (Throwable t) {
803 invokeCallbackOnError(callback, t);
804 }
805 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700806 }
807
808 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700809 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
810 @NonNull UserHandle userHandle) {
811 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700812 Objects.requireNonNull(userHandle);
813
Terry Wangf2093072020-11-30 04:47:19 -0800814 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700815 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700816 EXECUTOR.execute(() -> {
817 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700818 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700819 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700820 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
821 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700822 AppSearchUserInstance instance =
823 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700824 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700825 } catch (Throwable t) {
826 Log.e(TAG, "Unable to invalidate the query page token", t);
827 }
828 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800829 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800830
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700831 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800832 public void writeQueryResultsToFile(
833 @NonNull String packageName,
834 @NonNull String databaseName,
835 @NonNull ParcelFileDescriptor fileDescriptor,
836 @NonNull String queryExpression,
837 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700838 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800839 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700840 Objects.requireNonNull(packageName);
841 Objects.requireNonNull(databaseName);
842 Objects.requireNonNull(fileDescriptor);
843 Objects.requireNonNull(queryExpression);
844 Objects.requireNonNull(searchSpecBundle);
845 Objects.requireNonNull(userHandle);
846 Objects.requireNonNull(callback);
847
Terry Wang623e3b02021-02-02 20:27:33 -0800848 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700849 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700850 EXECUTOR.execute(() -> {
851 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700852 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
853 verifyUserUnlocked(callingUser);
854 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
855 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700856 AppSearchUserInstance instance =
857 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700858 // we don't need to append the file. The file is always brand new.
859 try (DataOutputStream outputStream = new DataOutputStream(
860 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700861 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700862 packageName,
863 databaseName,
864 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700865 new SearchSpec(searchSpecBundle),
866 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700867 while (!searchResultPage.getResults().isEmpty()) {
868 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
869 AppSearchMigrationHelper.writeBundleToOutputStream(
870 outputStream, searchResultPage.getResults().get(i)
871 .getGenericDocument().getBundle());
872 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700873 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700874 packageName, searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800875 }
Terry Wang623e3b02021-02-02 20:27:33 -0800876 }
Terry Wange04ceab2021-03-29 19:25:12 -0700877 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
878 } catch (Throwable t) {
879 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800880 }
Terry Wange04ceab2021-03-29 19:25:12 -0700881 });
Terry Wang623e3b02021-02-02 20:27:33 -0800882 }
883
884 @Override
885 public void putDocumentsFromFile(
886 @NonNull String packageName,
887 @NonNull String databaseName,
888 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700889 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800890 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700891 Objects.requireNonNull(packageName);
892 Objects.requireNonNull(databaseName);
893 Objects.requireNonNull(fileDescriptor);
894 Objects.requireNonNull(userHandle);
895 Objects.requireNonNull(callback);
896
Terry Wang623e3b02021-02-02 20:27:33 -0800897 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700898 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700899 EXECUTOR.execute(() -> {
900 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700901 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
902 verifyUserUnlocked(callingUser);
903 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
904 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700905 AppSearchUserInstance instance =
906 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800907
Terry Wange04ceab2021-03-29 19:25:12 -0700908 GenericDocument document;
909 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
910 try (DataInputStream inputStream = new DataInputStream(
911 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
912 while (true) {
913 try {
914 document = AppSearchMigrationHelper
915 .readDocumentFromInputStream(inputStream);
916 } catch (EOFException e) {
917 // nothing wrong, we just finish the reading.
918 break;
919 }
920 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700921 instance.getAppSearchImpl().putDocument(
922 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700923 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700924 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
925 document.getNamespace(),
926 document.getId(),
927 document.getSchemaType(),
928 AppSearchResult.throwableToFailedResult(t))
929 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700930 }
Terry Wang623e3b02021-02-02 20:27:33 -0800931 }
932 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700933 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700934 invokeCallbackOnResult(callback,
935 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
936 } catch (Throwable t) {
937 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800938 }
Terry Wange04ceab2021-03-29 19:25:12 -0700939 });
Terry Wang623e3b02021-02-02 20:27:33 -0800940 }
941
942 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800943 public void reportUsage(
944 @NonNull String packageName,
945 @NonNull String databaseName,
946 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700947 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800948 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700949 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700950 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800951 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700952 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800953 Objects.requireNonNull(databaseName);
954 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700955 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700956 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800957 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700958
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800959 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700960 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700961 EXECUTOR.execute(() -> {
962 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700963 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700964 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700965 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
966 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700967 AppSearchUserInstance instance =
968 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700969
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700970 if (systemUsage
971 && !instance.getVisibilityStore()
972 .doesCallerHaveSystemAccess(packageName)) {
973 throw new AppSearchException(
974 AppSearchResult.RESULT_SECURITY_ERROR,
975 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -0700976 }
977
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700978 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700979 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -0700980 usageTimeMillis, systemUsage);
981 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700982 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -0700983 } catch (Throwable t) {
984 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700985 }
Terry Wange04ceab2021-03-29 19:25:12 -0700986 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800987 }
988
989 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700990 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -0800991 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800992 @NonNull String databaseName,
993 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700994 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700995 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700996 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800997 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700998 Objects.requireNonNull(packageName);
999 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001000 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001001 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001002 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001003 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001004
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001005 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001006 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001007 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001008 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001009 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001010 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001011 int operationSuccessCount = 0;
1012 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001013 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001014 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001015 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001016 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1017 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -07001018 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1019 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001020 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001021 for (int i = 0; i < ids.size(); i++) {
1022 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001023 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001024 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001025 packageName,
1026 databaseName,
1027 namespace,
1028 id,
1029 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001030 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001031 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001032 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001033 AppSearchResult<Void> result = throwableToFailedResult(t);
1034 resultBuilder.setResult(id, result);
1035 // Since we can only include one status code in the atom,
1036 // for failures, we would just save the one for the last failure
1037 statusCode = result.getResultCode();
1038 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001039 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001040 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001041 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001042 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001043 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001044
1045 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001046 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001047 ++operationFailureCount;
1048 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001049 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001050 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001051 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001052 int estimatedBinderLatencyMillis =
1053 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1054 int totalLatencyMillis =
1055 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001056 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001057 .setPackageName(packageName)
1058 .setDatabase(databaseName)
1059 .setStatusCode(statusCode)
1060 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001061 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1062 // TODO(b/173532925) check the existing binder call latency chart
1063 // is good enough for us:
1064 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1065 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1066 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001067 .setNumOperationsFailed(operationFailureCount)
1068 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001069 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001070 }
Terry Wange04ceab2021-03-29 19:25:12 -07001071 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001072 }
1073
1074 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001075 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001076 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001077 @NonNull String databaseName,
1078 @NonNull String queryExpression,
1079 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001080 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001081 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001082 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001083 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001084 Objects.requireNonNull(packageName);
1085 Objects.requireNonNull(databaseName);
1086 Objects.requireNonNull(queryExpression);
1087 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001088 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001089 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001090
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001091 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001092 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001093 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001094 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001095 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001096 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001097 int operationSuccessCount = 0;
1098 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001099 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001100 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001101 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001102 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1103 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001104 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
1105 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001106 packageName,
1107 databaseName,
1108 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001109 new SearchSpec(searchSpecBundle),
1110 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001111 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001112 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001113 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001114 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001115
1116 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001117 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001118 ++operationFailureCount;
1119 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001120 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001121 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001122 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001123 int estimatedBinderLatencyMillis =
1124 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1125 int totalLatencyMillis =
1126 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001127 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001128 .setPackageName(packageName)
1129 .setDatabase(databaseName)
1130 .setStatusCode(statusCode)
1131 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001132 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1133 // TODO(b/173532925) check the existing binder call latency chart
1134 // is good enough for us:
1135 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1136 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1137 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001138 .setNumOperationsFailed(operationFailureCount)
1139 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001140 }
Terry Wange04ceab2021-03-29 19:25:12 -07001141 }
1142 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001143 }
1144
Terry Wangdbd1dca2020-11-03 17:03:56 -08001145 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001146 public void getStorageInfo(
1147 @NonNull String packageName,
1148 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001149 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001150 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001151 Objects.requireNonNull(packageName);
1152 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001153 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001154 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001155
Cassie Wang8f0df492021-03-24 09:23:18 -07001156 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001157 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001158 EXECUTOR.execute(() -> {
1159 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001160 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001161 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001162 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1163 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001164 AppSearchUserInstance instance =
1165 mAppSearchUserInstanceManager.getUserInstance(callingUser);
1166 StorageInfo storageInfo = instance.getAppSearchImpl()
1167 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001168 Bundle storageInfoBundle = storageInfo.getBundle();
1169 invokeCallbackOnResult(
1170 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1171 } catch (Throwable t) {
1172 invokeCallbackOnError(callback, t);
1173 }
1174 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001175 }
1176
1177 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001178 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001179 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001180 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001181 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001182 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001183 Objects.requireNonNull(userHandle);
1184
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001185 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wangb0d60122021-03-30 12:38:46 -07001186 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001187 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001188 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001189 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001190 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001191 int operationSuccessCount = 0;
1192 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001193 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001194 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001195 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001196 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1197 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001198 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
1199 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001200 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001201 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001202 ++operationFailureCount;
1203 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001204 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001205 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001206 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001207 int estimatedBinderLatencyMillis =
1208 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1209 int totalLatencyMillis =
1210 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001211 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001212 .setStatusCode(statusCode)
1213 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001214 .setCallType(CallStats.CALL_TYPE_FLUSH)
1215 // TODO(b/173532925) check the existing binder call latency chart
1216 // is good enough for us:
1217 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1218 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1219 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001220 .setNumOperationsFailed(operationFailureCount)
1221 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001222 }
Terry Wange04ceab2021-03-29 19:25:12 -07001223 }
1224 });
Terry Wang2da17852020-12-16 19:59:08 -08001225 }
1226
1227 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001228 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001229 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001230 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001231 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1232 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001233 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001234 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001235 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001236
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001237 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001238 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001239 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Cassie Wang84e33a02021-06-18 14:13:31 -07001240
Terry Wange04ceab2021-03-29 19:25:12 -07001241 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001242 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001243 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001244 int operationSuccessCount = 0;
1245 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001246 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001247 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001248 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001249 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1250 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001251 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001252 userContext, callingUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001253 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001254 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1255 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001256 ++operationFailureCount;
1257 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001258 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001259 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001260 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001261 int estimatedBinderLatencyMillis =
1262 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1263 int totalLatencyMillis =
1264 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001265 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001266 .setStatusCode(statusCode)
1267 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001268 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1269 // TODO(b/173532925) check the existing binder call latency chart
1270 // is good enough for us:
1271 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1272 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1273 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001274 .setNumOperationsFailed(operationFailureCount)
1275 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001276 }
Terry Wange04ceab2021-03-29 19:25:12 -07001277 }
1278 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001279 }
1280
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001281 private void verifyCallingPackage(
Cassie Wang84e33a02021-06-18 14:13:31 -07001282 @NonNull Context userContext,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001283 @NonNull UserHandle actualCallingUser,
1284 int actualCallingUid,
1285 @NonNull String claimedCallingPackage) {
1286 Objects.requireNonNull(actualCallingUser);
1287 Objects.requireNonNull(claimedCallingPackage);
1288
Cassie Wang84e33a02021-06-18 14:13:31 -07001289 int claimedCallingUid = PackageUtil.getPackageUid(
1290 userContext, claimedCallingPackage);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001291 if (claimedCallingUid == INVALID_UID) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001292 throw new SecurityException(
1293 "Specified calling package [" + claimedCallingPackage + "] not found");
1294 }
1295 if (claimedCallingUid != actualCallingUid) {
Cassie Wang0c62d992021-01-15 14:39:30 -08001296 throw new SecurityException(
1297 "Specified calling package ["
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001298 + claimedCallingPackage
Cassie Wang0c62d992021-01-15 14:39:30 -08001299 + "] does not match the calling uid "
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001300 + actualCallingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001301 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001302 }
1303
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001304 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001305 private void invokeCallbackOnResult(
1306 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001307 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001308 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001309 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001310 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001311 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001312 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001313
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001314 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001315 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001316 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001317 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001318 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001319 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001320 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001321 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001322 }
1323
1324 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001325 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001326 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001327 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001328 */
1329 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001330 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001331 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001332 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001333 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001334 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001335 }
1336 }
1337
1338 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001339 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001340 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001341 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001342 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001343 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001344 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001345 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001346 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001347 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001348 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001349 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001350 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001351 }
Terry Wangfebbead2019-10-17 17:05:18 -07001352 }
Terry Wangf2093072020-11-30 04:47:19 -08001353
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001354 /**
1355 * Helper for dealing with incoming user arguments to system service calls.
1356 *
1357 * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
1358 *
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001359 * @param requestedUser The user which the caller is requesting to execute as.
1360 * @param callingUid The actual uid of the caller as determined by Binder.
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001361 * @return the user handle that the call should run as. Will always be a concrete user.
1362 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001363 @NonNull
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001364 private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
Terry Wangf2093072020-11-30 04:47:19 -08001365 int callingPid = Binder.getCallingPid();
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001366 UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
1367 if (callingUser.equals(requestedUser)) {
1368 return requestedUser;
1369 }
1370 // Duplicates UserController#ensureNotSpecialUser
1371 if (requestedUser.getIdentifier() < 0) {
1372 throw new IllegalArgumentException(
1373 "Call does not support special user " + requestedUser);
1374 }
1375 boolean canInteractAcrossUsers = mContext.checkPermission(
1376 Manifest.permission.INTERACT_ACROSS_USERS,
Cassie Wang0c62d992021-01-15 14:39:30 -08001377 callingPid,
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001378 callingUid) == PackageManager.PERMISSION_GRANTED;
1379 if (!canInteractAcrossUsers) {
1380 canInteractAcrossUsers = mContext.checkPermission(
1381 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1382 callingPid,
1383 callingUid) == PackageManager.PERMISSION_GRANTED;
1384 }
1385 if (canInteractAcrossUsers) {
1386 return requestedUser;
1387 }
1388 throw new SecurityException(
1389 "Permission denied while calling from uid " + callingUid
1390 + " with " + requestedUser + "; Need to run as either the calling user ("
1391 + callingUser + "), or with one of the following permissions: "
1392 + Manifest.permission.INTERACT_ACROSS_USERS + " or "
1393 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001394 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001395
Cassie Wang84e33a02021-06-18 14:13:31 -07001396 /**
1397 * Helper for ensuring instant apps can't make calls to AppSearch.
1398 *
1399 * @param userContext Context of the user making the call.
1400 * @param packageName Package name of the caller.
1401 * @throws SecurityException if the caller is an instant app.
1402 */
1403 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1404 PackageManager callingPackageManager = userContext.getPackageManager();
1405 if (callingPackageManager.isInstantApp(packageName)) {
1406 throw new SecurityException("Caller not allowed to create AppSearch session"
1407 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1408 }
1409 }
1410
Yang Yu0fcd51a2021-04-23 11:25:44 -07001411 // TODO(b/179160886): Cache the previous storage stats.
1412 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1413 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001414 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001415 @NonNull PackageStats stats,
1416 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001417 @NonNull UserHandle userHandle,
1418 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001419 Objects.requireNonNull(stats);
1420 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001421 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001422
Yang Yu0fcd51a2021-04-23 11:25:44 -07001423 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001424 verifyUserUnlocked(userHandle);
Cassie Wang84e33a02021-06-18 14:13:31 -07001425 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001426 AppSearchUserInstance instance =
1427 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001428 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001429 stats.dataSize += instance.getAppSearchImpl()
1430 .getStorageInfoForPackage(packageName).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001431 } catch (Throwable t) {
1432 Log.e(
1433 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001434 "Unable to augment storage stats for "
1435 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001436 + " packageName "
1437 + packageName,
1438 t);
1439 }
1440 }
1441
1442 @Override
1443 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001444 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001445 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001446
1447 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001448 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001449 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001450 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1451 if (packagesForUid == null) {
1452 return;
1453 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001454 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001455 AppSearchUserInstance instance =
1456 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001457 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001458 for (int i = 0; i < packagesForUid.length; i++) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001459 stats.dataSize += instance.getAppSearchImpl()
1460 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001461 }
1462 } catch (Throwable t) {
1463 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1464 }
1465 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001466
1467 @Override
1468 public void augmentStatsForUser(
1469 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1470 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1471 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1472 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1473 Objects.requireNonNull(stats);
1474 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001475
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001476 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001477 verifyUserUnlocked(userHandle);
1478 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1479 /*flags=*/0, userHandle.getIdentifier());
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001480 if (packagesForUser == null) {
1481 return;
1482 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001483 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001484 AppSearchUserInstance instance =
1485 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001486 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001487 for (int i = 0; i < packagesForUser.size(); i++) {
1488 String packageName = packagesForUser.get(i).packageName;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001489 stats.dataSize += instance.getAppSearchImpl()
1490 .getStorageInfoForPackage(packageName).getSizeBytes();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001491 }
1492 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001493 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001494 }
1495 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001496 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001497
1498 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1499 EXECUTOR.execute(() -> {
1500 try {
1501 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize);
1502 } catch (AppSearchException e) {
1503 Log.w(TAG, "Error occurred when check for optimize", e);
1504 }
1505 });
1506 }
1507
1508 private void checkForOptimize(AppSearchUserInstance instance) {
1509 EXECUTOR.execute(() -> {
1510 try {
1511 instance.getAppSearchImpl().checkForOptimize();
1512 } catch (AppSearchException e) {
1513 Log.w(TAG, "Error occurred when check for optimize", e);
1514 }
1515 });
1516 }
Terry Wangfebbead2019-10-17 17:05:18 -07001517}