blob: f61fc154f0fae8810dc8c9149e77ebce07319d07 [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
Cassie Wang2e2d0552021-08-04 16:18:10 +000021import android.Manifest;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080022import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080023import android.annotation.NonNull;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080024import android.annotation.WorkerThread;
Alexander Dorokhine18465842020-01-21 01:08:57 -080025import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080026import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080027import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070028import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070029import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070030import android.app.appsearch.GetSchemaResponse;
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;
Terry Wang5b0c5612021-12-23 15:57:19 -080035import android.app.appsearch.VisibilityDocument;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070036import android.app.appsearch.aidl.AppSearchBatchResultParcel;
37import android.app.appsearch.aidl.AppSearchResultParcel;
38import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
39import android.app.appsearch.aidl.IAppSearchManager;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080040import android.app.appsearch.aidl.IAppSearchObserverProxy;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070041import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070042import android.app.appsearch.exceptions.AppSearchException;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080043import android.app.appsearch.observer.AppSearchObserverCallback;
44import android.app.appsearch.observer.DocumentChangeInfo;
45import android.app.appsearch.observer.ObserverSpec;
46import android.app.appsearch.observer.SchemaChangeInfo;
Terry Wang12dc6c02021-03-31 19:26:16 -070047import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070048import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070049import android.content.Intent;
50import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070051import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070052import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070053import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080054import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070055import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080056import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080057import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080058import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080059import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070060import android.os.UserManager;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080061import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080062import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070063
Cassie Wang15c86972021-02-09 13:43:25 -080064import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070065import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070066import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080067import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine14816e22021-07-12 10:53:24 -070068import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070069import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080070import com.android.server.appsearch.observer.AppSearchObserverProxy;
Xiaoyu Jin10329472021-06-23 16:50:03 -070071import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070072import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070073import com.android.server.usage.StorageStatsManagerLocal;
74import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080075
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070076import com.google.android.icing.proto.PersistType;
77
Terry Wang623e3b02021-02-02 20:27:33 -080078import java.io.DataInputStream;
79import java.io.DataOutputStream;
80import java.io.EOFException;
81import java.io.FileInputStream;
82import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080083import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080084import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080085import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080086import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080087import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070088import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070089import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070090import java.util.concurrent.ThreadPoolExecutor;
91import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080092
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070093/**
94 * The main service implementation which contains AppSearch's platform functionality.
Yang Yuc047f7b2021-06-25 12:22:42 -070095 *
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070096 * @hide
97 */
Terry Wangfebbead2019-10-17 17:05:18 -070098public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070099 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -0700100 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700101 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700102 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700103 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -0700104
Terry Wange04ceab2021-03-29 19:25:12 -0700105 // Never call shutdownNow(). It will cancel the futures it's returned. And since
106 // Executor#execute won't return anything, we will hang forever waiting for the execution.
107 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
108 // mutate requests will need to gain write lock and query requests need to gain read lock.
109 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
110 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700111 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700112
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700113 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
114 // suffix refers to the fact that access to the field should be locked; unrelated to the
115 // unlocked status of users.
116 @GuardedBy("mUnlockedUsersLocked")
117 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800118
Terry Wangfebbead2019-10-17 17:05:18 -0700119 public AppSearchManagerService(Context context) {
120 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700121 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700122 }
123
124 @Override
125 public void onStart() {
126 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700127 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700128 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700129 mUserManager = mContext.getSystemService(UserManager.class);
130 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700131 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700132 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700133 }
134
Xiaoyu Jin10329472021-06-23 16:50:03 -0700135 @Override
136 public void onBootPhase(/* @BootPhase */ int phase) {
137 if (phase == PHASE_BOOT_COMPLETED) {
138 StatsCollector.getInstance(mContext, EXECUTOR);
139 }
140 }
141
Terry Wang12dc6c02021-03-31 19:26:16 -0700142 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700143 mContext.registerReceiverForAllUsers(
144 new UserActionReceiver(),
145 new IntentFilter(Intent.ACTION_USER_REMOVED),
146 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700147 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700148
149 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
150 // broadcasts
151 IntentFilter packageChangedFilter = new IntentFilter();
152 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
153 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
154 packageChangedFilter.addDataScheme("package");
155 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700156 mContext.registerReceiverForAllUsers(
157 new PackageChangedReceiver(),
158 packageChangedFilter,
159 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700160 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700161 }
162
163 private class UserActionReceiver extends BroadcastReceiver {
164 @Override
165 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700166 Objects.requireNonNull(context);
167 Objects.requireNonNull(intent);
168
Terry Wang12dc6c02021-03-31 19:26:16 -0700169 switch (intent.getAction()) {
170 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700171 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
172 if (userHandle == null) {
173 Log.e(TAG, "Extra "
174 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700175 return;
176 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700177 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700178 break;
179 default:
Terry Wange201dc02021-04-16 01:03:20 -0700180 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700181 }
182 }
183 }
184
185 /**
186 * Handles user removed action.
187 *
188 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
189 * "credential encrypted" system directory of each user. That directory will be auto-deleted
190 * when a user is removed.
191 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700192 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700193 * @see android.os.Environment#getDataSystemCeDirectory
194 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700195 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700196 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700197 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700198 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700199 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700200 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700201 }
202 }
203
204 private class PackageChangedReceiver extends BroadcastReceiver {
205 @Override
206 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700207 Objects.requireNonNull(context);
208 Objects.requireNonNull(intent);
209
Terry Wange201dc02021-04-16 01:03:20 -0700210 switch (intent.getAction()) {
211 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
212 case Intent.ACTION_PACKAGE_DATA_CLEARED:
213 String packageName = intent.getData().getSchemeSpecificPart();
214 if (packageName == null) {
215 Log.e(TAG, "Package name is missing in the intent: " + intent);
216 return;
217 }
218 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
219 if (uid == INVALID_UID) {
220 Log.e(TAG, "uid is missing in the intent: " + intent);
221 return;
222 }
223 handlePackageRemoved(packageName, uid);
224 break;
225 default:
226 Log.e(TAG, "Received unknown intent: " + intent);
227 }
228 }
229 }
230
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700231 private void handlePackageRemoved(@NonNull String packageName, int uid) {
232 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700233 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700234 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700235 // We cannot access a locked user's directry and remove package data from it.
236 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700237 return;
238 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700239 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700240 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700241 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700242 AppSearchUserInstance instance =
243 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700244 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700245 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700246 instance.getAppSearchImpl().clearPackageData(packageName);
247 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700248 }
249 } catch (Throwable t) {
250 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700251 }
Terry Wangfebbead2019-10-17 17:05:18 -0700252 }
253
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800254 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700255 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700256 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700257 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700258 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700259 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800260 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700261 EXECUTOR.execute(() -> {
262 try {
263 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700264 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700265 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700266 AppSearchUserInstance instance =
267 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700268 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
269 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700270 .getPackageManager()
271 .getInstalledPackages(/*flags=*/0);
272 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
273 for (int i = 0; i < installedPackageInfos.size(); i++) {
274 packagesToKeep.add(installedPackageInfos.get(i).packageName);
275 }
276 packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
277 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700278 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700279 }
280 } catch (Throwable t) {
281 Log.e(TAG, "Unable to prune packages for " + user, t);
282 }
283 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800284 }
285
Terry Wangde9f3382021-04-28 19:45:07 -0700286 @Override
287 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700288 Objects.requireNonNull(user);
289
290 synchronized (mUnlockedUsersLocked) {
291 UserHandle userHandle = user.getUserHandle();
292 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700293 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700294 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700295 } catch (Throwable t) {
296 Log.e(TAG, "Error handling user stopping.", t);
297 }
298 }
299 }
300
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700301 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
302 if (isUserLocked(callingUser)) {
303 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700304 }
305 }
306
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700307 private boolean isUserLocked(@NonNull UserHandle callingUser) {
308 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700309 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700310 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700311 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700312 }
313 // If the local copy says the user is locked, check with UM for the actual state,
314 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700315 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700316 }
317 }
318
Terry Wangfebbead2019-10-17 17:05:18 -0700319 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800320 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800321 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800322 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700323 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700324 @NonNull List<Bundle> schemaBundles,
Terry Wang5b0c5612021-12-23 15:57:19 -0800325 @NonNull List<Bundle> visibilityBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800326 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700327 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700328 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700329 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800330 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700331 Objects.requireNonNull(packageName);
332 Objects.requireNonNull(databaseName);
333 Objects.requireNonNull(schemaBundles);
Terry Wang5b0c5612021-12-23 15:57:19 -0800334 Objects.requireNonNull(visibilityBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700335 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700336 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700337
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700338 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000339 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800340 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700341 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700342 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700343 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700344 int operationSuccessCount = 0;
345 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700346 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000347 verifyCaller(callingUid, packageName);
348
349 // Obtain the user where the client wants to run the operations in. This should
350 // end up being the same as userHandle, assuming it is not a special user and
351 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000352 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000353 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000354
Terry Wange04ceab2021-03-29 19:25:12 -0700355 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
356 for (int i = 0; i < schemaBundles.size(); i++) {
357 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800358 }
Terry Wang5b0c5612021-12-23 15:57:19 -0800359 List<VisibilityDocument> visibilityDocuments =
360 new ArrayList<>(visibilityBundles.size());
361 for (int i = 0; i < visibilityBundles.size(); i++) {
362 visibilityDocuments.add(
363 new VisibilityDocument(visibilityBundles.get(i)));
Terry Wange04ceab2021-03-29 19:25:12 -0700364 }
Cassie Wang2feb34d2021-07-22 18:55:19 +0000365 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700366 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700367 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700368 packageName,
369 databaseName,
370 schemas,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700371 instance.getVisibilityStore(),
Terry Wange15ea582021-10-21 18:59:21 -0700372 visibilityDocuments,
Terry Wange04ceab2021-03-29 19:25:12 -0700373 forceOverride,
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700374 schemaVersion,
375 /*setSchemaStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700376 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700377 invokeCallbackOnResult(callback,
378 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700379
380 // setSchema will sync the schemas in the request to AppSearch, any existing
381 // schemas which is not included in the request will be delete if we force
382 // override incompatible schemas. And all documents of these types will be
383 // deleted as well. We should checkForOptimize for these deletion.
384 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700385 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700386 ++operationFailureCount;
387 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700388 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700389 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700390 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700391 int estimatedBinderLatencyMillis =
392 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
393 int totalLatencyMillis =
394 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700395 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700396 .setPackageName(packageName)
397 .setDatabase(databaseName)
398 .setStatusCode(statusCode)
399 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700400 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
401 // TODO(b/173532925) check the existing binder call latency chart
402 // is good enough for us:
403 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
404 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
405 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700406 .setNumOperationsFailed(operationFailureCount)
407 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700408 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800409 }
Terry Wange04ceab2021-03-29 19:25:12 -0700410 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800411 }
412
413 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800414 public void getSchema(
Alexander Dorokhined41def42022-01-25 15:45:34 -0800415 @NonNull String callingPackageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800416 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800417 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700418 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800419 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800420 Objects.requireNonNull(callingPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700421 Objects.requireNonNull(packageName);
422 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700423 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700424 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700425
Cassie Wang2e2d0552021-08-04 16:18:10 +0000426 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700427 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700428 EXECUTOR.execute(() -> {
429 try {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800430 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000431
432 // Obtain the user where the client wants to run the operations in. This should
433 // end up being the same as userHandle, assuming it is not a special user and
434 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000435 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000436 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000437
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700438 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000439 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700440 GetSchemaResponse response =
Alexander Dorokhined41def42022-01-25 15:45:34 -0800441 instance.getAppSearchImpl().getSchema(
442 callingPackageName, packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700443 invokeCallbackOnResult(
444 callback,
445 AppSearchResult.newSuccessfulResult(response.getBundle()));
446 } catch (Throwable t) {
447 invokeCallbackOnError(callback, t);
448 }
449 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700450 }
451
452 @Override
453 public void getNamespaces(
454 @NonNull String packageName,
455 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700456 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700457 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700458 Objects.requireNonNull(packageName);
459 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700460 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700461 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700462
Cassie Wang2e2d0552021-08-04 16:18:10 +0000463 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700464 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700465 EXECUTOR.execute(() -> {
466 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000467 verifyCaller(callingUid, packageName);
468
469 // Obtain the user where the client wants to run the operations in. This should
470 // end up being the same as userHandle, assuming it is not a special user and
471 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000472 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000473 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000474
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700475 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000476 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700477 List<String> namespaces =
478 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
479 invokeCallbackOnResult(
480 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700481 } catch (Throwable t) {
482 invokeCallbackOnError(callback, t);
483 }
484 });
Terry Wang83a24932020-12-09 21:00:18 -0800485 }
486
487 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800488 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800489 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700490 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700491 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700492 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800493 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800494 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700495 Objects.requireNonNull(packageName);
496 Objects.requireNonNull(databaseName);
497 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700498 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700499 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700500
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700501 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000502 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800503 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700504 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800505 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700506 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800507 int operationSuccessCount = 0;
508 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700509 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000510 verifyCaller(callingUid, packageName);
511
512 // Obtain the user where the client wants to run the operations in. This should
513 // end up being the same as userHandle, assuming it is not a special user and
514 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000515 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000516 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000517
Terry Wange04ceab2021-03-29 19:25:12 -0700518 AppSearchBatchResult.Builder<String, Void> resultBuilder =
519 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000520 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700521 for (int i = 0; i < documentBundles.size(); i++) {
522 GenericDocument document = new GenericDocument(documentBundles.get(i));
523 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700524 instance.getAppSearchImpl().putDocument(
525 packageName, databaseName, document, instance.getLogger());
526 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800527 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700528 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700529 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800530 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700531 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700532 // Since we can only include one status code in the atom,
533 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800534 statusCode = result.getResultCode();
535 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700536 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800537 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700538 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700539 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700540 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700541
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800542 // Schedule a task to dispatch change notifications. See requirements for where
543 // the method is called documented in the method description.
544 dispatchChangeNotifications(instance);
545
Terry Wangf4d219b2021-07-01 19:11:39 -0700546 // The existing documents with same ID will be deleted, so there may be some
547 // resources that could be released after optimize().
548 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700549 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700550 ++operationFailureCount;
551 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700552 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800553 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700554 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700555 int estimatedBinderLatencyMillis =
556 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
557 int totalLatencyMillis =
558 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700559 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700560 .setPackageName(packageName)
561 .setDatabase(databaseName)
562 .setStatusCode(statusCode)
563 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800564 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
565 // TODO(b/173532925) check the existing binder call latency chart
566 // is good enough for us:
567 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700568 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800569 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700570 .setNumOperationsFailed(operationFailureCount)
571 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800572 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800573 }
Terry Wange04ceab2021-03-29 19:25:12 -0700574 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800575 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800576
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800577 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800578 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800579 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800580 @NonNull String databaseName,
581 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700582 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800583 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700584 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700585 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800586 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700587 Objects.requireNonNull(packageName);
588 Objects.requireNonNull(databaseName);
589 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700590 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700591 Objects.requireNonNull(typePropertyPaths);
592 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700593 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700594
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700595 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000596 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800597 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700598 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700599 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700600 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700601 int operationSuccessCount = 0;
602 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700603 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000604 verifyCaller(callingUid, packageName);
605
606 // Obtain the user where the client wants to run the operations in. This should
607 // end up being the same as userHandle, assuming it is not a special user and
608 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000609 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000610 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000611
Terry Wange04ceab2021-03-29 19:25:12 -0700612 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
613 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000614 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700615 for (int i = 0; i < ids.size(); i++) {
616 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700617 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700618 GenericDocument document = instance.getAppSearchImpl().getDocument(
619 packageName,
620 databaseName,
621 namespace,
622 id,
623 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700624 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700625 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700626 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700627 // Since we can only include one status code in the atom,
628 // for failures, we would just save the one for the last failure
629 AppSearchResult<Bundle> result = throwableToFailedResult(t);
630 resultBuilder.setResult(id, result);
631 statusCode = result.getResultCode();
632 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700633 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800634 }
Terry Wange04ceab2021-03-29 19:25:12 -0700635 invokeCallbackOnResult(callback, resultBuilder.build());
636 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700637 ++operationFailureCount;
638 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700639 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700640 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700641 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700642 int estimatedBinderLatencyMillis =
643 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
644 int totalLatencyMillis =
645 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700646 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700647 .setPackageName(packageName)
648 .setDatabase(databaseName)
649 .setStatusCode(statusCode)
650 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700651 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
652 // TODO(b/173532925) check the existing binder call latency chart
653 // is good enough for us:
654 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
655 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
656 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700657 .setNumOperationsFailed(operationFailureCount)
658 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700659 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800660 }
Terry Wange04ceab2021-03-29 19:25:12 -0700661 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800662 }
663
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800664 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800665 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800666 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700667 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700668 @NonNull String queryExpression,
669 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700670 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700671 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700672 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700673 Objects.requireNonNull(packageName);
674 Objects.requireNonNull(databaseName);
675 Objects.requireNonNull(queryExpression);
676 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700677 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700678 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700679
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700680 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000681 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800682 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700683 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700684 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700685 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700686 int operationSuccessCount = 0;
687 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700688 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000689 verifyCaller(callingUid, packageName);
690
691 // Obtain the user where the client wants to run the operations in. This should
692 // end up being the same as userHandle, assuming it is not a special user and
693 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000694 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000695 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000696
Cassie Wang2feb34d2021-07-22 18:55:19 +0000697 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700698 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
699 packageName,
700 databaseName,
701 queryExpression,
702 new SearchSpec(searchSpecBundle),
703 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700704 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700705 invokeCallbackOnResult(
706 callback,
707 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
708 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700709 ++operationFailureCount;
710 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700711 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700712 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700713 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700714 int estimatedBinderLatencyMillis =
715 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
716 int totalLatencyMillis =
717 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700718 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700719 .setPackageName(packageName)
720 .setDatabase(databaseName)
721 .setStatusCode(statusCode)
722 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700723 .setCallType(CallStats.CALL_TYPE_SEARCH)
724 // TODO(b/173532925) check the existing binder call latency chart
725 // is good enough for us:
726 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
727 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
728 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700729 .setNumOperationsFailed(operationFailureCount)
730 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700731 }
Terry Wange04ceab2021-03-29 19:25:12 -0700732 }
733 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700734 }
735
Terry Wangf2093072020-11-30 04:47:19 -0800736 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800737 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800738 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800739 @NonNull String queryExpression,
740 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700741 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700742 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800743 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700744 Objects.requireNonNull(packageName);
745 Objects.requireNonNull(queryExpression);
746 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700747 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700748 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700749
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700750 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000751 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800752 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700753 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700754 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700755 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700756 int operationSuccessCount = 0;
757 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700758 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000759 verifyCaller(callingUid, packageName);
760
761 // Obtain the user where the client wants to run the operations in. This should
762 // end up being the same as userHandle, assuming it is not a special user and
763 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000764 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000765 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000766
Cassie Wang2feb34d2021-07-22 18:55:19 +0000767 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700768
769 boolean callerHasSystemAccess =
770 instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
771 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
772 queryExpression,
773 new SearchSpec(searchSpecBundle),
774 packageName,
775 instance.getVisibilityStore(),
776 callingUid,
777 callerHasSystemAccess,
778 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700779 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700780 invokeCallbackOnResult(
781 callback,
782 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700783 } catch (Throwable t) {
784 ++operationFailureCount;
785 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700786 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700787 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700788 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700789 int estimatedBinderLatencyMillis =
790 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
791 int totalLatencyMillis =
792 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700793 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700794 .setPackageName(packageName)
795 .setStatusCode(statusCode)
796 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700797 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
798 // TODO(b/173532925) check the existing binder call latency chart
799 // is good enough for us:
800 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
801 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
802 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700803 .setNumOperationsFailed(operationFailureCount)
804 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700805 }
Terry Wange04ceab2021-03-29 19:25:12 -0700806 }
807 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800808 }
809
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700810 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800811 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700812 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800813 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700814 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700815 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700816 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700817 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700818 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700819
Cassie Wang2e2d0552021-08-04 16:18:10 +0000820 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800821 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700822 EXECUTOR.execute(() -> {
823 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000824 verifyCaller(callingUid, packageName);
825
826 // Obtain the user where the client wants to run the operations in. This should
827 // end up being the same as userHandle, assuming it is not a special user and
828 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000829 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000830 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000831
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700832 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000833 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700834 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700835 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700836 instance.getAppSearchImpl().getNextPage(
837 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700838 invokeCallbackOnResult(
839 callback,
840 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
841 } catch (Throwable t) {
842 invokeCallbackOnError(callback, t);
843 }
844 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700845 }
846
847 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700848 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
849 @NonNull UserHandle userHandle) {
850 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700851 Objects.requireNonNull(userHandle);
852
Cassie Wang2e2d0552021-08-04 16:18:10 +0000853 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800854 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700855 EXECUTOR.execute(() -> {
856 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000857 verifyCaller(callingUid, packageName);
858
859 // Obtain the user where the client wants to run the operations in. This should
860 // end up being the same as userHandle, assuming it is not a special user and
861 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000862 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000863 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000864
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700865 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000866 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700867 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700868 } catch (Throwable t) {
869 Log.e(TAG, "Unable to invalidate the query page token", t);
870 }
871 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800872 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800873
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700874 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800875 public void writeQueryResultsToFile(
876 @NonNull String packageName,
877 @NonNull String databaseName,
878 @NonNull ParcelFileDescriptor fileDescriptor,
879 @NonNull String queryExpression,
880 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700881 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800882 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700883 Objects.requireNonNull(packageName);
884 Objects.requireNonNull(databaseName);
885 Objects.requireNonNull(fileDescriptor);
886 Objects.requireNonNull(queryExpression);
887 Objects.requireNonNull(searchSpecBundle);
888 Objects.requireNonNull(userHandle);
889 Objects.requireNonNull(callback);
890
Cassie Wang2e2d0552021-08-04 16:18:10 +0000891 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800892 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700893 EXECUTOR.execute(() -> {
894 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000895 verifyCaller(callingUid, packageName);
896
897 // Obtain the user where the client wants to run the operations in. This should
898 // end up being the same as userHandle, assuming it is not a special user and
899 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000900 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000901 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000902
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700903 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000904 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700905 // we don't need to append the file. The file is always brand new.
906 try (DataOutputStream outputStream = new DataOutputStream(
907 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700908 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700909 packageName,
910 databaseName,
911 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700912 new SearchSpec(searchSpecBundle),
913 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700914 while (!searchResultPage.getResults().isEmpty()) {
915 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
916 AppSearchMigrationHelper.writeBundleToOutputStream(
917 outputStream, searchResultPage.getResults().get(i)
918 .getGenericDocument().getBundle());
919 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700920 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700921 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700922 packageName,
923 searchResultPage.getNextPageToken(),
924 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800925 }
Terry Wang623e3b02021-02-02 20:27:33 -0800926 }
Terry Wange04ceab2021-03-29 19:25:12 -0700927 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
928 } catch (Throwable t) {
929 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800930 }
Terry Wange04ceab2021-03-29 19:25:12 -0700931 });
Terry Wang623e3b02021-02-02 20:27:33 -0800932 }
933
934 @Override
935 public void putDocumentsFromFile(
936 @NonNull String packageName,
937 @NonNull String databaseName,
938 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700939 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800940 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700941 Objects.requireNonNull(packageName);
942 Objects.requireNonNull(databaseName);
943 Objects.requireNonNull(fileDescriptor);
944 Objects.requireNonNull(userHandle);
945 Objects.requireNonNull(callback);
946
Cassie Wang2e2d0552021-08-04 16:18:10 +0000947 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800948 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700949 EXECUTOR.execute(() -> {
950 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000951 verifyCaller(callingUid, packageName);
952
953 // Obtain the user where the client wants to run the operations in. This should
954 // end up being the same as userHandle, assuming it is not a special user and
955 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000956 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000957 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000958
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700959 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000960 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800961
Terry Wange04ceab2021-03-29 19:25:12 -0700962 GenericDocument document;
963 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
964 try (DataInputStream inputStream = new DataInputStream(
965 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
966 while (true) {
967 try {
968 document = AppSearchMigrationHelper
969 .readDocumentFromInputStream(inputStream);
970 } catch (EOFException e) {
971 // nothing wrong, we just finish the reading.
972 break;
973 }
974 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700975 instance.getAppSearchImpl().putDocument(
976 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700977 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700978 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
979 document.getNamespace(),
980 document.getId(),
981 document.getSchemaType(),
982 AppSearchResult.throwableToFailedResult(t))
983 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700984 }
Terry Wang623e3b02021-02-02 20:27:33 -0800985 }
986 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700987 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700988 invokeCallbackOnResult(callback,
989 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
990 } catch (Throwable t) {
991 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800992 }
Terry Wange04ceab2021-03-29 19:25:12 -0700993 });
Terry Wang623e3b02021-02-02 20:27:33 -0800994 }
995
996 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800997 public void reportUsage(
998 @NonNull String packageName,
999 @NonNull String databaseName,
1000 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001001 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001002 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001003 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001004 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001005 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001006 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001007 Objects.requireNonNull(databaseName);
1008 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001009 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001010 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001011 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001012
Cassie Wang2e2d0552021-08-04 16:18:10 +00001013 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001014 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001015 EXECUTOR.execute(() -> {
1016 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001017 verifyCaller(callingUid, packageName);
1018
1019 // Obtain the user where the client wants to run the operations in. This should
1020 // end up being the same as userHandle, assuming it is not a special user and
1021 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001022 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001023 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001024
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001025 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001026 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001027
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001028 if (systemUsage
1029 && !instance.getVisibilityStore()
1030 .doesCallerHaveSystemAccess(packageName)) {
1031 throw new AppSearchException(
1032 AppSearchResult.RESULT_SECURITY_ERROR,
1033 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001034 }
1035
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001036 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001037 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001038 usageTimeMillis, systemUsage);
1039 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001040 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001041 } catch (Throwable t) {
1042 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001043 }
Terry Wange04ceab2021-03-29 19:25:12 -07001044 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001045 }
1046
1047 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001048 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001049 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001050 @NonNull String databaseName,
1051 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001052 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001053 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001054 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001055 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001056 Objects.requireNonNull(packageName);
1057 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001058 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001059 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001060 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001061 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001062
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001063 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001064 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001065 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001066 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001067 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001068 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001069 int operationSuccessCount = 0;
1070 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001071 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001072 verifyCaller(callingUid, packageName);
1073
1074 // Obtain the user where the client wants to run the operations in. This should
1075 // end up being the same as userHandle, assuming it is not a special user and
1076 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001077 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001078 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001079
Terry Wange04ceab2021-03-29 19:25:12 -07001080 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1081 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001082 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001083 for (int i = 0; i < ids.size(); i++) {
1084 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001085 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001086 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001087 packageName,
1088 databaseName,
1089 namespace,
1090 id,
1091 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001092 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001093 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001094 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001095 AppSearchResult<Void> result = throwableToFailedResult(t);
1096 resultBuilder.setResult(id, result);
1097 // Since we can only include one status code in the atom,
1098 // for failures, we would just save the one for the last failure
1099 statusCode = result.getResultCode();
1100 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001101 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001102 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001103 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001104 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001105 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001106
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001107 // Schedule a task to dispatch change notifications. See requirements for where
1108 // the method is called documented in the method description.
1109 dispatchChangeNotifications(instance);
1110
Terry Wangf4d219b2021-07-01 19:11:39 -07001111 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001112 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001113 ++operationFailureCount;
1114 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001115 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001116 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001117 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001118 int estimatedBinderLatencyMillis =
1119 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1120 int totalLatencyMillis =
1121 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001122 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001123 .setPackageName(packageName)
1124 .setDatabase(databaseName)
1125 .setStatusCode(statusCode)
1126 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001127 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1128 // TODO(b/173532925) check the existing binder call latency chart
1129 // is good enough for us:
1130 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1131 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1132 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001133 .setNumOperationsFailed(operationFailureCount)
1134 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001135 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001136 }
Terry Wange04ceab2021-03-29 19:25:12 -07001137 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001138 }
1139
1140 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001141 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001142 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001143 @NonNull String databaseName,
1144 @NonNull String queryExpression,
1145 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001146 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001147 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001148 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001149 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001150 Objects.requireNonNull(packageName);
1151 Objects.requireNonNull(databaseName);
1152 Objects.requireNonNull(queryExpression);
1153 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001154 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001155 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001156
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001157 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001158 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001159 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001160 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001161 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001162 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001163 int operationSuccessCount = 0;
1164 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001165 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001166 verifyCaller(callingUid, packageName);
1167
1168 // Obtain the user where the client wants to run the operations in. This should
1169 // end up being the same as userHandle, assuming it is not a special user and
1170 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001171 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001172 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001173
Cassie Wang2feb34d2021-07-22 18:55:19 +00001174 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001175 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001176 packageName,
1177 databaseName,
1178 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001179 new SearchSpec(searchSpecBundle),
1180 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001181 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001182 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001183 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001184 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001185
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001186 // Schedule a task to dispatch change notifications. See requirements for where
1187 // the method is called documented in the method description.
1188 dispatchChangeNotifications(instance);
1189
Terry Wangf4d219b2021-07-01 19:11:39 -07001190 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001191 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001192 ++operationFailureCount;
1193 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001194 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001195 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001196 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001197 int estimatedBinderLatencyMillis =
1198 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1199 int totalLatencyMillis =
1200 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001201 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001202 .setPackageName(packageName)
1203 .setDatabase(databaseName)
1204 .setStatusCode(statusCode)
1205 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001206 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1207 // TODO(b/173532925) check the existing binder call latency chart
1208 // is good enough for us:
1209 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1210 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1211 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001212 .setNumOperationsFailed(operationFailureCount)
1213 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001214 }
Terry Wange04ceab2021-03-29 19:25:12 -07001215 }
1216 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001217 }
1218
Terry Wangdbd1dca2020-11-03 17:03:56 -08001219 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001220 public void getStorageInfo(
1221 @NonNull String packageName,
1222 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001223 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001224 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001225 Objects.requireNonNull(packageName);
1226 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001227 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001228 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001229
Cassie Wang2e2d0552021-08-04 16:18:10 +00001230 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001231 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001232 EXECUTOR.execute(() -> {
1233 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001234 verifyCaller(callingUid, packageName);
1235
1236 // Obtain the user where the client wants to run the operations in. This should
1237 // end up being the same as userHandle, assuming it is not a special user and
1238 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001239 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001240 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001241
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001242 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001243 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001244 StorageInfo storageInfo = instance.getAppSearchImpl()
1245 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001246 Bundle storageInfoBundle = storageInfo.getBundle();
1247 invokeCallbackOnResult(
1248 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1249 } catch (Throwable t) {
1250 invokeCallbackOnError(callback, t);
1251 }
1252 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001253 }
1254
1255 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001256 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001257 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001258 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001259 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001260 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001261 Objects.requireNonNull(userHandle);
1262
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001263 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001264 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001265 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001266 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001267 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001268 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001269 int operationSuccessCount = 0;
1270 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001271 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001272 verifyCaller(callingUid, packageName);
1273
1274 // Obtain the user where the client wants to run the operations in. This should
1275 // end up being the same as userHandle, assuming it is not a special user and
1276 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001277 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001278 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001279
Cassie Wang2feb34d2021-07-22 18:55:19 +00001280 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001281 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001282 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001283 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001284 ++operationFailureCount;
1285 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001286 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001287 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001288 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001289 int estimatedBinderLatencyMillis =
1290 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1291 int totalLatencyMillis =
1292 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001293 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001294 .setStatusCode(statusCode)
1295 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001296 .setCallType(CallStats.CALL_TYPE_FLUSH)
1297 // TODO(b/173532925) check the existing binder call latency chart
1298 // is good enough for us:
1299 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1300 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1301 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001302 .setNumOperationsFailed(operationFailureCount)
1303 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001304 }
Terry Wange04ceab2021-03-29 19:25:12 -07001305 }
1306 });
Terry Wang2da17852020-12-16 19:59:08 -08001307 }
1308
1309 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001310 public AppSearchResultParcel<Void> addObserver(
1311 @NonNull String callingPackage,
1312 @NonNull String observedPackage,
1313 @NonNull Bundle observerSpecBundle,
1314 @NonNull UserHandle userHandle,
1315 @NonNull IAppSearchObserverProxy observerProxyStub) {
1316 Objects.requireNonNull(callingPackage);
1317 Objects.requireNonNull(observedPackage);
1318 Objects.requireNonNull(observerSpecBundle);
1319 Objects.requireNonNull(userHandle);
1320 Objects.requireNonNull(observerProxyStub);
1321
1322 int callingPid = Binder.getCallingPid();
1323 int callingUid = Binder.getCallingUid();
1324 long callingIdentity = Binder.clearCallingIdentity();
1325
1326 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1327 try {
1328 verifyCaller(callingUid, callingPackage);
1329 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1330 verifyUserUnlocked(targetUser);
1331
1332 AppSearchUserInstance instance =
1333 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1334 instance.getAppSearchImpl().addObserver(
1335 observedPackage,
1336 new ObserverSpec(observerSpecBundle),
1337 EXECUTOR,
1338 new AppSearchObserverProxy(observerProxyStub));
1339 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1340 } catch (Throwable t) {
1341 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1342 } finally {
1343 Binder.restoreCallingIdentity(callingIdentity);
1344 }
1345 }
1346
1347 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001348 public AppSearchResultParcel<Void> removeObserver(
1349 @NonNull String callingPackage,
1350 @NonNull String observedPackage,
1351 @NonNull UserHandle userHandle,
1352 @NonNull IAppSearchObserverProxy observerProxyStub) {
1353 Objects.requireNonNull(callingPackage);
1354 Objects.requireNonNull(observedPackage);
1355 Objects.requireNonNull(userHandle);
1356 Objects.requireNonNull(observerProxyStub);
1357
1358 int callingPid = Binder.getCallingPid();
1359 int callingUid = Binder.getCallingUid();
1360 long callingIdentity = Binder.clearCallingIdentity();
1361
1362 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1363 try {
1364 verifyCaller(callingUid, callingPackage);
1365 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1366 verifyUserUnlocked(targetUser);
1367
1368 AppSearchUserInstance instance =
1369 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1370 instance.getAppSearchImpl().removeObserver(
1371 observedPackage,
1372 new AppSearchObserverProxy(observerProxyStub));
1373 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1374 } catch (Throwable t) {
1375 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1376 } finally {
1377 Binder.restoreCallingIdentity(callingIdentity);
1378 }
1379 }
1380
1381 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001382 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001383 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001384 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001385 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1386 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001387 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001388 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001389 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001390
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001391 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001392 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001393 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001394
Terry Wange04ceab2021-03-29 19:25:12 -07001395 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001396 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001397 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001398 int operationSuccessCount = 0;
1399 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001400 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001401 verifyCaller(callingUid, packageName);
1402
1403 // Obtain the user where the client wants to run the operations in. This should
1404 // end up being the same as userHandle, assuming it is not a special user and
1405 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001406 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001407 verifyUserUnlocked(targetUser);
1408
Cassie Wang2feb34d2021-07-22 18:55:19 +00001409 Context targetUserContext = mContext.createContextAsUser(targetUser,
1410 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001411 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001412 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001413 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001414 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1415 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001416 ++operationFailureCount;
1417 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001418 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001419 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001420 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001421 int estimatedBinderLatencyMillis =
1422 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1423 int totalLatencyMillis =
1424 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001425 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001426 .setStatusCode(statusCode)
1427 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001428 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1429 // TODO(b/173532925) check the existing binder call latency chart
1430 // is good enough for us:
1431 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1432 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1433 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001434 .setNumOperationsFailed(operationFailureCount)
1435 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001436 }
Terry Wange04ceab2021-03-29 19:25:12 -07001437 }
1438 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001439 }
1440
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001441 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001442 private void invokeCallbackOnResult(
1443 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001444 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001445 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001446 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001447 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001448 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001449 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001450
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001451 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001452 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001453 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001454 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001455 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001456 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001457 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001458 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001459 }
1460
1461 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001462 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001463 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001464 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001465 */
1466 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001467 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001468 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001469 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001470 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001471 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001472 }
1473 }
1474
1475 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001476 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001477 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001478 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001479 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001480 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001481 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001482 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001483 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001484 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001485 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001486 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001487 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001488 }
Terry Wangfebbead2019-10-17 17:05:18 -07001489 }
Terry Wangf2093072020-11-30 04:47:19 -08001490
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001491 /**
1492 * Helper for dealing with incoming user arguments to system service calls.
1493 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001494 * <p>Takes care of checking permissions and if the target is special user, this method will
1495 * simply throw.
1496 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001497 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001498 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001499 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001500 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001501 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001502 *
1503 * @throws IllegalArgumentException if the target user is a special user.
1504 * @throws SecurityException if caller trying to interact across user without
1505 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001506 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001507 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001508 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1509 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001510 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1511 if (callingUserHandle.equals(targetUserHandle)) {
1512 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001513 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001514
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001515 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001516 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001517 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001518 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001519 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001520
Cassie Wang2e2d0552021-08-04 16:18:10 +00001521 if (mContext.checkPermission(
1522 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1523 callingPid,
1524 callingUid) == PackageManager.PERMISSION_GRANTED) {
1525 return targetUserHandle;
1526 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001527 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001528 "Permission denied while calling from uid " + callingUid
1529 + " with " + targetUserHandle + "; Requires permission: "
1530 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001531 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001532
Cassie Wang84e33a02021-06-18 14:13:31 -07001533 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001534 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001535 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001536 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1537 * @param claimedCallingPackage Package name the caller claims to be.
1538 */
1539 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1540 // Obtain the user where the client is running in. Note that this could be different from
1541 // the userHandle where the client wants to run the AppSearch operation in.
1542 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1543 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1544 /*flags=*/ 0);
1545
1546 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1547 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1548 }
1549
1550 /**
1551 * Check that the caller's supposed package name matches the uid making the call.
1552 *
1553 * @throws SecurityException if the package name and uid don't match.
1554 */
1555 private void verifyCallingPackage(
1556 @NonNull Context actualCallingUserContext,
1557 int actualCallingUid,
1558 @NonNull String claimedCallingPackage) {
1559 int claimedCallingUid = PackageUtil.getPackageUid(
1560 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001561 if (claimedCallingUid != actualCallingUid) {
1562 throw new SecurityException(
1563 "Specified calling package ["
1564 + claimedCallingPackage
1565 + "] does not match the calling uid "
1566 + actualCallingUid);
1567 }
1568 }
1569
1570 /**
1571 * Ensure instant apps can't make calls to AppSearch.
1572 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001573 * @throws SecurityException if the caller is an instant app.
1574 */
1575 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1576 PackageManager callingPackageManager = userContext.getPackageManager();
1577 if (callingPackageManager.isInstantApp(packageName)) {
1578 throw new SecurityException("Caller not allowed to create AppSearch session"
1579 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1580 }
1581 }
1582
Yang Yu0fcd51a2021-04-23 11:25:44 -07001583 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1584 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001585 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001586 @NonNull PackageStats stats,
1587 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001588 @NonNull UserHandle userHandle,
1589 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001590 Objects.requireNonNull(stats);
1591 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001592 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001593
Yang Yu0fcd51a2021-04-23 11:25:44 -07001594 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001595 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001596 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001597 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1598 if (instance == null) {
1599 // augment storage info from file
1600 UserStorageInfo userStorageInfo =
1601 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1602 userHandle);
1603 stats.dataSize +=
1604 userStorageInfo.getSizeBytesForPackage(packageName);
1605 } else {
1606 stats.dataSize += instance.getAppSearchImpl()
1607 .getStorageInfoForPackage(packageName).getSizeBytes();
1608 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001609 } catch (Throwable t) {
1610 Log.e(
1611 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001612 "Unable to augment storage stats for "
1613 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001614 + " packageName "
1615 + packageName,
1616 t);
1617 }
1618 }
1619
1620 @Override
1621 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001622 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001623 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001624
1625 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001626 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001627 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001628 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1629 if (packagesForUid == null) {
1630 return;
1631 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001632 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001633 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1634 if (instance == null) {
1635 // augment storage info from file
1636 UserStorageInfo userStorageInfo =
1637 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1638 userHandle);
1639 for (int i = 0; i < packagesForUid.length; i++) {
1640 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1641 packagesForUid[i]);
1642 }
1643 } else {
1644 for (int i = 0; i < packagesForUid.length; i++) {
1645 stats.dataSize += instance.getAppSearchImpl()
1646 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1647 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001648 }
1649 } catch (Throwable t) {
1650 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1651 }
1652 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001653
1654 @Override
1655 public void augmentStatsForUser(
1656 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1657 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1658 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1659 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1660 Objects.requireNonNull(stats);
1661 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001662
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001663 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001664 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001665 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001666 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1667 if (instance == null) {
1668 // augment storage info from file
1669 UserStorageInfo userStorageInfo =
1670 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1671 userHandle);
1672 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1673 } else {
1674 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1675 /*flags=*/0, userHandle.getIdentifier());
1676 if (packagesForUser != null) {
1677 for (int i = 0; i < packagesForUser.size(); i++) {
1678 String packageName = packagesForUser.get(i).packageName;
1679 stats.dataSize += instance.getAppSearchImpl()
1680 .getStorageInfoForPackage(packageName).getSizeBytes();
1681 }
1682 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001683 }
1684 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001685 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001686 }
1687 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001688 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001689
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001690 /**
1691 * Dispatches change notifications if there are any to dispatch.
1692 *
1693 * <p>This method is async; notifications are dispatched onto their own registered executors.
1694 *
1695 * <p>IMPORTANT: You must always call this within the background task that contains the
1696 * operation that mutated the index. If you called it outside of that task, it could start
1697 * before the task completes, causing notifications to be missed.
1698 */
1699 @WorkerThread
1700 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1701 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1702 }
1703
1704 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001705 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1706 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001707 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1708 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001709 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001710 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001711 } catch (AppSearchException e) {
1712 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001713 } finally {
1714 OptimizeStats oStats = builder
1715 .setTotalLatencyMillis(
1716 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1717 .build();
1718 if (oStats.getOriginalDocumentCount() > 0) {
1719 // see if optimize has been run by checking originalDocumentCount
1720 instance.getLogger().logStats(oStats);
1721 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001722 }
1723 });
1724 }
1725
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001726 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001727 private void checkForOptimize(AppSearchUserInstance instance) {
1728 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001729 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1730 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001731 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001732 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001733 } catch (AppSearchException e) {
1734 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001735 } finally {
1736 OptimizeStats oStats = builder
1737 .setTotalLatencyMillis(
1738 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1739 .build();
1740 if (oStats.getOriginalDocumentCount() > 0) {
1741 // see if optimize has been run by checking originalDocumentCount
1742 instance.getLogger().logStats(oStats);
1743 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001744 }
1745 });
1746 }
Terry Wangfebbead2019-10-17 17:05:18 -07001747}