blob: a2ede1b5ead6cce3fd9d89596b96efc241810655 [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.ObserverSpec;
Terry Wang12dc6c02021-03-31 19:26:16 -070044import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070045import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070046import android.content.Intent;
47import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070048import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070049import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070050import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080051import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070052import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080053import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080054import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080055import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080056import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070057import android.os.UserManager;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080058import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080059import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070060
Cassie Wang15c86972021-02-09 13:43:25 -080061import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070062import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070063import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080064import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine14816e22021-07-12 10:53:24 -070065import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070066import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080067import com.android.server.appsearch.observer.AppSearchObserverProxy;
Xiaoyu Jin10329472021-06-23 16:50:03 -070068import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070069import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070070import com.android.server.usage.StorageStatsManagerLocal;
71import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080072
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070073import com.google.android.icing.proto.PersistType;
74
Terry Wang623e3b02021-02-02 20:27:33 -080075import java.io.DataInputStream;
76import java.io.DataOutputStream;
77import java.io.EOFException;
78import java.io.FileInputStream;
79import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080080import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080081import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080082import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080083import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080084import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070085import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070086import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070087import java.util.concurrent.ThreadPoolExecutor;
88import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080089
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070090/**
91 * The main service implementation which contains AppSearch's platform functionality.
Yang Yuc047f7b2021-06-25 12:22:42 -070092 *
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070093 * @hide
94 */
Terry Wangfebbead2019-10-17 17:05:18 -070095public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070096 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070097 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070098 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070099 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700100 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -0700101
Terry Wange04ceab2021-03-29 19:25:12 -0700102 // Never call shutdownNow(). It will cancel the futures it's returned. And since
103 // Executor#execute won't return anything, we will hang forever waiting for the execution.
104 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
105 // mutate requests will need to gain write lock and query requests need to gain read lock.
106 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
107 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700108 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700109
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700110 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
111 // suffix refers to the fact that access to the field should be locked; unrelated to the
112 // unlocked status of users.
113 @GuardedBy("mUnlockedUsersLocked")
114 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800115
Terry Wangfebbead2019-10-17 17:05:18 -0700116 public AppSearchManagerService(Context context) {
117 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700118 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700119 }
120
121 @Override
122 public void onStart() {
123 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700124 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700125 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700126 mUserManager = mContext.getSystemService(UserManager.class);
127 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700128 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700129 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700130 }
131
Xiaoyu Jin10329472021-06-23 16:50:03 -0700132 @Override
133 public void onBootPhase(/* @BootPhase */ int phase) {
134 if (phase == PHASE_BOOT_COMPLETED) {
135 StatsCollector.getInstance(mContext, EXECUTOR);
136 }
137 }
138
Terry Wang12dc6c02021-03-31 19:26:16 -0700139 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700140 mContext.registerReceiverForAllUsers(
141 new UserActionReceiver(),
142 new IntentFilter(Intent.ACTION_USER_REMOVED),
143 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700144 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700145
146 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
147 // broadcasts
148 IntentFilter packageChangedFilter = new IntentFilter();
149 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
150 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
151 packageChangedFilter.addDataScheme("package");
152 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700153 mContext.registerReceiverForAllUsers(
154 new PackageChangedReceiver(),
155 packageChangedFilter,
156 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700157 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700158 }
159
160 private class UserActionReceiver extends BroadcastReceiver {
161 @Override
162 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700163 Objects.requireNonNull(context);
164 Objects.requireNonNull(intent);
165
Terry Wang12dc6c02021-03-31 19:26:16 -0700166 switch (intent.getAction()) {
167 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700168 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
169 if (userHandle == null) {
170 Log.e(TAG, "Extra "
171 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700172 return;
173 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700174 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700175 break;
176 default:
Terry Wange201dc02021-04-16 01:03:20 -0700177 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700178 }
179 }
180 }
181
182 /**
183 * Handles user removed action.
184 *
185 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
186 * "credential encrypted" system directory of each user. That directory will be auto-deleted
187 * when a user is removed.
188 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700189 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700190 * @see android.os.Environment#getDataSystemCeDirectory
191 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700192 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700193 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700194 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700195 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700196 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700197 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700198 }
199 }
200
201 private class PackageChangedReceiver extends BroadcastReceiver {
202 @Override
203 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700204 Objects.requireNonNull(context);
205 Objects.requireNonNull(intent);
206
Terry Wange201dc02021-04-16 01:03:20 -0700207 switch (intent.getAction()) {
208 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
209 case Intent.ACTION_PACKAGE_DATA_CLEARED:
210 String packageName = intent.getData().getSchemeSpecificPart();
211 if (packageName == null) {
212 Log.e(TAG, "Package name is missing in the intent: " + intent);
213 return;
214 }
215 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
216 if (uid == INVALID_UID) {
217 Log.e(TAG, "uid is missing in the intent: " + intent);
218 return;
219 }
220 handlePackageRemoved(packageName, uid);
221 break;
222 default:
223 Log.e(TAG, "Received unknown intent: " + intent);
224 }
225 }
226 }
227
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700228 private void handlePackageRemoved(@NonNull String packageName, int uid) {
229 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700230 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700231 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700232 // We cannot access a locked user's directry and remove package data from it.
233 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700234 return;
235 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700236 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700237 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700238 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700239 AppSearchUserInstance instance =
240 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700241 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700242 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700243 instance.getAppSearchImpl().clearPackageData(packageName);
244 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700245 }
246 } catch (Throwable t) {
247 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700248 }
Terry Wangfebbead2019-10-17 17:05:18 -0700249 }
250
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800251 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700252 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700253 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700254 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700255 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700256 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800257 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700258 EXECUTOR.execute(() -> {
259 try {
260 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700261 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700262 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700263 AppSearchUserInstance instance =
264 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700265 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
266 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700267 .getPackageManager()
268 .getInstalledPackages(/*flags=*/0);
269 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
270 for (int i = 0; i < installedPackageInfos.size(); i++) {
271 packagesToKeep.add(installedPackageInfos.get(i).packageName);
272 }
Terry Wang0be9c302022-01-21 14:36:18 -0800273 packagesToKeep.add(VisibilityStore.VISIBILITY_PACKAGE_NAME);
Terry Wanga9e6e212021-04-23 15:51:37 -0700274 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700275 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700276 }
277 } catch (Throwable t) {
278 Log.e(TAG, "Unable to prune packages for " + user, t);
279 }
280 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800281 }
282
Terry Wangde9f3382021-04-28 19:45:07 -0700283 @Override
284 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700285 Objects.requireNonNull(user);
286
287 synchronized (mUnlockedUsersLocked) {
288 UserHandle userHandle = user.getUserHandle();
289 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700290 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700291 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700292 } catch (Throwable t) {
293 Log.e(TAG, "Error handling user stopping.", t);
294 }
295 }
296 }
297
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700298 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
299 if (isUserLocked(callingUser)) {
300 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700301 }
302 }
303
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700304 private boolean isUserLocked(@NonNull UserHandle callingUser) {
305 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700306 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700307 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700308 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700309 }
310 // If the local copy says the user is locked, check with UM for the actual state,
311 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700312 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700313 }
314 }
315
Terry Wangfebbead2019-10-17 17:05:18 -0700316 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800317 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800318 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800319 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700320 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700321 @NonNull List<Bundle> schemaBundles,
Terry Wang5b0c5612021-12-23 15:57:19 -0800322 @NonNull List<Bundle> visibilityBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800323 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700324 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700325 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700326 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800327 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700328 Objects.requireNonNull(packageName);
329 Objects.requireNonNull(databaseName);
330 Objects.requireNonNull(schemaBundles);
Terry Wang5b0c5612021-12-23 15:57:19 -0800331 Objects.requireNonNull(visibilityBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700332 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700333 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700334
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700335 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000336 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800337 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700338 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700339 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700340 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700341 int operationSuccessCount = 0;
342 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700343 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000344 verifyCaller(callingUid, packageName);
345
346 // Obtain the user where the client wants to run the operations in. This should
347 // end up being the same as userHandle, assuming it is not a special user and
348 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000349 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000350 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000351
Terry Wange04ceab2021-03-29 19:25:12 -0700352 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
353 for (int i = 0; i < schemaBundles.size(); i++) {
354 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800355 }
Terry Wang5b0c5612021-12-23 15:57:19 -0800356 List<VisibilityDocument> visibilityDocuments =
357 new ArrayList<>(visibilityBundles.size());
358 for (int i = 0; i < visibilityBundles.size(); i++) {
359 visibilityDocuments.add(
360 new VisibilityDocument(visibilityBundles.get(i)));
Terry Wange04ceab2021-03-29 19:25:12 -0700361 }
Cassie Wang2feb34d2021-07-22 18:55:19 +0000362 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700363 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700364 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700365 packageName,
366 databaseName,
367 schemas,
Terry Wange15ea582021-10-21 18:59:21 -0700368 visibilityDocuments,
Terry Wange04ceab2021-03-29 19:25:12 -0700369 forceOverride,
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700370 schemaVersion,
371 /*setSchemaStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700372 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700373 invokeCallbackOnResult(callback,
374 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700375
376 // setSchema will sync the schemas in the request to AppSearch, any existing
377 // schemas which is not included in the request will be delete if we force
378 // override incompatible schemas. And all documents of these types will be
379 // deleted as well. We should checkForOptimize for these deletion.
380 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700381 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700382 ++operationFailureCount;
383 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700384 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700385 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700386 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700387 int estimatedBinderLatencyMillis =
388 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
389 int totalLatencyMillis =
390 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700391 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700392 .setPackageName(packageName)
393 .setDatabase(databaseName)
394 .setStatusCode(statusCode)
395 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700396 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
397 // TODO(b/173532925) check the existing binder call latency chart
398 // is good enough for us:
399 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
400 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
401 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700402 .setNumOperationsFailed(operationFailureCount)
403 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700404 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800405 }
Terry Wange04ceab2021-03-29 19:25:12 -0700406 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800407 }
408
409 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800410 public void getSchema(
Alexander Dorokhined41def42022-01-25 15:45:34 -0800411 @NonNull String callingPackageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800412 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800413 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700414 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800415 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800416 Objects.requireNonNull(callingPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700417 Objects.requireNonNull(packageName);
418 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700419 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700420 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700421
Cassie Wang2e2d0552021-08-04 16:18:10 +0000422 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700423 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700424 EXECUTOR.execute(() -> {
425 try {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800426 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000427
428 // Obtain the user where the client wants to run the operations in. This should
429 // end up being the same as userHandle, assuming it is not a special user and
430 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000431 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000432 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000433
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700434 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000435 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700436 GetSchemaResponse response =
Alexander Dorokhined41def42022-01-25 15:45:34 -0800437 instance.getAppSearchImpl().getSchema(
438 callingPackageName, packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700439 invokeCallbackOnResult(
440 callback,
441 AppSearchResult.newSuccessfulResult(response.getBundle()));
442 } catch (Throwable t) {
443 invokeCallbackOnError(callback, t);
444 }
445 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700446 }
447
448 @Override
449 public void getNamespaces(
450 @NonNull String packageName,
451 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700452 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700453 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700454 Objects.requireNonNull(packageName);
455 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700456 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700457 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700458
Cassie Wang2e2d0552021-08-04 16:18:10 +0000459 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700460 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700461 EXECUTOR.execute(() -> {
462 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000463 verifyCaller(callingUid, packageName);
464
465 // Obtain the user where the client wants to run the operations in. This should
466 // end up being the same as userHandle, assuming it is not a special user and
467 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000468 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000469 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000470
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700471 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000472 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700473 List<String> namespaces =
474 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
475 invokeCallbackOnResult(
476 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700477 } catch (Throwable t) {
478 invokeCallbackOnError(callback, t);
479 }
480 });
Terry Wang83a24932020-12-09 21:00:18 -0800481 }
482
483 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800484 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800485 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700486 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700487 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700488 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800489 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800490 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700491 Objects.requireNonNull(packageName);
492 Objects.requireNonNull(databaseName);
493 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700494 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700495 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700496
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700497 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000498 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800499 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700500 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800501 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700502 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800503 int operationSuccessCount = 0;
504 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700505 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000506 verifyCaller(callingUid, packageName);
507
508 // Obtain the user where the client wants to run the operations in. This should
509 // end up being the same as userHandle, assuming it is not a special user and
510 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000511 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000512 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000513
Terry Wange04ceab2021-03-29 19:25:12 -0700514 AppSearchBatchResult.Builder<String, Void> resultBuilder =
515 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000516 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700517 for (int i = 0; i < documentBundles.size(); i++) {
518 GenericDocument document = new GenericDocument(documentBundles.get(i));
519 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700520 instance.getAppSearchImpl().putDocument(
521 packageName, databaseName, document, instance.getLogger());
522 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800523 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700524 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700525 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800526 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700527 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700528 // Since we can only include one status code in the atom,
529 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800530 statusCode = result.getResultCode();
531 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700532 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800533 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700534 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700535 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700536 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700537
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800538 // Schedule a task to dispatch change notifications. See requirements for where
539 // the method is called documented in the method description.
540 dispatchChangeNotifications(instance);
541
Terry Wangf4d219b2021-07-01 19:11:39 -0700542 // The existing documents with same ID will be deleted, so there may be some
543 // resources that could be released after optimize().
544 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700545 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700546 ++operationFailureCount;
547 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700548 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800549 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700550 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700551 int estimatedBinderLatencyMillis =
552 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
553 int totalLatencyMillis =
554 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700555 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700556 .setPackageName(packageName)
557 .setDatabase(databaseName)
558 .setStatusCode(statusCode)
559 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800560 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
561 // TODO(b/173532925) check the existing binder call latency chart
562 // is good enough for us:
563 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700564 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800565 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700566 .setNumOperationsFailed(operationFailureCount)
567 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800568 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800569 }
Terry Wange04ceab2021-03-29 19:25:12 -0700570 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800571 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800572
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800573 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800574 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800575 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800576 @NonNull String databaseName,
577 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700578 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800579 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700580 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700581 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800582 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700583 Objects.requireNonNull(packageName);
584 Objects.requireNonNull(databaseName);
585 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700586 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700587 Objects.requireNonNull(typePropertyPaths);
588 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700589 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700590
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700591 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000592 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800593 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700594 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700595 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700596 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700597 int operationSuccessCount = 0;
598 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700599 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000600 verifyCaller(callingUid, packageName);
601
602 // Obtain the user where the client wants to run the operations in. This should
603 // end up being the same as userHandle, assuming it is not a special user and
604 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000605 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000606 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000607
Terry Wange04ceab2021-03-29 19:25:12 -0700608 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
609 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000610 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700611 for (int i = 0; i < ids.size(); i++) {
612 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700613 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700614 GenericDocument document = instance.getAppSearchImpl().getDocument(
615 packageName,
616 databaseName,
617 namespace,
618 id,
619 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700620 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700621 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700622 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700623 // Since we can only include one status code in the atom,
624 // for failures, we would just save the one for the last failure
625 AppSearchResult<Bundle> result = throwableToFailedResult(t);
626 resultBuilder.setResult(id, result);
627 statusCode = result.getResultCode();
628 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700629 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800630 }
Terry Wange04ceab2021-03-29 19:25:12 -0700631 invokeCallbackOnResult(callback, resultBuilder.build());
632 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700633 ++operationFailureCount;
634 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700635 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700636 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700637 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700638 int estimatedBinderLatencyMillis =
639 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
640 int totalLatencyMillis =
641 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700642 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700643 .setPackageName(packageName)
644 .setDatabase(databaseName)
645 .setStatusCode(statusCode)
646 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700647 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
648 // TODO(b/173532925) check the existing binder call latency chart
649 // is good enough for us:
650 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
651 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
652 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700653 .setNumOperationsFailed(operationFailureCount)
654 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700655 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800656 }
Terry Wange04ceab2021-03-29 19:25:12 -0700657 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800658 }
659
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800660 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800661 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800662 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700663 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700664 @NonNull String queryExpression,
665 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700666 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700667 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700668 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700669 Objects.requireNonNull(packageName);
670 Objects.requireNonNull(databaseName);
671 Objects.requireNonNull(queryExpression);
672 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700673 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700674 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700675
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700676 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000677 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800678 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700679 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700680 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700681 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700682 int operationSuccessCount = 0;
683 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700684 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000685 verifyCaller(callingUid, packageName);
686
687 // Obtain the user where the client wants to run the operations in. This should
688 // end up being the same as userHandle, assuming it is not a special user and
689 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000690 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000691 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000692
Cassie Wang2feb34d2021-07-22 18:55:19 +0000693 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700694 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
695 packageName,
696 databaseName,
697 queryExpression,
698 new SearchSpec(searchSpecBundle),
699 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700700 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700701 invokeCallbackOnResult(
702 callback,
703 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
704 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700705 ++operationFailureCount;
706 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700707 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700708 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700709 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700710 int estimatedBinderLatencyMillis =
711 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
712 int totalLatencyMillis =
713 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700714 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700715 .setPackageName(packageName)
716 .setDatabase(databaseName)
717 .setStatusCode(statusCode)
718 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700719 .setCallType(CallStats.CALL_TYPE_SEARCH)
720 // TODO(b/173532925) check the existing binder call latency chart
721 // is good enough for us:
722 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
723 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
724 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700725 .setNumOperationsFailed(operationFailureCount)
726 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700727 }
Terry Wange04ceab2021-03-29 19:25:12 -0700728 }
729 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700730 }
731
Terry Wangf2093072020-11-30 04:47:19 -0800732 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800733 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800734 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800735 @NonNull String queryExpression,
736 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700737 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700738 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800739 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700740 Objects.requireNonNull(packageName);
741 Objects.requireNonNull(queryExpression);
742 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700743 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700744 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700745
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700746 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000747 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800748 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700749 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700750 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700751 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700752 int operationSuccessCount = 0;
753 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700754 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000755 verifyCaller(callingUid, packageName);
756
757 // Obtain the user where the client wants to run the operations in. This should
758 // end up being the same as userHandle, assuming it is not a special user and
759 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000760 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000761 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000762
Cassie Wang2feb34d2021-07-22 18:55:19 +0000763 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700764
Terry Wang0be9c302022-01-21 14:36:18 -0800765 boolean callerHasSystemAccess = instance.getVisibilityCheckImpl()
766 .doesCallerHaveSystemAccess(packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700767 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
768 queryExpression,
769 new SearchSpec(searchSpecBundle),
770 packageName,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700771 callingUid,
772 callerHasSystemAccess,
773 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700774 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700775 invokeCallbackOnResult(
776 callback,
777 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700778 } catch (Throwable t) {
779 ++operationFailureCount;
780 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700781 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700782 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700783 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700784 int estimatedBinderLatencyMillis =
785 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
786 int totalLatencyMillis =
787 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700788 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700789 .setPackageName(packageName)
790 .setStatusCode(statusCode)
791 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700792 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
793 // TODO(b/173532925) check the existing binder call latency chart
794 // is good enough for us:
795 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
796 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
797 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700798 .setNumOperationsFailed(operationFailureCount)
799 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700800 }
Terry Wange04ceab2021-03-29 19:25:12 -0700801 }
802 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800803 }
804
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700805 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800806 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700807 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800808 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700809 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700810 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700811 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700812 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700813 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700814
Cassie Wang2e2d0552021-08-04 16:18:10 +0000815 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800816 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700817 EXECUTOR.execute(() -> {
818 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000819 verifyCaller(callingUid, packageName);
820
821 // Obtain the user where the client wants to run the operations in. This should
822 // end up being the same as userHandle, assuming it is not a special user and
823 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000824 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000825 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000826
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700827 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000828 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700829 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700830 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700831 instance.getAppSearchImpl().getNextPage(
832 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700833 invokeCallbackOnResult(
834 callback,
835 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
836 } catch (Throwable t) {
837 invokeCallbackOnError(callback, t);
838 }
839 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700840 }
841
842 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700843 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
844 @NonNull UserHandle userHandle) {
845 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700846 Objects.requireNonNull(userHandle);
847
Cassie Wang2e2d0552021-08-04 16:18:10 +0000848 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800849 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700850 EXECUTOR.execute(() -> {
851 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000852 verifyCaller(callingUid, packageName);
853
854 // Obtain the user where the client wants to run the operations in. This should
855 // end up being the same as userHandle, assuming it is not a special user and
856 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000857 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000858 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000859
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700860 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000861 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700862 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700863 } catch (Throwable t) {
864 Log.e(TAG, "Unable to invalidate the query page token", t);
865 }
866 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800867 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800868
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700869 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800870 public void writeQueryResultsToFile(
871 @NonNull String packageName,
872 @NonNull String databaseName,
873 @NonNull ParcelFileDescriptor fileDescriptor,
874 @NonNull String queryExpression,
875 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700876 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800877 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700878 Objects.requireNonNull(packageName);
879 Objects.requireNonNull(databaseName);
880 Objects.requireNonNull(fileDescriptor);
881 Objects.requireNonNull(queryExpression);
882 Objects.requireNonNull(searchSpecBundle);
883 Objects.requireNonNull(userHandle);
884 Objects.requireNonNull(callback);
885
Cassie Wang2e2d0552021-08-04 16:18:10 +0000886 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800887 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700888 EXECUTOR.execute(() -> {
889 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000890 verifyCaller(callingUid, packageName);
891
892 // Obtain the user where the client wants to run the operations in. This should
893 // end up being the same as userHandle, assuming it is not a special user and
894 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000895 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000896 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000897
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700898 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000899 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700900 // we don't need to append the file. The file is always brand new.
901 try (DataOutputStream outputStream = new DataOutputStream(
902 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700903 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700904 packageName,
905 databaseName,
906 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700907 new SearchSpec(searchSpecBundle),
908 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700909 while (!searchResultPage.getResults().isEmpty()) {
910 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
911 AppSearchMigrationHelper.writeBundleToOutputStream(
912 outputStream, searchResultPage.getResults().get(i)
913 .getGenericDocument().getBundle());
914 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700915 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700916 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700917 packageName,
918 searchResultPage.getNextPageToken(),
919 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800920 }
Terry Wang623e3b02021-02-02 20:27:33 -0800921 }
Terry Wange04ceab2021-03-29 19:25:12 -0700922 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
923 } catch (Throwable t) {
924 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800925 }
Terry Wange04ceab2021-03-29 19:25:12 -0700926 });
Terry Wang623e3b02021-02-02 20:27:33 -0800927 }
928
929 @Override
930 public void putDocumentsFromFile(
931 @NonNull String packageName,
932 @NonNull String databaseName,
933 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700934 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800935 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700936 Objects.requireNonNull(packageName);
937 Objects.requireNonNull(databaseName);
938 Objects.requireNonNull(fileDescriptor);
939 Objects.requireNonNull(userHandle);
940 Objects.requireNonNull(callback);
941
Cassie Wang2e2d0552021-08-04 16:18:10 +0000942 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800943 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700944 EXECUTOR.execute(() -> {
945 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000946 verifyCaller(callingUid, packageName);
947
948 // Obtain the user where the client wants to run the operations in. This should
949 // end up being the same as userHandle, assuming it is not a special user and
950 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000951 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000952 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000953
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700954 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000955 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800956
Terry Wange04ceab2021-03-29 19:25:12 -0700957 GenericDocument document;
958 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
959 try (DataInputStream inputStream = new DataInputStream(
960 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
961 while (true) {
962 try {
963 document = AppSearchMigrationHelper
964 .readDocumentFromInputStream(inputStream);
965 } catch (EOFException e) {
966 // nothing wrong, we just finish the reading.
967 break;
968 }
969 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700970 instance.getAppSearchImpl().putDocument(
971 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700972 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700973 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
974 document.getNamespace(),
975 document.getId(),
976 document.getSchemaType(),
977 AppSearchResult.throwableToFailedResult(t))
978 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700979 }
Terry Wang623e3b02021-02-02 20:27:33 -0800980 }
981 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700982 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700983 invokeCallbackOnResult(callback,
984 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
985 } catch (Throwable t) {
986 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800987 }
Terry Wange04ceab2021-03-29 19:25:12 -0700988 });
Terry Wang623e3b02021-02-02 20:27:33 -0800989 }
990
991 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800992 public void reportUsage(
993 @NonNull String packageName,
994 @NonNull String databaseName,
995 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700996 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800997 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700998 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700999 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001000 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001001 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001002 Objects.requireNonNull(databaseName);
1003 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001004 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001005 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001006 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001007
Cassie Wang2e2d0552021-08-04 16:18:10 +00001008 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001009 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001010 EXECUTOR.execute(() -> {
1011 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001012 verifyCaller(callingUid, packageName);
1013
1014 // Obtain the user where the client wants to run the operations in. This should
1015 // end up being the same as userHandle, assuming it is not a special user and
1016 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001017 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001018 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001019
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001020 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001021 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001022
Terry Wang0be9c302022-01-21 14:36:18 -08001023 if (systemUsage && !instance.getVisibilityCheckImpl().
1024 doesCallerHaveSystemAccess(packageName)) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001025 throw new AppSearchException(
1026 AppSearchResult.RESULT_SECURITY_ERROR,
1027 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001028 }
1029
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001030 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001031 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001032 usageTimeMillis, systemUsage);
1033 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001034 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001035 } catch (Throwable t) {
1036 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001037 }
Terry Wange04ceab2021-03-29 19:25:12 -07001038 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001039 }
1040
1041 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001042 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001043 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001044 @NonNull String databaseName,
1045 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001046 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001047 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001048 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001049 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001050 Objects.requireNonNull(packageName);
1051 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001052 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001053 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001054 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001055 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001056
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001057 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001058 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001059 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001060 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001061 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001062 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001063 int operationSuccessCount = 0;
1064 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001065 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001066 verifyCaller(callingUid, packageName);
1067
1068 // Obtain the user where the client wants to run the operations in. This should
1069 // end up being the same as userHandle, assuming it is not a special user and
1070 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001071 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001072 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001073
Terry Wange04ceab2021-03-29 19:25:12 -07001074 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1075 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001076 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001077 for (int i = 0; i < ids.size(); i++) {
1078 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001079 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001080 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001081 packageName,
1082 databaseName,
1083 namespace,
1084 id,
1085 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001086 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001087 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001088 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001089 AppSearchResult<Void> result = throwableToFailedResult(t);
1090 resultBuilder.setResult(id, result);
1091 // Since we can only include one status code in the atom,
1092 // for failures, we would just save the one for the last failure
1093 statusCode = result.getResultCode();
1094 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001095 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001096 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001097 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001098 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001099 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001100
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001101 // Schedule a task to dispatch change notifications. See requirements for where
1102 // the method is called documented in the method description.
1103 dispatchChangeNotifications(instance);
1104
Terry Wangf4d219b2021-07-01 19:11:39 -07001105 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001106 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001107 ++operationFailureCount;
1108 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001109 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001110 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001111 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001112 int estimatedBinderLatencyMillis =
1113 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1114 int totalLatencyMillis =
1115 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001116 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001117 .setPackageName(packageName)
1118 .setDatabase(databaseName)
1119 .setStatusCode(statusCode)
1120 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001121 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1122 // TODO(b/173532925) check the existing binder call latency chart
1123 // is good enough for us:
1124 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1125 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1126 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001127 .setNumOperationsFailed(operationFailureCount)
1128 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001129 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001130 }
Terry Wange04ceab2021-03-29 19:25:12 -07001131 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001132 }
1133
1134 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001135 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001136 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001137 @NonNull String databaseName,
1138 @NonNull String queryExpression,
1139 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001140 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001141 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001142 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001143 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001144 Objects.requireNonNull(packageName);
1145 Objects.requireNonNull(databaseName);
1146 Objects.requireNonNull(queryExpression);
1147 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001148 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001149 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001150
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001151 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001152 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001153 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001154 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001155 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001156 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001157 int operationSuccessCount = 0;
1158 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001159 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001160 verifyCaller(callingUid, packageName);
1161
1162 // Obtain the user where the client wants to run the operations in. This should
1163 // end up being the same as userHandle, assuming it is not a special user and
1164 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001165 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001166 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001167
Cassie Wang2feb34d2021-07-22 18:55:19 +00001168 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001169 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001170 packageName,
1171 databaseName,
1172 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001173 new SearchSpec(searchSpecBundle),
1174 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001175 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001176 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001177 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001178 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001179
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001180 // Schedule a task to dispatch change notifications. See requirements for where
1181 // the method is called documented in the method description.
1182 dispatchChangeNotifications(instance);
1183
Terry Wangf4d219b2021-07-01 19:11:39 -07001184 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001185 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001186 ++operationFailureCount;
1187 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001188 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001189 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001190 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001191 int estimatedBinderLatencyMillis =
1192 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1193 int totalLatencyMillis =
1194 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001195 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001196 .setPackageName(packageName)
1197 .setDatabase(databaseName)
1198 .setStatusCode(statusCode)
1199 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001200 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1201 // TODO(b/173532925) check the existing binder call latency chart
1202 // is good enough for us:
1203 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1204 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1205 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001206 .setNumOperationsFailed(operationFailureCount)
1207 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001208 }
Terry Wange04ceab2021-03-29 19:25:12 -07001209 }
1210 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001211 }
1212
Terry Wangdbd1dca2020-11-03 17:03:56 -08001213 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001214 public void getStorageInfo(
1215 @NonNull String packageName,
1216 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001217 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001218 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001219 Objects.requireNonNull(packageName);
1220 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001221 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001222 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001223
Cassie Wang2e2d0552021-08-04 16:18:10 +00001224 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001225 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001226 EXECUTOR.execute(() -> {
1227 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001228 verifyCaller(callingUid, packageName);
1229
1230 // Obtain the user where the client wants to run the operations in. This should
1231 // end up being the same as userHandle, assuming it is not a special user and
1232 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001233 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001234 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001235
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001236 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001237 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001238 StorageInfo storageInfo = instance.getAppSearchImpl()
1239 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001240 Bundle storageInfoBundle = storageInfo.getBundle();
1241 invokeCallbackOnResult(
1242 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1243 } catch (Throwable t) {
1244 invokeCallbackOnError(callback, t);
1245 }
1246 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001247 }
1248
1249 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001250 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001251 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001252 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001253 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001254 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001255 Objects.requireNonNull(userHandle);
1256
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001257 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001258 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001259 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001260 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001261 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001262 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001263 int operationSuccessCount = 0;
1264 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001265 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001266 verifyCaller(callingUid, packageName);
1267
1268 // Obtain the user where the client wants to run the operations in. This should
1269 // end up being the same as userHandle, assuming it is not a special user and
1270 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001271 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001272 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001273
Cassie Wang2feb34d2021-07-22 18:55:19 +00001274 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001275 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001276 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001277 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001278 ++operationFailureCount;
1279 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001280 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001281 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001282 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001283 int estimatedBinderLatencyMillis =
1284 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1285 int totalLatencyMillis =
1286 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001287 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001288 .setStatusCode(statusCode)
1289 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001290 .setCallType(CallStats.CALL_TYPE_FLUSH)
1291 // TODO(b/173532925) check the existing binder call latency chart
1292 // is good enough for us:
1293 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1294 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1295 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001296 .setNumOperationsFailed(operationFailureCount)
1297 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001298 }
Terry Wange04ceab2021-03-29 19:25:12 -07001299 }
1300 });
Terry Wang2da17852020-12-16 19:59:08 -08001301 }
1302
1303 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001304 public AppSearchResultParcel<Void> addObserver(
1305 @NonNull String callingPackage,
1306 @NonNull String observedPackage,
1307 @NonNull Bundle observerSpecBundle,
1308 @NonNull UserHandle userHandle,
1309 @NonNull IAppSearchObserverProxy observerProxyStub) {
1310 Objects.requireNonNull(callingPackage);
1311 Objects.requireNonNull(observedPackage);
1312 Objects.requireNonNull(observerSpecBundle);
1313 Objects.requireNonNull(userHandle);
1314 Objects.requireNonNull(observerProxyStub);
1315
1316 int callingPid = Binder.getCallingPid();
1317 int callingUid = Binder.getCallingUid();
1318 long callingIdentity = Binder.clearCallingIdentity();
1319
1320 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1321 try {
1322 verifyCaller(callingUid, callingPackage);
1323 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1324 verifyUserUnlocked(targetUser);
1325
1326 AppSearchUserInstance instance =
1327 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1328 instance.getAppSearchImpl().addObserver(
1329 observedPackage,
1330 new ObserverSpec(observerSpecBundle),
1331 EXECUTOR,
1332 new AppSearchObserverProxy(observerProxyStub));
1333 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1334 } catch (Throwable t) {
1335 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1336 } finally {
1337 Binder.restoreCallingIdentity(callingIdentity);
1338 }
1339 }
1340
1341 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001342 public AppSearchResultParcel<Void> removeObserver(
1343 @NonNull String callingPackage,
1344 @NonNull String observedPackage,
1345 @NonNull UserHandle userHandle,
1346 @NonNull IAppSearchObserverProxy observerProxyStub) {
1347 Objects.requireNonNull(callingPackage);
1348 Objects.requireNonNull(observedPackage);
1349 Objects.requireNonNull(userHandle);
1350 Objects.requireNonNull(observerProxyStub);
1351
1352 int callingPid = Binder.getCallingPid();
1353 int callingUid = Binder.getCallingUid();
1354 long callingIdentity = Binder.clearCallingIdentity();
1355
1356 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1357 try {
1358 verifyCaller(callingUid, callingPackage);
1359 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1360 verifyUserUnlocked(targetUser);
1361
1362 AppSearchUserInstance instance =
1363 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1364 instance.getAppSearchImpl().removeObserver(
1365 observedPackage,
1366 new AppSearchObserverProxy(observerProxyStub));
1367 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1368 } catch (Throwable t) {
1369 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1370 } finally {
1371 Binder.restoreCallingIdentity(callingIdentity);
1372 }
1373 }
1374
1375 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001376 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001377 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001378 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001379 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1380 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001381 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001382 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001383 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001384
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001385 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001386 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001387 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001388
Terry Wange04ceab2021-03-29 19:25:12 -07001389 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001390 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001391 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001392 int operationSuccessCount = 0;
1393 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001394 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001395 verifyCaller(callingUid, packageName);
1396
1397 // Obtain the user where the client wants to run the operations in. This should
1398 // end up being the same as userHandle, assuming it is not a special user and
1399 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001400 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001401 verifyUserUnlocked(targetUser);
1402
Cassie Wang2feb34d2021-07-22 18:55:19 +00001403 Context targetUserContext = mContext.createContextAsUser(targetUser,
1404 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001405 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001406 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001407 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001408 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1409 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001410 ++operationFailureCount;
1411 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001412 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001413 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001414 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001415 int estimatedBinderLatencyMillis =
1416 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1417 int totalLatencyMillis =
1418 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001419 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001420 .setStatusCode(statusCode)
1421 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001422 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1423 // TODO(b/173532925) check the existing binder call latency chart
1424 // is good enough for us:
1425 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1426 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1427 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001428 .setNumOperationsFailed(operationFailureCount)
1429 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001430 }
Terry Wange04ceab2021-03-29 19:25:12 -07001431 }
1432 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001433 }
1434
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001435 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001436 private void invokeCallbackOnResult(
1437 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001438 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001439 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001440 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001441 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001442 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001443 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001444
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001445 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001446 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001447 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001448 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001449 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001450 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001451 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001452 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001453 }
1454
1455 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001456 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001457 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001458 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001459 */
1460 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001461 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001462 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001463 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001464 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001465 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001466 }
1467 }
1468
1469 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001470 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001471 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001472 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001473 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001474 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001475 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001476 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001477 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001478 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001479 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001480 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001481 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001482 }
Terry Wangfebbead2019-10-17 17:05:18 -07001483 }
Terry Wangf2093072020-11-30 04:47:19 -08001484
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001485 /**
1486 * Helper for dealing with incoming user arguments to system service calls.
1487 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001488 * <p>Takes care of checking permissions and if the target is special user, this method will
1489 * simply throw.
1490 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001491 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001492 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001493 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001494 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001495 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001496 *
1497 * @throws IllegalArgumentException if the target user is a special user.
1498 * @throws SecurityException if caller trying to interact across user without
1499 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001500 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001501 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001502 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1503 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001504 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1505 if (callingUserHandle.equals(targetUserHandle)) {
1506 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001507 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001508
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001509 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001510 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001511 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001512 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001513 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001514
Cassie Wang2e2d0552021-08-04 16:18:10 +00001515 if (mContext.checkPermission(
1516 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1517 callingPid,
1518 callingUid) == PackageManager.PERMISSION_GRANTED) {
1519 return targetUserHandle;
1520 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001521 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001522 "Permission denied while calling from uid " + callingUid
1523 + " with " + targetUserHandle + "; Requires permission: "
1524 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001525 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001526
Cassie Wang84e33a02021-06-18 14:13:31 -07001527 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001528 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001529 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001530 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1531 * @param claimedCallingPackage Package name the caller claims to be.
1532 */
1533 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1534 // Obtain the user where the client is running in. Note that this could be different from
1535 // the userHandle where the client wants to run the AppSearch operation in.
1536 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1537 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1538 /*flags=*/ 0);
1539
1540 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1541 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1542 }
1543
1544 /**
1545 * Check that the caller's supposed package name matches the uid making the call.
1546 *
1547 * @throws SecurityException if the package name and uid don't match.
1548 */
1549 private void verifyCallingPackage(
1550 @NonNull Context actualCallingUserContext,
1551 int actualCallingUid,
1552 @NonNull String claimedCallingPackage) {
1553 int claimedCallingUid = PackageUtil.getPackageUid(
1554 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001555 if (claimedCallingUid != actualCallingUid) {
1556 throw new SecurityException(
1557 "Specified calling package ["
1558 + claimedCallingPackage
1559 + "] does not match the calling uid "
1560 + actualCallingUid);
1561 }
1562 }
1563
1564 /**
1565 * Ensure instant apps can't make calls to AppSearch.
1566 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001567 * @throws SecurityException if the caller is an instant app.
1568 */
1569 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1570 PackageManager callingPackageManager = userContext.getPackageManager();
1571 if (callingPackageManager.isInstantApp(packageName)) {
1572 throw new SecurityException("Caller not allowed to create AppSearch session"
1573 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1574 }
1575 }
1576
Yang Yu0fcd51a2021-04-23 11:25:44 -07001577 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1578 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001579 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001580 @NonNull PackageStats stats,
1581 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001582 @NonNull UserHandle userHandle,
1583 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001584 Objects.requireNonNull(stats);
1585 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001586 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001587
Yang Yu0fcd51a2021-04-23 11:25:44 -07001588 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001589 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001590 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001591 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1592 if (instance == null) {
1593 // augment storage info from file
1594 UserStorageInfo userStorageInfo =
1595 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1596 userHandle);
1597 stats.dataSize +=
1598 userStorageInfo.getSizeBytesForPackage(packageName);
1599 } else {
1600 stats.dataSize += instance.getAppSearchImpl()
1601 .getStorageInfoForPackage(packageName).getSizeBytes();
1602 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001603 } catch (Throwable t) {
1604 Log.e(
1605 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001606 "Unable to augment storage stats for "
1607 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001608 + " packageName "
1609 + packageName,
1610 t);
1611 }
1612 }
1613
1614 @Override
1615 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001616 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001617 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001618
1619 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001620 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001621 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001622 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1623 if (packagesForUid == null) {
1624 return;
1625 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001626 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001627 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1628 if (instance == null) {
1629 // augment storage info from file
1630 UserStorageInfo userStorageInfo =
1631 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1632 userHandle);
1633 for (int i = 0; i < packagesForUid.length; i++) {
1634 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1635 packagesForUid[i]);
1636 }
1637 } else {
1638 for (int i = 0; i < packagesForUid.length; i++) {
1639 stats.dataSize += instance.getAppSearchImpl()
1640 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1641 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001642 }
1643 } catch (Throwable t) {
1644 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1645 }
1646 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001647
1648 @Override
1649 public void augmentStatsForUser(
1650 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1651 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1652 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1653 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1654 Objects.requireNonNull(stats);
1655 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001656
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001657 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001658 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001659 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001660 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1661 if (instance == null) {
1662 // augment storage info from file
1663 UserStorageInfo userStorageInfo =
1664 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1665 userHandle);
1666 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1667 } else {
1668 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1669 /*flags=*/0, userHandle.getIdentifier());
1670 if (packagesForUser != null) {
1671 for (int i = 0; i < packagesForUser.size(); i++) {
1672 String packageName = packagesForUser.get(i).packageName;
1673 stats.dataSize += instance.getAppSearchImpl()
1674 .getStorageInfoForPackage(packageName).getSizeBytes();
1675 }
1676 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001677 }
1678 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001679 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001680 }
1681 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001682 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001683
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001684 /**
1685 * Dispatches change notifications if there are any to dispatch.
1686 *
1687 * <p>This method is async; notifications are dispatched onto their own registered executors.
1688 *
1689 * <p>IMPORTANT: You must always call this within the background task that contains the
1690 * operation that mutated the index. If you called it outside of that task, it could start
1691 * before the task completes, causing notifications to be missed.
1692 */
1693 @WorkerThread
1694 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1695 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1696 }
1697
1698 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001699 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1700 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001701 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1702 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001703 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001704 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001705 } catch (AppSearchException e) {
1706 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001707 } finally {
1708 OptimizeStats oStats = builder
1709 .setTotalLatencyMillis(
1710 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1711 .build();
1712 if (oStats.getOriginalDocumentCount() > 0) {
1713 // see if optimize has been run by checking originalDocumentCount
1714 instance.getLogger().logStats(oStats);
1715 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001716 }
1717 });
1718 }
1719
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001720 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001721 private void checkForOptimize(AppSearchUserInstance instance) {
1722 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001723 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1724 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001725 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001726 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001727 } catch (AppSearchException e) {
1728 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001729 } finally {
1730 OptimizeStats oStats = builder
1731 .setTotalLatencyMillis(
1732 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1733 .build();
1734 if (oStats.getOriginalDocumentCount() > 0) {
1735 // see if optimize has been run by checking originalDocumentCount
1736 instance.getLogger().logStats(oStats);
1737 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001738 }
1739 });
1740 }
Terry Wangfebbead2019-10-17 17:05:18 -07001741}