blob: dd2a5dbe6dce19c6f944b3c97b33e65f09e7bc67 [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;
Alexander Dorokhineab789062021-01-11 21:00:00 -080031import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070032import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070033import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080034import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070035import android.app.appsearch.StorageInfo;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070036import android.app.appsearch.aidl.AppSearchBatchResultParcel;
37import android.app.appsearch.aidl.AppSearchResultParcel;
38import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
39import android.app.appsearch.aidl.IAppSearchManager;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080040import android.app.appsearch.aidl.IAppSearchObserverProxy;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070041import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070042import android.app.appsearch.exceptions.AppSearchException;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080043import android.app.appsearch.observer.AppSearchObserverCallback;
44import android.app.appsearch.observer.DocumentChangeInfo;
45import android.app.appsearch.observer.ObserverSpec;
46import android.app.appsearch.observer.SchemaChangeInfo;
Terry Wang12dc6c02021-03-31 19:26:16 -070047import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070048import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070049import android.content.Intent;
50import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070051import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070052import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070053import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080054import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070055import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080056import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080057import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080058import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080059import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070060import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080061import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080062import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080063import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070064
Cassie Wang15c86972021-02-09 13:43:25 -080065import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070066import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070067import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080068import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine14816e22021-07-12 10:53:24 -070069import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070070import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080071import com.android.server.appsearch.observer.AppSearchObserverProxy;
Xiaoyu Jin10329472021-06-23 16:50:03 -070072import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070073import com.android.server.appsearch.util.PackageUtil;
Terry Wange15ea582021-10-21 18:59:21 -070074import com.android.server.appsearch.visibilitystore.VisibilityDocument;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070075import com.android.server.usage.StorageStatsManagerLocal;
76import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080077
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070078import com.google.android.icing.proto.PersistType;
79
Terry Wang623e3b02021-02-02 20:27:33 -080080import java.io.DataInputStream;
81import java.io.DataOutputStream;
82import java.io.EOFException;
83import java.io.FileInputStream;
84import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080085import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080086import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080087import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080088import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080089import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070090import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070091import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070092import java.util.concurrent.ThreadPoolExecutor;
93import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080094
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070095/**
96 * The main service implementation which contains AppSearch's platform functionality.
Yang Yuc047f7b2021-06-25 12:22:42 -070097 *
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070098 * @hide
99 */
Terry Wangfebbead2019-10-17 17:05:18 -0700100public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700101 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -0700102 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700103 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700104 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700105 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -0700106
Terry Wange04ceab2021-03-29 19:25:12 -0700107 // Never call shutdownNow(). It will cancel the futures it's returned. And since
108 // Executor#execute won't return anything, we will hang forever waiting for the execution.
109 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
110 // mutate requests will need to gain write lock and query requests need to gain read lock.
111 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
112 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700113 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700114
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700115 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
116 // suffix refers to the fact that access to the field should be locked; unrelated to the
117 // unlocked status of users.
118 @GuardedBy("mUnlockedUsersLocked")
119 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800120
Terry Wangfebbead2019-10-17 17:05:18 -0700121 public AppSearchManagerService(Context context) {
122 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700123 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700124 }
125
126 @Override
127 public void onStart() {
128 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700129 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700130 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700131 mUserManager = mContext.getSystemService(UserManager.class);
132 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700133 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700134 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700135 }
136
Xiaoyu Jin10329472021-06-23 16:50:03 -0700137 @Override
138 public void onBootPhase(/* @BootPhase */ int phase) {
139 if (phase == PHASE_BOOT_COMPLETED) {
140 StatsCollector.getInstance(mContext, EXECUTOR);
141 }
142 }
143
Terry Wang12dc6c02021-03-31 19:26:16 -0700144 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700145 mContext.registerReceiverForAllUsers(
146 new UserActionReceiver(),
147 new IntentFilter(Intent.ACTION_USER_REMOVED),
148 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700149 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700150
151 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
152 // broadcasts
153 IntentFilter packageChangedFilter = new IntentFilter();
154 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
155 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
156 packageChangedFilter.addDataScheme("package");
157 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700158 mContext.registerReceiverForAllUsers(
159 new PackageChangedReceiver(),
160 packageChangedFilter,
161 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700162 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700163 }
164
165 private class UserActionReceiver extends BroadcastReceiver {
166 @Override
167 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700168 Objects.requireNonNull(context);
169 Objects.requireNonNull(intent);
170
Terry Wang12dc6c02021-03-31 19:26:16 -0700171 switch (intent.getAction()) {
172 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700173 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
174 if (userHandle == null) {
175 Log.e(TAG, "Extra "
176 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700177 return;
178 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700179 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700180 break;
181 default:
Terry Wange201dc02021-04-16 01:03:20 -0700182 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700183 }
184 }
185 }
186
187 /**
188 * Handles user removed action.
189 *
190 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
191 * "credential encrypted" system directory of each user. That directory will be auto-deleted
192 * when a user is removed.
193 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700194 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700195 * @see android.os.Environment#getDataSystemCeDirectory
196 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700197 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700198 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700199 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700200 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700201 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700202 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700203 }
204 }
205
206 private class PackageChangedReceiver extends BroadcastReceiver {
207 @Override
208 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700209 Objects.requireNonNull(context);
210 Objects.requireNonNull(intent);
211
Terry Wange201dc02021-04-16 01:03:20 -0700212 switch (intent.getAction()) {
213 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
214 case Intent.ACTION_PACKAGE_DATA_CLEARED:
215 String packageName = intent.getData().getSchemeSpecificPart();
216 if (packageName == null) {
217 Log.e(TAG, "Package name is missing in the intent: " + intent);
218 return;
219 }
220 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
221 if (uid == INVALID_UID) {
222 Log.e(TAG, "uid is missing in the intent: " + intent);
223 return;
224 }
225 handlePackageRemoved(packageName, uid);
226 break;
227 default:
228 Log.e(TAG, "Received unknown intent: " + intent);
229 }
230 }
231 }
232
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700233 private void handlePackageRemoved(@NonNull String packageName, int uid) {
234 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700235 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700236 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700237 // We cannot access a locked user's directry and remove package data from it.
238 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700239 return;
240 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700241 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700242 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700243 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700244 AppSearchUserInstance instance =
245 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700246 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700247 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700248 instance.getAppSearchImpl().clearPackageData(packageName);
249 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700250 }
251 } catch (Throwable t) {
252 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700253 }
Terry Wangfebbead2019-10-17 17:05:18 -0700254 }
255
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800256 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700257 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700258 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700259 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700260 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700261 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800262 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700263 EXECUTOR.execute(() -> {
264 try {
265 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700266 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700267 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700268 AppSearchUserInstance instance =
269 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700270 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
271 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700272 .getPackageManager()
273 .getInstalledPackages(/*flags=*/0);
274 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
275 for (int i = 0; i < installedPackageInfos.size(); i++) {
276 packagesToKeep.add(installedPackageInfos.get(i).packageName);
277 }
278 packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
279 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700280 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700281 }
282 } catch (Throwable t) {
283 Log.e(TAG, "Unable to prune packages for " + user, t);
284 }
285 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800286 }
287
Terry Wangde9f3382021-04-28 19:45:07 -0700288 @Override
289 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700290 Objects.requireNonNull(user);
291
292 synchronized (mUnlockedUsersLocked) {
293 UserHandle userHandle = user.getUserHandle();
294 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700295 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700296 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700297 } catch (Throwable t) {
298 Log.e(TAG, "Error handling user stopping.", t);
299 }
300 }
301 }
302
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700303 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
304 if (isUserLocked(callingUser)) {
305 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700306 }
307 }
308
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700309 private boolean isUserLocked(@NonNull UserHandle callingUser) {
310 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700311 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700312 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700313 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700314 }
315 // If the local copy says the user is locked, check with UM for the actual state,
316 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700317 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700318 }
319 }
320
Terry Wangfebbead2019-10-17 17:05:18 -0700321 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800322 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800323 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800324 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700325 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700326 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800327 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700328 @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800329 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700330 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700331 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700332 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800333 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700334 Objects.requireNonNull(packageName);
335 Objects.requireNonNull(databaseName);
336 Objects.requireNonNull(schemaBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700337 Objects.requireNonNull(schemasNotDisplayedBySystem);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700338 Objects.requireNonNull(schemasVisibleToPackagesBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700339 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700340 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700341
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700342 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000343 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800344 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700345 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700346 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700347 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700348 int operationSuccessCount = 0;
349 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700350 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000351 verifyCaller(callingUid, packageName);
352
353 // Obtain the user where the client wants to run the operations in. This should
354 // end up being the same as userHandle, assuming it is not a special user and
355 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000356 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000357 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000358
Terry Wange04ceab2021-03-29 19:25:12 -0700359 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
360 for (int i = 0; i < schemaBundles.size(); i++) {
361 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800362 }
Terry Wange15ea582021-10-21 18:59:21 -0700363 // TODO(b/202194495) move build VisibilityDocument to the SDK side and only pass
364 // it/s bundle via binder.
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700365 Map<String, List<PackageIdentifier>> schemasVisibleToPackages =
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700366 new ArrayMap<>(schemasVisibleToPackagesBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700367 for (Map.Entry<String, List<Bundle>> entry :
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700368 schemasVisibleToPackagesBundles.entrySet()) {
Terry Wange04ceab2021-03-29 19:25:12 -0700369 List<PackageIdentifier> packageIdentifiers =
370 new ArrayList<>(entry.getValue().size());
371 for (int i = 0; i < entry.getValue().size(); i++) {
372 packageIdentifiers.add(
373 new PackageIdentifier(entry.getValue().get(i)));
374 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700375 schemasVisibleToPackages.put(entry.getKey(), packageIdentifiers);
Terry Wange04ceab2021-03-29 19:25:12 -0700376 }
Terry Wange15ea582021-10-21 18:59:21 -0700377 List<VisibilityDocument> visibilityDocuments = VisibilityDocument
378 .toVisibilityDocuments(schemas, schemasNotDisplayedBySystem,
379 schemasVisibleToPackages);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000380 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700381 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700382 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700383 packageName,
384 databaseName,
385 schemas,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700386 instance.getVisibilityStore(),
Terry Wange15ea582021-10-21 18:59:21 -0700387 visibilityDocuments,
Terry Wange04ceab2021-03-29 19:25:12 -0700388 forceOverride,
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700389 schemaVersion,
390 /*setSchemaStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700391 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700392 invokeCallbackOnResult(callback,
393 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700394
395 // setSchema will sync the schemas in the request to AppSearch, any existing
396 // schemas which is not included in the request will be delete if we force
397 // override incompatible schemas. And all documents of these types will be
398 // deleted as well. We should checkForOptimize for these deletion.
399 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700400 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700401 ++operationFailureCount;
402 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700403 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700404 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700405 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700406 int estimatedBinderLatencyMillis =
407 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
408 int totalLatencyMillis =
409 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700410 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700411 .setPackageName(packageName)
412 .setDatabase(databaseName)
413 .setStatusCode(statusCode)
414 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700415 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
416 // TODO(b/173532925) check the existing binder call latency chart
417 // is good enough for us:
418 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
419 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
420 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700421 .setNumOperationsFailed(operationFailureCount)
422 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700423 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800424 }
Terry Wange04ceab2021-03-29 19:25:12 -0700425 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800426 }
427
428 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800429 public void getSchema(
Alexander Dorokhined41def42022-01-25 15:45:34 -0800430 @NonNull String callingPackageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800431 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800432 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700433 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800434 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800435 Objects.requireNonNull(callingPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700436 Objects.requireNonNull(packageName);
437 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700438 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700439 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700440
Cassie Wang2e2d0552021-08-04 16:18:10 +0000441 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700442 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700443 EXECUTOR.execute(() -> {
444 try {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800445 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000446
447 // Obtain the user where the client wants to run the operations in. This should
448 // end up being the same as userHandle, assuming it is not a special user and
449 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000450 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000451 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000452
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700453 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000454 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700455 GetSchemaResponse response =
Alexander Dorokhined41def42022-01-25 15:45:34 -0800456 instance.getAppSearchImpl().getSchema(
457 callingPackageName, packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700458 invokeCallbackOnResult(
459 callback,
460 AppSearchResult.newSuccessfulResult(response.getBundle()));
461 } catch (Throwable t) {
462 invokeCallbackOnError(callback, t);
463 }
464 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700465 }
466
467 @Override
468 public void getNamespaces(
469 @NonNull String packageName,
470 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700471 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700472 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700473 Objects.requireNonNull(packageName);
474 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700475 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700476 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700477
Cassie Wang2e2d0552021-08-04 16:18:10 +0000478 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700479 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700480 EXECUTOR.execute(() -> {
481 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000482 verifyCaller(callingUid, packageName);
483
484 // Obtain the user where the client wants to run the operations in. This should
485 // end up being the same as userHandle, assuming it is not a special user and
486 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000487 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000488 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000489
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700490 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000491 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700492 List<String> namespaces =
493 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
494 invokeCallbackOnResult(
495 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700496 } catch (Throwable t) {
497 invokeCallbackOnError(callback, t);
498 }
499 });
Terry Wang83a24932020-12-09 21:00:18 -0800500 }
501
502 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800503 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800504 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700505 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700506 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700507 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800508 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800509 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700510 Objects.requireNonNull(packageName);
511 Objects.requireNonNull(databaseName);
512 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700513 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700514 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700515
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700516 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000517 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800518 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700519 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800520 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700521 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800522 int operationSuccessCount = 0;
523 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700524 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000525 verifyCaller(callingUid, packageName);
526
527 // Obtain the user where the client wants to run the operations in. This should
528 // end up being the same as userHandle, assuming it is not a special user and
529 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000530 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000531 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000532
Terry Wange04ceab2021-03-29 19:25:12 -0700533 AppSearchBatchResult.Builder<String, Void> resultBuilder =
534 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000535 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700536 for (int i = 0; i < documentBundles.size(); i++) {
537 GenericDocument document = new GenericDocument(documentBundles.get(i));
538 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700539 instance.getAppSearchImpl().putDocument(
540 packageName, databaseName, document, instance.getLogger());
541 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800542 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700543 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700544 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800545 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700546 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700547 // Since we can only include one status code in the atom,
548 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800549 statusCode = result.getResultCode();
550 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700551 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800552 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700553 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700554 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700555 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700556
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800557 // Schedule a task to dispatch change notifications. See requirements for where
558 // the method is called documented in the method description.
559 dispatchChangeNotifications(instance);
560
Terry Wangf4d219b2021-07-01 19:11:39 -0700561 // The existing documents with same ID will be deleted, so there may be some
562 // resources that could be released after optimize().
563 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700564 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700565 ++operationFailureCount;
566 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700567 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800568 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700569 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700570 int estimatedBinderLatencyMillis =
571 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
572 int totalLatencyMillis =
573 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700574 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700575 .setPackageName(packageName)
576 .setDatabase(databaseName)
577 .setStatusCode(statusCode)
578 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800579 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
580 // TODO(b/173532925) check the existing binder call latency chart
581 // is good enough for us:
582 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700583 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800584 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700585 .setNumOperationsFailed(operationFailureCount)
586 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800587 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800588 }
Terry Wange04ceab2021-03-29 19:25:12 -0700589 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800590 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800591
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800592 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800593 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800594 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800595 @NonNull String databaseName,
596 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700597 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800598 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700599 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700600 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800601 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700602 Objects.requireNonNull(packageName);
603 Objects.requireNonNull(databaseName);
604 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700605 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700606 Objects.requireNonNull(typePropertyPaths);
607 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700608 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700609
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700610 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000611 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800612 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700613 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700614 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700615 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700616 int operationSuccessCount = 0;
617 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700618 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000619 verifyCaller(callingUid, packageName);
620
621 // Obtain the user where the client wants to run the operations in. This should
622 // end up being the same as userHandle, assuming it is not a special user and
623 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000624 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000625 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000626
Terry Wange04ceab2021-03-29 19:25:12 -0700627 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
628 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000629 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700630 for (int i = 0; i < ids.size(); i++) {
631 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700632 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700633 GenericDocument document = instance.getAppSearchImpl().getDocument(
634 packageName,
635 databaseName,
636 namespace,
637 id,
638 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700639 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700640 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700641 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700642 // Since we can only include one status code in the atom,
643 // for failures, we would just save the one for the last failure
644 AppSearchResult<Bundle> result = throwableToFailedResult(t);
645 resultBuilder.setResult(id, result);
646 statusCode = result.getResultCode();
647 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700648 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800649 }
Terry Wange04ceab2021-03-29 19:25:12 -0700650 invokeCallbackOnResult(callback, resultBuilder.build());
651 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700652 ++operationFailureCount;
653 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700654 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700655 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700656 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700657 int estimatedBinderLatencyMillis =
658 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
659 int totalLatencyMillis =
660 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700661 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700662 .setPackageName(packageName)
663 .setDatabase(databaseName)
664 .setStatusCode(statusCode)
665 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700666 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
667 // TODO(b/173532925) check the existing binder call latency chart
668 // is good enough for us:
669 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
670 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
671 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700672 .setNumOperationsFailed(operationFailureCount)
673 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700674 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800675 }
Terry Wange04ceab2021-03-29 19:25:12 -0700676 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800677 }
678
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800679 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800680 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800681 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700682 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700683 @NonNull String queryExpression,
684 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700685 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700686 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700687 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700688 Objects.requireNonNull(packageName);
689 Objects.requireNonNull(databaseName);
690 Objects.requireNonNull(queryExpression);
691 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700692 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700693 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700694
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700695 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000696 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800697 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700698 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700699 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700700 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700701 int operationSuccessCount = 0;
702 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700703 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000704 verifyCaller(callingUid, packageName);
705
706 // Obtain the user where the client wants to run the operations in. This should
707 // end up being the same as userHandle, assuming it is not a special user and
708 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000709 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000710 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000711
Cassie Wang2feb34d2021-07-22 18:55:19 +0000712 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700713 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
714 packageName,
715 databaseName,
716 queryExpression,
717 new SearchSpec(searchSpecBundle),
718 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700719 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700720 invokeCallbackOnResult(
721 callback,
722 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
723 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700724 ++operationFailureCount;
725 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700726 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700727 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700728 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700729 int estimatedBinderLatencyMillis =
730 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
731 int totalLatencyMillis =
732 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700733 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700734 .setPackageName(packageName)
735 .setDatabase(databaseName)
736 .setStatusCode(statusCode)
737 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700738 .setCallType(CallStats.CALL_TYPE_SEARCH)
739 // TODO(b/173532925) check the existing binder call latency chart
740 // is good enough for us:
741 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
742 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
743 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700744 .setNumOperationsFailed(operationFailureCount)
745 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700746 }
Terry Wange04ceab2021-03-29 19:25:12 -0700747 }
748 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700749 }
750
Terry Wangf2093072020-11-30 04:47:19 -0800751 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800752 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800753 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800754 @NonNull String queryExpression,
755 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700756 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700757 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800758 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700759 Objects.requireNonNull(packageName);
760 Objects.requireNonNull(queryExpression);
761 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700762 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700763 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700764
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700765 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000766 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800767 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700768 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700769 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700770 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700771 int operationSuccessCount = 0;
772 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700773 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000774 verifyCaller(callingUid, packageName);
775
776 // Obtain the user where the client wants to run the operations in. This should
777 // end up being the same as userHandle, assuming it is not a special user and
778 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000779 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000780 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000781
Cassie Wang2feb34d2021-07-22 18:55:19 +0000782 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700783
784 boolean callerHasSystemAccess =
785 instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
786 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
787 queryExpression,
788 new SearchSpec(searchSpecBundle),
789 packageName,
790 instance.getVisibilityStore(),
791 callingUid,
792 callerHasSystemAccess,
793 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700794 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700795 invokeCallbackOnResult(
796 callback,
797 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700798 } catch (Throwable t) {
799 ++operationFailureCount;
800 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700801 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700802 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700803 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700804 int estimatedBinderLatencyMillis =
805 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
806 int totalLatencyMillis =
807 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700808 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700809 .setPackageName(packageName)
810 .setStatusCode(statusCode)
811 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700812 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
813 // TODO(b/173532925) check the existing binder call latency chart
814 // is good enough for us:
815 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
816 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
817 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700818 .setNumOperationsFailed(operationFailureCount)
819 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700820 }
Terry Wange04ceab2021-03-29 19:25:12 -0700821 }
822 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800823 }
824
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700825 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800826 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700827 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800828 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700829 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700830 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700831 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700832 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700833 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700834
Cassie Wang2e2d0552021-08-04 16:18:10 +0000835 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800836 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700837 EXECUTOR.execute(() -> {
838 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000839 verifyCaller(callingUid, packageName);
840
841 // Obtain the user where the client wants to run the operations in. This should
842 // end up being the same as userHandle, assuming it is not a special user and
843 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000844 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000845 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000846
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700847 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000848 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700849 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700850 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700851 instance.getAppSearchImpl().getNextPage(
852 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700853 invokeCallbackOnResult(
854 callback,
855 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
856 } catch (Throwable t) {
857 invokeCallbackOnError(callback, t);
858 }
859 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700860 }
861
862 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700863 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
864 @NonNull UserHandle userHandle) {
865 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700866 Objects.requireNonNull(userHandle);
867
Cassie Wang2e2d0552021-08-04 16:18:10 +0000868 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800869 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700870 EXECUTOR.execute(() -> {
871 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000872 verifyCaller(callingUid, packageName);
873
874 // Obtain the user where the client wants to run the operations in. This should
875 // end up being the same as userHandle, assuming it is not a special user and
876 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000877 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000878 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000879
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700880 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000881 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700882 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700883 } catch (Throwable t) {
884 Log.e(TAG, "Unable to invalidate the query page token", t);
885 }
886 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800887 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800888
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700889 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800890 public void writeQueryResultsToFile(
891 @NonNull String packageName,
892 @NonNull String databaseName,
893 @NonNull ParcelFileDescriptor fileDescriptor,
894 @NonNull String queryExpression,
895 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700896 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800897 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700898 Objects.requireNonNull(packageName);
899 Objects.requireNonNull(databaseName);
900 Objects.requireNonNull(fileDescriptor);
901 Objects.requireNonNull(queryExpression);
902 Objects.requireNonNull(searchSpecBundle);
903 Objects.requireNonNull(userHandle);
904 Objects.requireNonNull(callback);
905
Cassie Wang2e2d0552021-08-04 16:18:10 +0000906 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800907 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700908 EXECUTOR.execute(() -> {
909 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000910 verifyCaller(callingUid, packageName);
911
912 // Obtain the user where the client wants to run the operations in. This should
913 // end up being the same as userHandle, assuming it is not a special user and
914 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000915 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000916 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000917
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700918 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000919 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700920 // we don't need to append the file. The file is always brand new.
921 try (DataOutputStream outputStream = new DataOutputStream(
922 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700923 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700924 packageName,
925 databaseName,
926 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700927 new SearchSpec(searchSpecBundle),
928 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700929 while (!searchResultPage.getResults().isEmpty()) {
930 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
931 AppSearchMigrationHelper.writeBundleToOutputStream(
932 outputStream, searchResultPage.getResults().get(i)
933 .getGenericDocument().getBundle());
934 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700935 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700936 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700937 packageName,
938 searchResultPage.getNextPageToken(),
939 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800940 }
Terry Wang623e3b02021-02-02 20:27:33 -0800941 }
Terry Wange04ceab2021-03-29 19:25:12 -0700942 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
943 } catch (Throwable t) {
944 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800945 }
Terry Wange04ceab2021-03-29 19:25:12 -0700946 });
Terry Wang623e3b02021-02-02 20:27:33 -0800947 }
948
949 @Override
950 public void putDocumentsFromFile(
951 @NonNull String packageName,
952 @NonNull String databaseName,
953 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700954 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800955 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700956 Objects.requireNonNull(packageName);
957 Objects.requireNonNull(databaseName);
958 Objects.requireNonNull(fileDescriptor);
959 Objects.requireNonNull(userHandle);
960 Objects.requireNonNull(callback);
961
Cassie Wang2e2d0552021-08-04 16:18:10 +0000962 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800963 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700964 EXECUTOR.execute(() -> {
965 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000966 verifyCaller(callingUid, packageName);
967
968 // Obtain the user where the client wants to run the operations in. This should
969 // end up being the same as userHandle, assuming it is not a special user and
970 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000971 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000972 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000973
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700974 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000975 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800976
Terry Wange04ceab2021-03-29 19:25:12 -0700977 GenericDocument document;
978 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
979 try (DataInputStream inputStream = new DataInputStream(
980 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
981 while (true) {
982 try {
983 document = AppSearchMigrationHelper
984 .readDocumentFromInputStream(inputStream);
985 } catch (EOFException e) {
986 // nothing wrong, we just finish the reading.
987 break;
988 }
989 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700990 instance.getAppSearchImpl().putDocument(
991 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700992 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700993 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
994 document.getNamespace(),
995 document.getId(),
996 document.getSchemaType(),
997 AppSearchResult.throwableToFailedResult(t))
998 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700999 }
Terry Wang623e3b02021-02-02 20:27:33 -08001000 }
1001 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001002 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -07001003 invokeCallbackOnResult(callback,
1004 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
1005 } catch (Throwable t) {
1006 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -08001007 }
Terry Wange04ceab2021-03-29 19:25:12 -07001008 });
Terry Wang623e3b02021-02-02 20:27:33 -08001009 }
1010
1011 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001012 public void reportUsage(
1013 @NonNull String packageName,
1014 @NonNull String databaseName,
1015 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001016 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001017 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001018 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001019 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001020 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001021 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001022 Objects.requireNonNull(databaseName);
1023 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001024 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001025 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001026 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001027
Cassie Wang2e2d0552021-08-04 16:18:10 +00001028 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001029 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001030 EXECUTOR.execute(() -> {
1031 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001032 verifyCaller(callingUid, packageName);
1033
1034 // Obtain the user where the client wants to run the operations in. This should
1035 // end up being the same as userHandle, assuming it is not a special user and
1036 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001037 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001038 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001039
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001040 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001041 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001042
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001043 if (systemUsage
1044 && !instance.getVisibilityStore()
1045 .doesCallerHaveSystemAccess(packageName)) {
1046 throw new AppSearchException(
1047 AppSearchResult.RESULT_SECURITY_ERROR,
1048 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001049 }
1050
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001051 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001052 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001053 usageTimeMillis, systemUsage);
1054 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001055 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001056 } catch (Throwable t) {
1057 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001058 }
Terry Wange04ceab2021-03-29 19:25:12 -07001059 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001060 }
1061
1062 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001063 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001064 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001065 @NonNull String databaseName,
1066 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001067 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001068 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001069 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001070 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001071 Objects.requireNonNull(packageName);
1072 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001073 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001074 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001075 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001076 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001077
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001078 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001079 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001080 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001081 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001082 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001083 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001084 int operationSuccessCount = 0;
1085 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001086 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001087 verifyCaller(callingUid, packageName);
1088
1089 // Obtain the user where the client wants to run the operations in. This should
1090 // end up being the same as userHandle, assuming it is not a special user and
1091 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001092 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001093 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001094
Terry Wange04ceab2021-03-29 19:25:12 -07001095 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1096 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001097 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001098 for (int i = 0; i < ids.size(); i++) {
1099 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001100 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001101 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001102 packageName,
1103 databaseName,
1104 namespace,
1105 id,
1106 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001107 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001108 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001109 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001110 AppSearchResult<Void> result = throwableToFailedResult(t);
1111 resultBuilder.setResult(id, result);
1112 // Since we can only include one status code in the atom,
1113 // for failures, we would just save the one for the last failure
1114 statusCode = result.getResultCode();
1115 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001116 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001117 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001118 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001119 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001120 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001121
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001122 // Schedule a task to dispatch change notifications. See requirements for where
1123 // the method is called documented in the method description.
1124 dispatchChangeNotifications(instance);
1125
Terry Wangf4d219b2021-07-01 19:11:39 -07001126 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001127 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001128 ++operationFailureCount;
1129 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001130 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001131 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001132 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001133 int estimatedBinderLatencyMillis =
1134 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1135 int totalLatencyMillis =
1136 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001137 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001138 .setPackageName(packageName)
1139 .setDatabase(databaseName)
1140 .setStatusCode(statusCode)
1141 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001142 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1143 // TODO(b/173532925) check the existing binder call latency chart
1144 // is good enough for us:
1145 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1146 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1147 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001148 .setNumOperationsFailed(operationFailureCount)
1149 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001150 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001151 }
Terry Wange04ceab2021-03-29 19:25:12 -07001152 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001153 }
1154
1155 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001156 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001157 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001158 @NonNull String databaseName,
1159 @NonNull String queryExpression,
1160 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001161 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001162 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001163 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001164 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001165 Objects.requireNonNull(packageName);
1166 Objects.requireNonNull(databaseName);
1167 Objects.requireNonNull(queryExpression);
1168 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001169 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001170 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001171
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001172 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001173 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001174 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001175 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001176 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001177 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001178 int operationSuccessCount = 0;
1179 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001180 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001181 verifyCaller(callingUid, packageName);
1182
1183 // Obtain the user where the client wants to run the operations in. This should
1184 // end up being the same as userHandle, assuming it is not a special user and
1185 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001186 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001187 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001188
Cassie Wang2feb34d2021-07-22 18:55:19 +00001189 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001190 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001191 packageName,
1192 databaseName,
1193 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001194 new SearchSpec(searchSpecBundle),
1195 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001196 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001197 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001198 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001199 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001200
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001201 // Schedule a task to dispatch change notifications. See requirements for where
1202 // the method is called documented in the method description.
1203 dispatchChangeNotifications(instance);
1204
Terry Wangf4d219b2021-07-01 19:11:39 -07001205 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001206 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001207 ++operationFailureCount;
1208 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001209 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001210 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001211 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001212 int estimatedBinderLatencyMillis =
1213 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1214 int totalLatencyMillis =
1215 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001216 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001217 .setPackageName(packageName)
1218 .setDatabase(databaseName)
1219 .setStatusCode(statusCode)
1220 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001221 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1222 // TODO(b/173532925) check the existing binder call latency chart
1223 // is good enough for us:
1224 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1225 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1226 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001227 .setNumOperationsFailed(operationFailureCount)
1228 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001229 }
Terry Wange04ceab2021-03-29 19:25:12 -07001230 }
1231 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001232 }
1233
Terry Wangdbd1dca2020-11-03 17:03:56 -08001234 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001235 public void getStorageInfo(
1236 @NonNull String packageName,
1237 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001238 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001239 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001240 Objects.requireNonNull(packageName);
1241 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001242 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001243 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001244
Cassie Wang2e2d0552021-08-04 16:18:10 +00001245 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001246 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001247 EXECUTOR.execute(() -> {
1248 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001249 verifyCaller(callingUid, packageName);
1250
1251 // Obtain the user where the client wants to run the operations in. This should
1252 // end up being the same as userHandle, assuming it is not a special user and
1253 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001254 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001255 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001256
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001257 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001258 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001259 StorageInfo storageInfo = instance.getAppSearchImpl()
1260 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001261 Bundle storageInfoBundle = storageInfo.getBundle();
1262 invokeCallbackOnResult(
1263 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1264 } catch (Throwable t) {
1265 invokeCallbackOnError(callback, t);
1266 }
1267 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001268 }
1269
1270 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001271 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001272 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001273 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001274 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001275 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001276 Objects.requireNonNull(userHandle);
1277
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001278 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001279 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001280 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001281 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001282 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001283 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001284 int operationSuccessCount = 0;
1285 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001286 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001287 verifyCaller(callingUid, packageName);
1288
1289 // Obtain the user where the client wants to run the operations in. This should
1290 // end up being the same as userHandle, assuming it is not a special user and
1291 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001292 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001293 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001294
Cassie Wang2feb34d2021-07-22 18:55:19 +00001295 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001296 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001297 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001298 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001299 ++operationFailureCount;
1300 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001301 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001302 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001303 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001304 int estimatedBinderLatencyMillis =
1305 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1306 int totalLatencyMillis =
1307 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001308 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001309 .setStatusCode(statusCode)
1310 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001311 .setCallType(CallStats.CALL_TYPE_FLUSH)
1312 // TODO(b/173532925) check the existing binder call latency chart
1313 // is good enough for us:
1314 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1315 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1316 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001317 .setNumOperationsFailed(operationFailureCount)
1318 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001319 }
Terry Wange04ceab2021-03-29 19:25:12 -07001320 }
1321 });
Terry Wang2da17852020-12-16 19:59:08 -08001322 }
1323
1324 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001325 public AppSearchResultParcel<Void> addObserver(
1326 @NonNull String callingPackage,
1327 @NonNull String observedPackage,
1328 @NonNull Bundle observerSpecBundle,
1329 @NonNull UserHandle userHandle,
1330 @NonNull IAppSearchObserverProxy observerProxyStub) {
1331 Objects.requireNonNull(callingPackage);
1332 Objects.requireNonNull(observedPackage);
1333 Objects.requireNonNull(observerSpecBundle);
1334 Objects.requireNonNull(userHandle);
1335 Objects.requireNonNull(observerProxyStub);
1336
1337 int callingPid = Binder.getCallingPid();
1338 int callingUid = Binder.getCallingUid();
1339 long callingIdentity = Binder.clearCallingIdentity();
1340
1341 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1342 try {
1343 verifyCaller(callingUid, callingPackage);
1344 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1345 verifyUserUnlocked(targetUser);
1346
1347 AppSearchUserInstance instance =
1348 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1349 instance.getAppSearchImpl().addObserver(
1350 observedPackage,
1351 new ObserverSpec(observerSpecBundle),
1352 EXECUTOR,
1353 new AppSearchObserverProxy(observerProxyStub));
1354 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1355 } catch (Throwable t) {
1356 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1357 } finally {
1358 Binder.restoreCallingIdentity(callingIdentity);
1359 }
1360 }
1361
1362 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001363 public AppSearchResultParcel<Void> removeObserver(
1364 @NonNull String callingPackage,
1365 @NonNull String observedPackage,
1366 @NonNull UserHandle userHandle,
1367 @NonNull IAppSearchObserverProxy observerProxyStub) {
1368 Objects.requireNonNull(callingPackage);
1369 Objects.requireNonNull(observedPackage);
1370 Objects.requireNonNull(userHandle);
1371 Objects.requireNonNull(observerProxyStub);
1372
1373 int callingPid = Binder.getCallingPid();
1374 int callingUid = Binder.getCallingUid();
1375 long callingIdentity = Binder.clearCallingIdentity();
1376
1377 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1378 try {
1379 verifyCaller(callingUid, callingPackage);
1380 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1381 verifyUserUnlocked(targetUser);
1382
1383 AppSearchUserInstance instance =
1384 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1385 instance.getAppSearchImpl().removeObserver(
1386 observedPackage,
1387 new AppSearchObserverProxy(observerProxyStub));
1388 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1389 } catch (Throwable t) {
1390 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1391 } finally {
1392 Binder.restoreCallingIdentity(callingIdentity);
1393 }
1394 }
1395
1396 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001397 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001398 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001399 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001400 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1401 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001402 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001403 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001404 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001405
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001406 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001407 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001408 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001409
Terry Wange04ceab2021-03-29 19:25:12 -07001410 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001411 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001412 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001413 int operationSuccessCount = 0;
1414 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001415 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001416 verifyCaller(callingUid, packageName);
1417
1418 // Obtain the user where the client wants to run the operations in. This should
1419 // end up being the same as userHandle, assuming it is not a special user and
1420 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001421 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001422 verifyUserUnlocked(targetUser);
1423
Cassie Wang2feb34d2021-07-22 18:55:19 +00001424 Context targetUserContext = mContext.createContextAsUser(targetUser,
1425 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001426 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001427 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001428 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001429 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1430 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001431 ++operationFailureCount;
1432 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001433 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001434 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001435 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001436 int estimatedBinderLatencyMillis =
1437 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1438 int totalLatencyMillis =
1439 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001440 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001441 .setStatusCode(statusCode)
1442 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001443 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1444 // TODO(b/173532925) check the existing binder call latency chart
1445 // is good enough for us:
1446 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1447 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1448 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001449 .setNumOperationsFailed(operationFailureCount)
1450 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001451 }
Terry Wange04ceab2021-03-29 19:25:12 -07001452 }
1453 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001454 }
1455
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001456 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001457 private void invokeCallbackOnResult(
1458 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001459 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001460 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001461 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001462 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001463 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001464 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001465
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001466 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001467 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001468 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001469 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001470 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001471 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001472 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001473 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001474 }
1475
1476 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001477 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001478 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001479 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001480 */
1481 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001482 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001483 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001484 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001485 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001486 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001487 }
1488 }
1489
1490 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001491 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001492 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001493 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001494 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001495 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001496 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001497 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001498 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001499 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001500 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001501 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001502 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001503 }
Terry Wangfebbead2019-10-17 17:05:18 -07001504 }
Terry Wangf2093072020-11-30 04:47:19 -08001505
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001506 /**
1507 * Helper for dealing with incoming user arguments to system service calls.
1508 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001509 * <p>Takes care of checking permissions and if the target is special user, this method will
1510 * simply throw.
1511 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001512 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001513 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001514 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001515 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001516 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001517 *
1518 * @throws IllegalArgumentException if the target user is a special user.
1519 * @throws SecurityException if caller trying to interact across user without
1520 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001521 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001522 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001523 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1524 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001525 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1526 if (callingUserHandle.equals(targetUserHandle)) {
1527 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001528 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001529
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001530 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001531 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001532 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001533 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001534 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001535
Cassie Wang2e2d0552021-08-04 16:18:10 +00001536 if (mContext.checkPermission(
1537 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1538 callingPid,
1539 callingUid) == PackageManager.PERMISSION_GRANTED) {
1540 return targetUserHandle;
1541 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001542 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001543 "Permission denied while calling from uid " + callingUid
1544 + " with " + targetUserHandle + "; Requires permission: "
1545 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001546 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001547
Cassie Wang84e33a02021-06-18 14:13:31 -07001548 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001549 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001550 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001551 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1552 * @param claimedCallingPackage Package name the caller claims to be.
1553 */
1554 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1555 // Obtain the user where the client is running in. Note that this could be different from
1556 // the userHandle where the client wants to run the AppSearch operation in.
1557 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1558 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1559 /*flags=*/ 0);
1560
1561 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1562 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1563 }
1564
1565 /**
1566 * Check that the caller's supposed package name matches the uid making the call.
1567 *
1568 * @throws SecurityException if the package name and uid don't match.
1569 */
1570 private void verifyCallingPackage(
1571 @NonNull Context actualCallingUserContext,
1572 int actualCallingUid,
1573 @NonNull String claimedCallingPackage) {
1574 int claimedCallingUid = PackageUtil.getPackageUid(
1575 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001576 if (claimedCallingUid != actualCallingUid) {
1577 throw new SecurityException(
1578 "Specified calling package ["
1579 + claimedCallingPackage
1580 + "] does not match the calling uid "
1581 + actualCallingUid);
1582 }
1583 }
1584
1585 /**
1586 * Ensure instant apps can't make calls to AppSearch.
1587 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001588 * @throws SecurityException if the caller is an instant app.
1589 */
1590 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1591 PackageManager callingPackageManager = userContext.getPackageManager();
1592 if (callingPackageManager.isInstantApp(packageName)) {
1593 throw new SecurityException("Caller not allowed to create AppSearch session"
1594 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1595 }
1596 }
1597
Yang Yu0fcd51a2021-04-23 11:25:44 -07001598 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1599 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001600 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001601 @NonNull PackageStats stats,
1602 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001603 @NonNull UserHandle userHandle,
1604 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001605 Objects.requireNonNull(stats);
1606 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001607 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001608
Yang Yu0fcd51a2021-04-23 11:25:44 -07001609 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001610 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001611 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001612 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1613 if (instance == null) {
1614 // augment storage info from file
1615 UserStorageInfo userStorageInfo =
1616 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1617 userHandle);
1618 stats.dataSize +=
1619 userStorageInfo.getSizeBytesForPackage(packageName);
1620 } else {
1621 stats.dataSize += instance.getAppSearchImpl()
1622 .getStorageInfoForPackage(packageName).getSizeBytes();
1623 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001624 } catch (Throwable t) {
1625 Log.e(
1626 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001627 "Unable to augment storage stats for "
1628 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001629 + " packageName "
1630 + packageName,
1631 t);
1632 }
1633 }
1634
1635 @Override
1636 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001637 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001638 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001639
1640 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001641 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001642 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001643 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1644 if (packagesForUid == null) {
1645 return;
1646 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001647 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001648 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1649 if (instance == null) {
1650 // augment storage info from file
1651 UserStorageInfo userStorageInfo =
1652 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1653 userHandle);
1654 for (int i = 0; i < packagesForUid.length; i++) {
1655 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1656 packagesForUid[i]);
1657 }
1658 } else {
1659 for (int i = 0; i < packagesForUid.length; i++) {
1660 stats.dataSize += instance.getAppSearchImpl()
1661 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1662 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001663 }
1664 } catch (Throwable t) {
1665 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1666 }
1667 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001668
1669 @Override
1670 public void augmentStatsForUser(
1671 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1672 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1673 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1674 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1675 Objects.requireNonNull(stats);
1676 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001677
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001678 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001679 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001680 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001681 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1682 if (instance == null) {
1683 // augment storage info from file
1684 UserStorageInfo userStorageInfo =
1685 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1686 userHandle);
1687 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1688 } else {
1689 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1690 /*flags=*/0, userHandle.getIdentifier());
1691 if (packagesForUser != null) {
1692 for (int i = 0; i < packagesForUser.size(); i++) {
1693 String packageName = packagesForUser.get(i).packageName;
1694 stats.dataSize += instance.getAppSearchImpl()
1695 .getStorageInfoForPackage(packageName).getSizeBytes();
1696 }
1697 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001698 }
1699 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001700 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001701 }
1702 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001703 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001704
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001705 /**
1706 * Dispatches change notifications if there are any to dispatch.
1707 *
1708 * <p>This method is async; notifications are dispatched onto their own registered executors.
1709 *
1710 * <p>IMPORTANT: You must always call this within the background task that contains the
1711 * operation that mutated the index. If you called it outside of that task, it could start
1712 * before the task completes, causing notifications to be missed.
1713 */
1714 @WorkerThread
1715 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1716 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1717 }
1718
1719 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001720 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1721 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001722 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1723 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001724 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001725 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001726 } catch (AppSearchException e) {
1727 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001728 } finally {
1729 OptimizeStats oStats = builder
1730 .setTotalLatencyMillis(
1731 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1732 .build();
1733 if (oStats.getOriginalDocumentCount() > 0) {
1734 // see if optimize has been run by checking originalDocumentCount
1735 instance.getLogger().logStats(oStats);
1736 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001737 }
1738 });
1739 }
1740
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001741 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001742 private void checkForOptimize(AppSearchUserInstance instance) {
1743 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001744 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1745 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001746 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001747 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001748 } catch (AppSearchException e) {
1749 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001750 } finally {
1751 OptimizeStats oStats = builder
1752 .setTotalLatencyMillis(
1753 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1754 .build();
1755 if (oStats.getOriginalDocumentCount() > 0) {
1756 // see if optimize has been run by checking originalDocumentCount
1757 instance.getLogger().logStats(oStats);
1758 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001759 }
1760 });
1761 }
Terry Wangfebbead2019-10-17 17:05:18 -07001762}