blob: edd0786b0a8e357aa0be34e5ab7ab86682b764be [file] [log] [blame]
Terry Wangfebbead2019-10-17 17:05:18 -07001/*
sidchhabraa7c8f8a2020-01-16 18:38:17 -08002 * Copyright (C) 2020 The Android Open Source Project
Terry Wangfebbead2019-10-17 17:05:18 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.appsearch;
17
Terry Wangdbd1dca2020-11-03 17:03:56 -080018import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
Terry Wange201dc02021-04-16 01:03:20 -070019import static android.os.Process.INVALID_UID;
Terry Wangdbd1dca2020-11-03 17:03:56 -080020
Alexander Dorokhine5c416772021-06-04 09:05:00 -070021import android.Manifest;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080022import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080023import android.annotation.NonNull;
Alexander Dorokhine18465842020-01-21 01:08:57 -080024import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080025import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080026import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070027import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070028import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070029import android.app.appsearch.GetSchemaResponse;
Alexander Dorokhineab789062021-01-11 21:00:00 -080030import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070031import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070032import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080033import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070034import android.app.appsearch.StorageInfo;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070035import android.app.appsearch.aidl.AppSearchBatchResultParcel;
36import android.app.appsearch.aidl.AppSearchResultParcel;
37import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
38import android.app.appsearch.aidl.IAppSearchManager;
39import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070040import android.app.appsearch.exceptions.AppSearchException;
Terry Wang12dc6c02021-03-31 19:26:16 -070041import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070042import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070043import android.content.Intent;
44import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070045import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070046import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070047import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080048import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070049import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080050import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080051import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080052import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080053import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070054import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080055import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080056import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080057import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070058
Cassie Wang15c86972021-02-09 13:43:25 -080059import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070060import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070061import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080062import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070063import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070064import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070065import com.android.server.usage.StorageStatsManagerLocal;
66import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080067
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070068import com.google.android.icing.proto.PersistType;
69
Terry Wang623e3b02021-02-02 20:27:33 -080070import java.io.DataInputStream;
71import java.io.DataOutputStream;
72import java.io.EOFException;
73import java.io.FileInputStream;
74import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080075import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080076import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080077import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080078import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080079import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070080import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070081import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070082import java.util.concurrent.ThreadPoolExecutor;
83import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080084
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070085/**
86 * The main service implementation which contains AppSearch's platform functionality.
87 * @hide
88 */
Terry Wangfebbead2019-10-17 17:05:18 -070089public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070090 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070091 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070092 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070093 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070094 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -070095
Terry Wange04ceab2021-03-29 19:25:12 -070096 // Never call shutdownNow(). It will cancel the futures it's returned. And since
97 // Executor#execute won't return anything, we will hang forever waiting for the execution.
98 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
99 // mutate requests will need to gain write lock and query requests need to gain read lock.
100 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
101 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700102 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700103
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700104 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
105 // suffix refers to the fact that access to the field should be locked; unrelated to the
106 // unlocked status of users.
107 @GuardedBy("mUnlockedUsersLocked")
108 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800109
Terry Wangfebbead2019-10-17 17:05:18 -0700110 public AppSearchManagerService(Context context) {
111 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700112 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700113 }
114
115 @Override
116 public void onStart() {
117 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700118 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700119 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700120 mUserManager = mContext.getSystemService(UserManager.class);
121 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700122 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700123 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700124 }
125
126 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700127 mContext.registerReceiverForAllUsers(
128 new UserActionReceiver(),
129 new IntentFilter(Intent.ACTION_USER_REMOVED),
130 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700131 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700132
133 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
134 // broadcasts
135 IntentFilter packageChangedFilter = new IntentFilter();
136 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
137 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
138 packageChangedFilter.addDataScheme("package");
139 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700140 mContext.registerReceiverForAllUsers(
141 new PackageChangedReceiver(),
142 packageChangedFilter,
143 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700144 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700145 }
146
147 private class UserActionReceiver extends BroadcastReceiver {
148 @Override
149 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700150 Objects.requireNonNull(context);
151 Objects.requireNonNull(intent);
152
Terry Wang12dc6c02021-03-31 19:26:16 -0700153 switch (intent.getAction()) {
154 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700155 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
156 if (userHandle == null) {
157 Log.e(TAG, "Extra "
158 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700159 return;
160 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700161 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700162 break;
163 default:
Terry Wange201dc02021-04-16 01:03:20 -0700164 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700165 }
166 }
167 }
168
169 /**
170 * Handles user removed action.
171 *
172 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
173 * "credential encrypted" system directory of each user. That directory will be auto-deleted
174 * when a user is removed.
175 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700176 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700177 *
178 * @see android.os.Environment#getDataSystemCeDirectory
179 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700180 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700181 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700182 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700183 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700184 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700185 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700186 }
187 }
188
189 private class PackageChangedReceiver extends BroadcastReceiver {
190 @Override
191 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700192 Objects.requireNonNull(context);
193 Objects.requireNonNull(intent);
194
Terry Wange201dc02021-04-16 01:03:20 -0700195 switch (intent.getAction()) {
196 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
197 case Intent.ACTION_PACKAGE_DATA_CLEARED:
198 String packageName = intent.getData().getSchemeSpecificPart();
199 if (packageName == null) {
200 Log.e(TAG, "Package name is missing in the intent: " + intent);
201 return;
202 }
203 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
204 if (uid == INVALID_UID) {
205 Log.e(TAG, "uid is missing in the intent: " + intent);
206 return;
207 }
208 handlePackageRemoved(packageName, uid);
209 break;
210 default:
211 Log.e(TAG, "Received unknown intent: " + intent);
212 }
213 }
214 }
215
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700216 private void handlePackageRemoved(@NonNull String packageName, int uid) {
217 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700218 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700219 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700220 // We cannot access a locked user's directry and remove package data from it.
221 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700222 return;
223 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700224 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700225 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700226 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700227 AppSearchUserInstance instance =
228 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700229 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700230 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700231 instance.getAppSearchImpl().clearPackageData(packageName);
232 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700233 }
234 } catch (Throwable t) {
235 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700236 }
Terry Wangfebbead2019-10-17 17:05:18 -0700237 }
238
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800239 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700240 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700241 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700242 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700243 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700244 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800245 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700246 EXECUTOR.execute(() -> {
247 try {
248 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700249 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700250 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700251 AppSearchUserInstance instance =
252 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700253 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
254 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700255 .getPackageManager()
256 .getInstalledPackages(/*flags=*/0);
257 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
258 for (int i = 0; i < installedPackageInfos.size(); i++) {
259 packagesToKeep.add(installedPackageInfos.get(i).packageName);
260 }
261 packagesToKeep.add(VisibilityStore.PACKAGE_NAME);
262 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700263 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700264 }
265 } catch (Throwable t) {
266 Log.e(TAG, "Unable to prune packages for " + user, t);
267 }
268 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800269 }
270
Terry Wangde9f3382021-04-28 19:45:07 -0700271 @Override
272 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700273 Objects.requireNonNull(user);
274
275 synchronized (mUnlockedUsersLocked) {
276 UserHandle userHandle = user.getUserHandle();
277 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700278 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700279 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700280 } catch (Throwable t) {
281 Log.e(TAG, "Error handling user stopping.", t);
282 }
283 }
284 }
285
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700286 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
287 if (isUserLocked(callingUser)) {
288 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700289 }
290 }
291
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700292 private boolean isUserLocked(@NonNull UserHandle callingUser) {
293 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700294 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700295 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700296 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700297 }
298 // If the local copy says the user is locked, check with UM for the actual state,
299 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700300 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700301 }
302 }
303
Terry Wangfebbead2019-10-17 17:05:18 -0700304 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800305 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800306 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800307 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700308 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700309 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800310 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700311 @NonNull Map<String, List<Bundle>> schemasVisibleToPackagesBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800312 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700313 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700314 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700315 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800316 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700317 Objects.requireNonNull(packageName);
318 Objects.requireNonNull(databaseName);
319 Objects.requireNonNull(schemaBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700320 Objects.requireNonNull(schemasNotDisplayedBySystem);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700321 Objects.requireNonNull(schemasVisibleToPackagesBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700322 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700323 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700324
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700325 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800326 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700327 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700328 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700329 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700330 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700331 int operationSuccessCount = 0;
332 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700333 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700334 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700335 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700336 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
337 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700338 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
339 for (int i = 0; i < schemaBundles.size(); i++) {
340 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800341 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700342 Map<String, List<PackageIdentifier>> schemasVisibleToPackages =
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700343 new ArrayMap<>(schemasVisibleToPackagesBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700344 for (Map.Entry<String, List<Bundle>> entry :
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700345 schemasVisibleToPackagesBundles.entrySet()) {
Terry Wange04ceab2021-03-29 19:25:12 -0700346 List<PackageIdentifier> packageIdentifiers =
347 new ArrayList<>(entry.getValue().size());
348 for (int i = 0; i < entry.getValue().size(); i++) {
349 packageIdentifiers.add(
350 new PackageIdentifier(entry.getValue().get(i)));
351 }
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700352 schemasVisibleToPackages.put(entry.getKey(), packageIdentifiers);
Terry Wange04ceab2021-03-29 19:25:12 -0700353 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700354 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
355 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700356 packageName,
357 databaseName,
358 schemas,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700359 instance.getVisibilityStore(),
Terry Wange04ceab2021-03-29 19:25:12 -0700360 schemasNotDisplayedBySystem,
Alexander Dorokhine15d0ae42021-06-18 14:28:34 -0700361 schemasVisibleToPackages,
Terry Wange04ceab2021-03-29 19:25:12 -0700362 forceOverride,
363 schemaVersion);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700364 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700365 invokeCallbackOnResult(callback,
366 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700367
368 // setSchema will sync the schemas in the request to AppSearch, any existing
369 // schemas which is not included in the request will be delete if we force
370 // override incompatible schemas. And all documents of these types will be
371 // deleted as well. We should checkForOptimize for these deletion.
372 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700373 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700374 ++operationFailureCount;
375 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700376 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700377 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700378 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700379 int estimatedBinderLatencyMillis =
380 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
381 int totalLatencyMillis =
382 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700383 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700384 .setPackageName(packageName)
385 .setDatabase(databaseName)
386 .setStatusCode(statusCode)
387 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700388 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
389 // TODO(b/173532925) check the existing binder call latency chart
390 // is good enough for us:
391 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
392 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
393 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700394 .setNumOperationsFailed(operationFailureCount)
395 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700396 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800397 }
Terry Wange04ceab2021-03-29 19:25:12 -0700398 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800399 }
400
401 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800402 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800403 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800404 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700405 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800406 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700407 Objects.requireNonNull(packageName);
408 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700409 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700410 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700411
Cassie Wangb0d60122021-03-30 12:38:46 -0700412 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700413 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700414 EXECUTOR.execute(() -> {
415 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700416 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700417 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700418 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
419 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700420 AppSearchUserInstance instance =
421 mAppSearchUserInstanceManager.getUserInstance(callingUser);
422 GetSchemaResponse response =
423 instance.getAppSearchImpl().getSchema(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700424 invokeCallbackOnResult(
425 callback,
426 AppSearchResult.newSuccessfulResult(response.getBundle()));
427 } catch (Throwable t) {
428 invokeCallbackOnError(callback, t);
429 }
430 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700431 }
432
433 @Override
434 public void getNamespaces(
435 @NonNull String packageName,
436 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700437 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700438 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700439 Objects.requireNonNull(packageName);
440 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700441 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700442 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700443
Cassie Wangb0d60122021-03-30 12:38:46 -0700444 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700445 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700446 EXECUTOR.execute(() -> {
447 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700448 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700449 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700450 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
451 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700452 AppSearchUserInstance instance =
453 mAppSearchUserInstanceManager.getUserInstance(callingUser);
454 List<String> namespaces =
455 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
456 invokeCallbackOnResult(
457 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700458 } catch (Throwable t) {
459 invokeCallbackOnError(callback, t);
460 }
461 });
Terry Wang83a24932020-12-09 21:00:18 -0800462 }
463
464 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800465 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800466 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700467 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700468 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700469 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800470 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800471 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700472 Objects.requireNonNull(packageName);
473 Objects.requireNonNull(databaseName);
474 Objects.requireNonNull(documentBundles);
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
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700478 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800479 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700480 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700481 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800482 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700483 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800484 int operationSuccessCount = 0;
485 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700486 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700487 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700488 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700489 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
490 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700491 AppSearchBatchResult.Builder<String, Void> resultBuilder =
492 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700493 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700494 for (int i = 0; i < documentBundles.size(); i++) {
495 GenericDocument document = new GenericDocument(documentBundles.get(i));
496 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700497 instance.getAppSearchImpl().putDocument(
498 packageName, databaseName, document, instance.getLogger());
499 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800500 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700501 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700502 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800503 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700504 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700505 // Since we can only include one status code in the atom,
506 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800507 statusCode = result.getResultCode();
508 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700509 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800510 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700511 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700512 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700513 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700514
515 // The existing documents with same ID will be deleted, so there may be some
516 // resources that could be released after optimize().
517 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700518 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700519 ++operationFailureCount;
520 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700521 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800522 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700523 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700524 int estimatedBinderLatencyMillis =
525 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
526 int totalLatencyMillis =
527 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700528 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700529 .setPackageName(packageName)
530 .setDatabase(databaseName)
531 .setStatusCode(statusCode)
532 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800533 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
534 // TODO(b/173532925) check the existing binder call latency chart
535 // is good enough for us:
536 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700537 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800538 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700539 .setNumOperationsFailed(operationFailureCount)
540 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800541 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800542 }
Terry Wange04ceab2021-03-29 19:25:12 -0700543 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800544 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800545
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800546 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800547 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800548 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800549 @NonNull String databaseName,
550 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700551 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800552 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700553 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700554 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800555 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700556 Objects.requireNonNull(packageName);
557 Objects.requireNonNull(databaseName);
558 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700559 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700560 Objects.requireNonNull(typePropertyPaths);
561 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700562 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700563
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700564 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800565 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700566 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700567 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700568 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700569 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700570 int operationSuccessCount = 0;
571 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700572 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700573 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700574 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700575 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
576 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700577 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
578 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700579 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700580 for (int i = 0; i < ids.size(); i++) {
581 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700582 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700583 GenericDocument document = instance.getAppSearchImpl().getDocument(
584 packageName,
585 databaseName,
586 namespace,
587 id,
588 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700589 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700590 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700591 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700592 // Since we can only include one status code in the atom,
593 // for failures, we would just save the one for the last failure
594 AppSearchResult<Bundle> result = throwableToFailedResult(t);
595 resultBuilder.setResult(id, result);
596 statusCode = result.getResultCode();
597 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700598 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800599 }
Terry Wange04ceab2021-03-29 19:25:12 -0700600 invokeCallbackOnResult(callback, resultBuilder.build());
601 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700602 ++operationFailureCount;
603 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700604 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700605 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700606 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700607 int estimatedBinderLatencyMillis =
608 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
609 int totalLatencyMillis =
610 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700611 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700612 .setPackageName(packageName)
613 .setDatabase(databaseName)
614 .setStatusCode(statusCode)
615 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700616 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
617 // TODO(b/173532925) check the existing binder call latency chart
618 // is good enough for us:
619 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
620 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
621 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700622 .setNumOperationsFailed(operationFailureCount)
623 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700624 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800625 }
Terry Wange04ceab2021-03-29 19:25:12 -0700626 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800627 }
628
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800629 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800630 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800631 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700632 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700633 @NonNull String queryExpression,
634 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700635 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700636 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700637 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700638 Objects.requireNonNull(packageName);
639 Objects.requireNonNull(databaseName);
640 Objects.requireNonNull(queryExpression);
641 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700642 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700643 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700644
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700645 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800646 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700647 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700648 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700649 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700650 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700651 int operationSuccessCount = 0;
652 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700653 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700654 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700655 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700656 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
657 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700658 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
659 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
660 packageName,
661 databaseName,
662 queryExpression,
663 new SearchSpec(searchSpecBundle),
664 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700665 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700666 invokeCallbackOnResult(
667 callback,
668 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
669 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700670 ++operationFailureCount;
671 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700672 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700673 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700674 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700675 int estimatedBinderLatencyMillis =
676 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
677 int totalLatencyMillis =
678 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700679 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700680 .setPackageName(packageName)
681 .setDatabase(databaseName)
682 .setStatusCode(statusCode)
683 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700684 .setCallType(CallStats.CALL_TYPE_SEARCH)
685 // TODO(b/173532925) check the existing binder call latency chart
686 // is good enough for us:
687 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
688 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
689 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700690 .setNumOperationsFailed(operationFailureCount)
691 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700692 }
Terry Wange04ceab2021-03-29 19:25:12 -0700693 }
694 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700695 }
696
Terry Wangf2093072020-11-30 04:47:19 -0800697 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800698 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800699 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800700 @NonNull String queryExpression,
701 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700702 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700703 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800704 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700705 Objects.requireNonNull(packageName);
706 Objects.requireNonNull(queryExpression);
707 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700708 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700709 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700710
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700711 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800712 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700713 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700714 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700715 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700716 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700717 int operationSuccessCount = 0;
718 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700719 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700720 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700721 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700722 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
723 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700724 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
725
726 boolean callerHasSystemAccess =
727 instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
728 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
729 queryExpression,
730 new SearchSpec(searchSpecBundle),
731 packageName,
732 instance.getVisibilityStore(),
733 callingUid,
734 callerHasSystemAccess,
735 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700736 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700737 invokeCallbackOnResult(
738 callback,
739 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700740 } catch (Throwable t) {
741 ++operationFailureCount;
742 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700743 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700744 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700745 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700746 int estimatedBinderLatencyMillis =
747 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
748 int totalLatencyMillis =
749 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700750 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700751 .setPackageName(packageName)
752 .setStatusCode(statusCode)
753 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700754 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
755 // TODO(b/173532925) check the existing binder call latency chart
756 // is good enough for us:
757 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
758 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
759 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700760 .setNumOperationsFailed(operationFailureCount)
761 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700762 }
Terry Wange04ceab2021-03-29 19:25:12 -0700763 }
764 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800765 }
766
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700767 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800768 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700769 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800770 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700771 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700772 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700773 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700774 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700775 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700776
Terry Wangf2093072020-11-30 04:47:19 -0800777 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700778 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700779 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
780 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700781 EXECUTOR.execute(() -> {
782 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700783 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700784 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700785 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
786 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700787 AppSearchUserInstance instance =
788 mAppSearchUserInstanceManager.getUserInstance(callingUser);
789 SearchResultPage searchResultPage =
790 instance.getAppSearchImpl().getNextPage(nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700791 invokeCallbackOnResult(
792 callback,
793 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
794 } catch (Throwable t) {
795 invokeCallbackOnError(callback, t);
796 }
797 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700798 }
799
800 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700801 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
802 @NonNull UserHandle userHandle) {
803 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700804 Objects.requireNonNull(userHandle);
805
Terry Wangf2093072020-11-30 04:47:19 -0800806 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700807 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700808 EXECUTOR.execute(() -> {
809 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700810 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700811 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700812 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
813 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700814 AppSearchUserInstance instance =
815 mAppSearchUserInstanceManager.getUserInstance(callingUser);
816 instance.getAppSearchImpl().invalidateNextPageToken(nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700817 } catch (Throwable t) {
818 Log.e(TAG, "Unable to invalidate the query page token", t);
819 }
820 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800821 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800822
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700823 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800824 public void writeQueryResultsToFile(
825 @NonNull String packageName,
826 @NonNull String databaseName,
827 @NonNull ParcelFileDescriptor fileDescriptor,
828 @NonNull String queryExpression,
829 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700830 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800831 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700832 Objects.requireNonNull(packageName);
833 Objects.requireNonNull(databaseName);
834 Objects.requireNonNull(fileDescriptor);
835 Objects.requireNonNull(queryExpression);
836 Objects.requireNonNull(searchSpecBundle);
837 Objects.requireNonNull(userHandle);
838 Objects.requireNonNull(callback);
839
Terry Wang623e3b02021-02-02 20:27:33 -0800840 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700841 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700842 EXECUTOR.execute(() -> {
843 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700844 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
845 verifyUserUnlocked(callingUser);
846 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
847 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700848 AppSearchUserInstance instance =
849 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700850 // we don't need to append the file. The file is always brand new.
851 try (DataOutputStream outputStream = new DataOutputStream(
852 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700853 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700854 packageName,
855 databaseName,
856 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700857 new SearchSpec(searchSpecBundle),
858 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700859 while (!searchResultPage.getResults().isEmpty()) {
860 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
861 AppSearchMigrationHelper.writeBundleToOutputStream(
862 outputStream, searchResultPage.getResults().get(i)
863 .getGenericDocument().getBundle());
864 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700865 searchResultPage = instance.getAppSearchImpl().getNextPage(
Terry Wange04ceab2021-03-29 19:25:12 -0700866 searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800867 }
Terry Wang623e3b02021-02-02 20:27:33 -0800868 }
Terry Wange04ceab2021-03-29 19:25:12 -0700869 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
870 } catch (Throwable t) {
871 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800872 }
Terry Wange04ceab2021-03-29 19:25:12 -0700873 });
Terry Wang623e3b02021-02-02 20:27:33 -0800874 }
875
876 @Override
877 public void putDocumentsFromFile(
878 @NonNull String packageName,
879 @NonNull String databaseName,
880 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700881 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800882 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700883 Objects.requireNonNull(packageName);
884 Objects.requireNonNull(databaseName);
885 Objects.requireNonNull(fileDescriptor);
886 Objects.requireNonNull(userHandle);
887 Objects.requireNonNull(callback);
888
Terry Wang623e3b02021-02-02 20:27:33 -0800889 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700890 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700891 EXECUTOR.execute(() -> {
892 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700893 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
894 verifyUserUnlocked(callingUser);
895 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
896 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700897 AppSearchUserInstance instance =
898 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800899
Terry Wange04ceab2021-03-29 19:25:12 -0700900 GenericDocument document;
901 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
902 try (DataInputStream inputStream = new DataInputStream(
903 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
904 while (true) {
905 try {
906 document = AppSearchMigrationHelper
907 .readDocumentFromInputStream(inputStream);
908 } catch (EOFException e) {
909 // nothing wrong, we just finish the reading.
910 break;
911 }
912 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700913 instance.getAppSearchImpl().putDocument(
914 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700915 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700916 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
917 document.getNamespace(),
918 document.getId(),
919 document.getSchemaType(),
920 AppSearchResult.throwableToFailedResult(t))
921 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700922 }
Terry Wang623e3b02021-02-02 20:27:33 -0800923 }
924 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700925 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700926 invokeCallbackOnResult(callback,
927 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
928 } catch (Throwable t) {
929 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800930 }
Terry Wange04ceab2021-03-29 19:25:12 -0700931 });
Terry Wang623e3b02021-02-02 20:27:33 -0800932 }
933
934 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800935 public void reportUsage(
936 @NonNull String packageName,
937 @NonNull String databaseName,
938 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700939 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800940 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700941 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700942 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800943 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700944 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800945 Objects.requireNonNull(databaseName);
946 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700947 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700948 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800949 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700950
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800951 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700952 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700953 EXECUTOR.execute(() -> {
954 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700955 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700956 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700957 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
958 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700959 AppSearchUserInstance instance =
960 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700961
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700962 if (systemUsage
963 && !instance.getVisibilityStore()
964 .doesCallerHaveSystemAccess(packageName)) {
965 throw new AppSearchException(
966 AppSearchResult.RESULT_SECURITY_ERROR,
967 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -0700968 }
969
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700970 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700971 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -0700972 usageTimeMillis, systemUsage);
973 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700974 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -0700975 } catch (Throwable t) {
976 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700977 }
Terry Wange04ceab2021-03-29 19:25:12 -0700978 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800979 }
980
981 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700982 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -0800983 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800984 @NonNull String databaseName,
985 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700986 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700987 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700988 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800989 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700990 Objects.requireNonNull(packageName);
991 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700992 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700993 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700994 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700995 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700996
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700997 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800998 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700999 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001000 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001001 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001002 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001003 int operationSuccessCount = 0;
1004 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001005 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001006 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001007 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001008 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1009 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -07001010 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1011 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001012 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001013 for (int i = 0; i < ids.size(); i++) {
1014 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001015 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001016 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001017 packageName,
1018 databaseName,
1019 namespace,
1020 id,
1021 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001022 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001023 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001024 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001025 AppSearchResult<Void> result = throwableToFailedResult(t);
1026 resultBuilder.setResult(id, result);
1027 // Since we can only include one status code in the atom,
1028 // for failures, we would just save the one for the last failure
1029 statusCode = result.getResultCode();
1030 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001031 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001032 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001033 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001034 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001035 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001036
1037 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001038 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001039 ++operationFailureCount;
1040 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001041 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001042 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001043 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001044 int estimatedBinderLatencyMillis =
1045 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1046 int totalLatencyMillis =
1047 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001048 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001049 .setPackageName(packageName)
1050 .setDatabase(databaseName)
1051 .setStatusCode(statusCode)
1052 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001053 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1054 // TODO(b/173532925) check the existing binder call latency chart
1055 // is good enough for us:
1056 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1057 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1058 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001059 .setNumOperationsFailed(operationFailureCount)
1060 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001061 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001062 }
Terry Wange04ceab2021-03-29 19:25:12 -07001063 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001064 }
1065
1066 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001067 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001068 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001069 @NonNull String databaseName,
1070 @NonNull String queryExpression,
1071 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001072 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001073 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001074 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001075 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001076 Objects.requireNonNull(packageName);
1077 Objects.requireNonNull(databaseName);
1078 Objects.requireNonNull(queryExpression);
1079 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001080 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001081 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001082
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001083 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001084 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001085 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001086 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001087 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001088 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001089 int operationSuccessCount = 0;
1090 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001091 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001092 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001093 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001094 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1095 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001096 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
1097 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001098 packageName,
1099 databaseName,
1100 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001101 new SearchSpec(searchSpecBundle),
1102 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001103 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001104 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001105 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001106 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001107
1108 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001109 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001110 ++operationFailureCount;
1111 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001112 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001113 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001114 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001115 int estimatedBinderLatencyMillis =
1116 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1117 int totalLatencyMillis =
1118 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001119 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001120 .setPackageName(packageName)
1121 .setDatabase(databaseName)
1122 .setStatusCode(statusCode)
1123 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001124 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1125 // TODO(b/173532925) check the existing binder call latency chart
1126 // is good enough for us:
1127 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1128 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1129 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001130 .setNumOperationsFailed(operationFailureCount)
1131 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001132 }
Terry Wange04ceab2021-03-29 19:25:12 -07001133 }
1134 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001135 }
1136
Terry Wangdbd1dca2020-11-03 17:03:56 -08001137 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001138 public void getStorageInfo(
1139 @NonNull String packageName,
1140 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001141 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001142 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001143 Objects.requireNonNull(packageName);
1144 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001145 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001146 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001147
Cassie Wang8f0df492021-03-24 09:23:18 -07001148 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001149 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001150 EXECUTOR.execute(() -> {
1151 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001152 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001153 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001154 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1155 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001156 AppSearchUserInstance instance =
1157 mAppSearchUserInstanceManager.getUserInstance(callingUser);
1158 StorageInfo storageInfo = instance.getAppSearchImpl()
1159 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001160 Bundle storageInfoBundle = storageInfo.getBundle();
1161 invokeCallbackOnResult(
1162 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1163 } catch (Throwable t) {
1164 invokeCallbackOnError(callback, t);
1165 }
1166 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001167 }
1168
1169 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001170 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001171 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001172 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001173 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001174 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001175 Objects.requireNonNull(userHandle);
1176
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001177 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wangb0d60122021-03-30 12:38:46 -07001178 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001179 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001180 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001181 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001182 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001183 int operationSuccessCount = 0;
1184 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001185 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001186 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001187 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001188 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1189 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001190 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
1191 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001192 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001193 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001194 ++operationFailureCount;
1195 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001196 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001197 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001198 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001199 int estimatedBinderLatencyMillis =
1200 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1201 int totalLatencyMillis =
1202 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001203 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001204 .setStatusCode(statusCode)
1205 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001206 .setCallType(CallStats.CALL_TYPE_FLUSH)
1207 // TODO(b/173532925) check the existing binder call latency chart
1208 // is good enough for us:
1209 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1210 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1211 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001212 .setNumOperationsFailed(operationFailureCount)
1213 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001214 }
Terry Wange04ceab2021-03-29 19:25:12 -07001215 }
1216 });
Terry Wang2da17852020-12-16 19:59:08 -08001217 }
1218
1219 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001220 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001221 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001222 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001223 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1224 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001225 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001226 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001227 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001228
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001229 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001230 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001231 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Cassie Wang84e33a02021-06-18 14:13:31 -07001232
Terry Wange04ceab2021-03-29 19:25:12 -07001233 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001234 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001235 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001236 int operationSuccessCount = 0;
1237 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001238 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001239 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001240 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001241 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1242 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001243 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001244 userContext, callingUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001245 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001246 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1247 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001248 ++operationFailureCount;
1249 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001250 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001251 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001252 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001253 int estimatedBinderLatencyMillis =
1254 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1255 int totalLatencyMillis =
1256 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001257 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001258 .setStatusCode(statusCode)
1259 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001260 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1261 // TODO(b/173532925) check the existing binder call latency chart
1262 // is good enough for us:
1263 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1264 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1265 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001266 .setNumOperationsFailed(operationFailureCount)
1267 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001268 }
Terry Wange04ceab2021-03-29 19:25:12 -07001269 }
1270 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001271 }
1272
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001273 private void verifyCallingPackage(
Cassie Wang84e33a02021-06-18 14:13:31 -07001274 @NonNull Context userContext,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001275 @NonNull UserHandle actualCallingUser,
1276 int actualCallingUid,
1277 @NonNull String claimedCallingPackage) {
1278 Objects.requireNonNull(actualCallingUser);
1279 Objects.requireNonNull(claimedCallingPackage);
1280
Cassie Wang84e33a02021-06-18 14:13:31 -07001281 int claimedCallingUid = PackageUtil.getPackageUid(
1282 userContext, claimedCallingPackage);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001283 if (claimedCallingUid == INVALID_UID) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001284 throw new SecurityException(
1285 "Specified calling package [" + claimedCallingPackage + "] not found");
1286 }
1287 if (claimedCallingUid != actualCallingUid) {
Cassie Wang0c62d992021-01-15 14:39:30 -08001288 throw new SecurityException(
1289 "Specified calling package ["
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001290 + claimedCallingPackage
Cassie Wang0c62d992021-01-15 14:39:30 -08001291 + "] does not match the calling uid "
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001292 + actualCallingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001293 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001294 }
1295
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001296 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001297 private void invokeCallbackOnResult(
1298 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001299 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001300 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001301 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001302 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001303 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001304 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001305
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001306 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001307 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001308 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001309 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001310 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001311 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001312 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001313 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001314 }
1315
1316 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001317 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001318 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001319 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001320 */
1321 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001322 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001323 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001324 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001325 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001326 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001327 }
1328 }
1329
1330 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001331 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001332 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001333 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001334 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001335 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001336 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001337 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001338 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001339 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001340 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001341 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001342 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001343 }
Terry Wangfebbead2019-10-17 17:05:18 -07001344 }
Terry Wangf2093072020-11-30 04:47:19 -08001345
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001346 /**
1347 * Helper for dealing with incoming user arguments to system service calls.
1348 *
1349 * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
1350 *
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001351 * @param requestedUser The user which the caller is requesting to execute as.
1352 * @param callingUid The actual uid of the caller as determined by Binder.
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001353 * @return the user handle that the call should run as. Will always be a concrete user.
1354 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001355 @NonNull
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001356 private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
Terry Wangf2093072020-11-30 04:47:19 -08001357 int callingPid = Binder.getCallingPid();
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001358 UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
1359 if (callingUser.equals(requestedUser)) {
1360 return requestedUser;
1361 }
1362 // Duplicates UserController#ensureNotSpecialUser
1363 if (requestedUser.getIdentifier() < 0) {
1364 throw new IllegalArgumentException(
1365 "Call does not support special user " + requestedUser);
1366 }
1367 boolean canInteractAcrossUsers = mContext.checkPermission(
1368 Manifest.permission.INTERACT_ACROSS_USERS,
Cassie Wang0c62d992021-01-15 14:39:30 -08001369 callingPid,
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001370 callingUid) == PackageManager.PERMISSION_GRANTED;
1371 if (!canInteractAcrossUsers) {
1372 canInteractAcrossUsers = mContext.checkPermission(
1373 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1374 callingPid,
1375 callingUid) == PackageManager.PERMISSION_GRANTED;
1376 }
1377 if (canInteractAcrossUsers) {
1378 return requestedUser;
1379 }
1380 throw new SecurityException(
1381 "Permission denied while calling from uid " + callingUid
1382 + " with " + requestedUser + "; Need to run as either the calling user ("
1383 + callingUser + "), or with one of the following permissions: "
1384 + Manifest.permission.INTERACT_ACROSS_USERS + " or "
1385 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001386 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001387
Cassie Wang84e33a02021-06-18 14:13:31 -07001388 /**
1389 * Helper for ensuring instant apps can't make calls to AppSearch.
1390 *
1391 * @param userContext Context of the user making the call.
1392 * @param packageName Package name of the caller.
1393 * @throws SecurityException if the caller is an instant app.
1394 */
1395 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1396 PackageManager callingPackageManager = userContext.getPackageManager();
1397 if (callingPackageManager.isInstantApp(packageName)) {
1398 throw new SecurityException("Caller not allowed to create AppSearch session"
1399 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1400 }
1401 }
1402
Yang Yu0fcd51a2021-04-23 11:25:44 -07001403 // TODO(b/179160886): Cache the previous storage stats.
1404 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1405 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001406 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001407 @NonNull PackageStats stats,
1408 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001409 @NonNull UserHandle userHandle,
1410 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001411 Objects.requireNonNull(stats);
1412 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001413 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001414
Yang Yu0fcd51a2021-04-23 11:25:44 -07001415 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001416 verifyUserUnlocked(userHandle);
Cassie Wang84e33a02021-06-18 14:13:31 -07001417 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001418 AppSearchUserInstance instance =
1419 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001420 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001421 stats.dataSize += instance.getAppSearchImpl()
1422 .getStorageInfoForPackage(packageName).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001423 } catch (Throwable t) {
1424 Log.e(
1425 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001426 "Unable to augment storage stats for "
1427 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001428 + " packageName "
1429 + packageName,
1430 t);
1431 }
1432 }
1433
1434 @Override
1435 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001436 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001437 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001438
1439 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001440 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001441 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001442 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1443 if (packagesForUid == null) {
1444 return;
1445 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001446 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001447 AppSearchUserInstance instance =
1448 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001449 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001450 for (int i = 0; i < packagesForUid.length; i++) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001451 stats.dataSize += instance.getAppSearchImpl()
1452 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001453 }
1454 } catch (Throwable t) {
1455 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1456 }
1457 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001458
1459 @Override
1460 public void augmentStatsForUser(
1461 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1462 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1463 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1464 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1465 Objects.requireNonNull(stats);
1466 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001467
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001468 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001469 verifyUserUnlocked(userHandle);
1470 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1471 /*flags=*/0, userHandle.getIdentifier());
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001472 if (packagesForUser == null) {
1473 return;
1474 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001475 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001476 AppSearchUserInstance instance =
1477 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001478 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001479 for (int i = 0; i < packagesForUser.size(); i++) {
1480 String packageName = packagesForUser.get(i).packageName;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001481 stats.dataSize += instance.getAppSearchImpl()
1482 .getStorageInfoForPackage(packageName).getSizeBytes();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001483 }
1484 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001485 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001486 }
1487 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001488 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001489
1490 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1491 EXECUTOR.execute(() -> {
1492 try {
1493 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize);
1494 } catch (AppSearchException e) {
1495 Log.w(TAG, "Error occurred when check for optimize", e);
1496 }
1497 });
1498 }
1499
1500 private void checkForOptimize(AppSearchUserInstance instance) {
1501 EXECUTOR.execute(() -> {
1502 try {
1503 instance.getAppSearchImpl().checkForOptimize();
1504 } catch (AppSearchException e) {
1505 Log.w(TAG, "Error occurred when check for optimize", e);
1506 }
1507 });
1508 }
Terry Wangfebbead2019-10-17 17:05:18 -07001509}