blob: 85a9cce53c94d3e104368789b9c409f3bca5ddcd [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()));
367 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700368 ++operationFailureCount;
369 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700370 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700371 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700372 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700373 int estimatedBinderLatencyMillis =
374 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
375 int totalLatencyMillis =
376 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700377 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700378 .setPackageName(packageName)
379 .setDatabase(databaseName)
380 .setStatusCode(statusCode)
381 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700382 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
383 // TODO(b/173532925) check the existing binder call latency chart
384 // is good enough for us:
385 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
386 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
387 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700388 .setNumOperationsFailed(operationFailureCount)
389 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700390 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800391 }
Terry Wange04ceab2021-03-29 19:25:12 -0700392 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800393 }
394
395 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800396 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800397 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800398 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700399 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800400 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700401 Objects.requireNonNull(packageName);
402 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700403 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700404 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700405
Cassie Wangb0d60122021-03-30 12:38:46 -0700406 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700407 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700408 EXECUTOR.execute(() -> {
409 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700410 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700411 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700412 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
413 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700414 AppSearchUserInstance instance =
415 mAppSearchUserInstanceManager.getUserInstance(callingUser);
416 GetSchemaResponse response =
417 instance.getAppSearchImpl().getSchema(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700418 invokeCallbackOnResult(
419 callback,
420 AppSearchResult.newSuccessfulResult(response.getBundle()));
421 } catch (Throwable t) {
422 invokeCallbackOnError(callback, t);
423 }
424 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700425 }
426
427 @Override
428 public void getNamespaces(
429 @NonNull String packageName,
430 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700431 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700432 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700433 Objects.requireNonNull(packageName);
434 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700435 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700436 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700437
Cassie Wangb0d60122021-03-30 12:38:46 -0700438 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700439 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700440 EXECUTOR.execute(() -> {
441 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700442 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700443 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700444 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
445 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700446 AppSearchUserInstance instance =
447 mAppSearchUserInstanceManager.getUserInstance(callingUser);
448 List<String> namespaces =
449 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
450 invokeCallbackOnResult(
451 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700452 } catch (Throwable t) {
453 invokeCallbackOnError(callback, t);
454 }
455 });
Terry Wang83a24932020-12-09 21:00:18 -0800456 }
457
458 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800459 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800460 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700461 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700462 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700463 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800464 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800465 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700466 Objects.requireNonNull(packageName);
467 Objects.requireNonNull(databaseName);
468 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700469 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700470 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700471
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700472 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800473 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700474 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700475 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800476 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700477 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800478 int operationSuccessCount = 0;
479 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700480 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700481 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700482 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700483 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
484 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700485 AppSearchBatchResult.Builder<String, Void> resultBuilder =
486 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700487 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700488 for (int i = 0; i < documentBundles.size(); i++) {
489 GenericDocument document = new GenericDocument(documentBundles.get(i));
490 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700491 instance.getAppSearchImpl().putDocument(
492 packageName, databaseName, document, instance.getLogger());
493 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800494 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700495 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700496 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800497 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700498 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700499 // Since we can only include one status code in the atom,
500 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800501 statusCode = result.getResultCode();
502 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700503 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800504 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700505 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700506 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700507 invokeCallbackOnResult(callback, resultBuilder.build());
508 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700509 ++operationFailureCount;
510 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700511 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800512 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700513 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700514 int estimatedBinderLatencyMillis =
515 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
516 int totalLatencyMillis =
517 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700518 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700519 .setPackageName(packageName)
520 .setDatabase(databaseName)
521 .setStatusCode(statusCode)
522 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800523 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
524 // TODO(b/173532925) check the existing binder call latency chart
525 // is good enough for us:
526 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700527 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800528 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700529 .setNumOperationsFailed(operationFailureCount)
530 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800531 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800532 }
Terry Wange04ceab2021-03-29 19:25:12 -0700533 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800534 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800535
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800536 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800537 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800538 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800539 @NonNull String databaseName,
540 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700541 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800542 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700543 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700544 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800545 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700546 Objects.requireNonNull(packageName);
547 Objects.requireNonNull(databaseName);
548 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700549 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700550 Objects.requireNonNull(typePropertyPaths);
551 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700552 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700553
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700554 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800555 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700556 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700557 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700558 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700559 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700560 int operationSuccessCount = 0;
561 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700562 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700563 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700564 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700565 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
566 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700567 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
568 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700569 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700570 for (int i = 0; i < ids.size(); i++) {
571 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700572 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700573 GenericDocument document = instance.getAppSearchImpl().getDocument(
574 packageName,
575 databaseName,
576 namespace,
577 id,
578 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700579 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700580 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700581 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700582 // Since we can only include one status code in the atom,
583 // for failures, we would just save the one for the last failure
584 AppSearchResult<Bundle> result = throwableToFailedResult(t);
585 resultBuilder.setResult(id, result);
586 statusCode = result.getResultCode();
587 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700588 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800589 }
Terry Wange04ceab2021-03-29 19:25:12 -0700590 invokeCallbackOnResult(callback, resultBuilder.build());
591 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700592 ++operationFailureCount;
593 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700594 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700595 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700596 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700597 int estimatedBinderLatencyMillis =
598 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
599 int totalLatencyMillis =
600 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700601 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700602 .setPackageName(packageName)
603 .setDatabase(databaseName)
604 .setStatusCode(statusCode)
605 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700606 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
607 // TODO(b/173532925) check the existing binder call latency chart
608 // is good enough for us:
609 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
610 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
611 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700612 .setNumOperationsFailed(operationFailureCount)
613 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700614 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800615 }
Terry Wange04ceab2021-03-29 19:25:12 -0700616 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800617 }
618
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800619 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800620 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800621 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700622 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700623 @NonNull String queryExpression,
624 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700625 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700626 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700627 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700628 Objects.requireNonNull(packageName);
629 Objects.requireNonNull(databaseName);
630 Objects.requireNonNull(queryExpression);
631 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700632 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700633 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700634
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700635 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800636 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700637 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700638 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700639 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700640 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700641 int operationSuccessCount = 0;
642 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700643 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700644 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700645 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700646 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
647 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700648 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
649 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
650 packageName,
651 databaseName,
652 queryExpression,
653 new SearchSpec(searchSpecBundle),
654 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700655 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700656 invokeCallbackOnResult(
657 callback,
658 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
659 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700660 ++operationFailureCount;
661 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700662 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700663 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700664 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700665 int estimatedBinderLatencyMillis =
666 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
667 int totalLatencyMillis =
668 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700669 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700670 .setPackageName(packageName)
671 .setDatabase(databaseName)
672 .setStatusCode(statusCode)
673 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700674 .setCallType(CallStats.CALL_TYPE_SEARCH)
675 // TODO(b/173532925) check the existing binder call latency chart
676 // is good enough for us:
677 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
678 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
679 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700680 .setNumOperationsFailed(operationFailureCount)
681 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700682 }
Terry Wange04ceab2021-03-29 19:25:12 -0700683 }
684 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700685 }
686
Terry Wangf2093072020-11-30 04:47:19 -0800687 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800688 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800689 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800690 @NonNull String queryExpression,
691 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700692 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700693 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800694 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700695 Objects.requireNonNull(packageName);
696 Objects.requireNonNull(queryExpression);
697 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700698 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700699 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700700
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700701 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800702 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700703 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700704 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700705 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700706 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700707 int operationSuccessCount = 0;
708 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700709 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700710 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700711 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700712 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
713 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700714 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
715
716 boolean callerHasSystemAccess =
717 instance.getVisibilityStore().doesCallerHaveSystemAccess(packageName);
718 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
719 queryExpression,
720 new SearchSpec(searchSpecBundle),
721 packageName,
722 instance.getVisibilityStore(),
723 callingUid,
724 callerHasSystemAccess,
725 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700726 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700727 invokeCallbackOnResult(
728 callback,
729 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700730 } catch (Throwable t) {
731 ++operationFailureCount;
732 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700733 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700734 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700735 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700736 int estimatedBinderLatencyMillis =
737 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
738 int totalLatencyMillis =
739 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700740 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700741 .setPackageName(packageName)
742 .setStatusCode(statusCode)
743 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700744 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
745 // TODO(b/173532925) check the existing binder call latency chart
746 // is good enough for us:
747 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
748 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
749 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700750 .setNumOperationsFailed(operationFailureCount)
751 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700752 }
Terry Wange04ceab2021-03-29 19:25:12 -0700753 }
754 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800755 }
756
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700757 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800758 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700759 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800760 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700761 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700762 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700763 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700764 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700765 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700766
Terry Wangf2093072020-11-30 04:47:19 -0800767 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700768 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700769 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
770 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700771 EXECUTOR.execute(() -> {
772 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700773 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700774 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700775 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
776 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700777 AppSearchUserInstance instance =
778 mAppSearchUserInstanceManager.getUserInstance(callingUser);
779 SearchResultPage searchResultPage =
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700780 instance.getAppSearchImpl().getNextPage(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700781 invokeCallbackOnResult(
782 callback,
783 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
784 } catch (Throwable t) {
785 invokeCallbackOnError(callback, t);
786 }
787 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700788 }
789
790 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700791 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
792 @NonNull UserHandle userHandle) {
793 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700794 Objects.requireNonNull(userHandle);
795
Terry Wangf2093072020-11-30 04:47:19 -0800796 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700797 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700798 EXECUTOR.execute(() -> {
799 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700800 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700801 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700802 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
803 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700804 AppSearchUserInstance instance =
805 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700806 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700807 } catch (Throwable t) {
808 Log.e(TAG, "Unable to invalidate the query page token", t);
809 }
810 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800811 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800812
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700813 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800814 public void writeQueryResultsToFile(
815 @NonNull String packageName,
816 @NonNull String databaseName,
817 @NonNull ParcelFileDescriptor fileDescriptor,
818 @NonNull String queryExpression,
819 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700820 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800821 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700822 Objects.requireNonNull(packageName);
823 Objects.requireNonNull(databaseName);
824 Objects.requireNonNull(fileDescriptor);
825 Objects.requireNonNull(queryExpression);
826 Objects.requireNonNull(searchSpecBundle);
827 Objects.requireNonNull(userHandle);
828 Objects.requireNonNull(callback);
829
Terry Wang623e3b02021-02-02 20:27:33 -0800830 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700831 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700832 EXECUTOR.execute(() -> {
833 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700834 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
835 verifyUserUnlocked(callingUser);
836 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
837 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700838 AppSearchUserInstance instance =
839 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700840 // we don't need to append the file. The file is always brand new.
841 try (DataOutputStream outputStream = new DataOutputStream(
842 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700843 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700844 packageName,
845 databaseName,
846 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700847 new SearchSpec(searchSpecBundle),
848 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700849 while (!searchResultPage.getResults().isEmpty()) {
850 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
851 AppSearchMigrationHelper.writeBundleToOutputStream(
852 outputStream, searchResultPage.getResults().get(i)
853 .getGenericDocument().getBundle());
854 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700855 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700856 packageName, searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800857 }
Terry Wang623e3b02021-02-02 20:27:33 -0800858 }
Terry Wange04ceab2021-03-29 19:25:12 -0700859 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
860 } catch (Throwable t) {
861 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800862 }
Terry Wange04ceab2021-03-29 19:25:12 -0700863 });
Terry Wang623e3b02021-02-02 20:27:33 -0800864 }
865
866 @Override
867 public void putDocumentsFromFile(
868 @NonNull String packageName,
869 @NonNull String databaseName,
870 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700871 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800872 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700873 Objects.requireNonNull(packageName);
874 Objects.requireNonNull(databaseName);
875 Objects.requireNonNull(fileDescriptor);
876 Objects.requireNonNull(userHandle);
877 Objects.requireNonNull(callback);
878
Terry Wang623e3b02021-02-02 20:27:33 -0800879 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700880 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700881 EXECUTOR.execute(() -> {
882 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700883 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
884 verifyUserUnlocked(callingUser);
885 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
886 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700887 AppSearchUserInstance instance =
888 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800889
Terry Wange04ceab2021-03-29 19:25:12 -0700890 GenericDocument document;
891 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
892 try (DataInputStream inputStream = new DataInputStream(
893 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
894 while (true) {
895 try {
896 document = AppSearchMigrationHelper
897 .readDocumentFromInputStream(inputStream);
898 } catch (EOFException e) {
899 // nothing wrong, we just finish the reading.
900 break;
901 }
902 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700903 instance.getAppSearchImpl().putDocument(
904 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700905 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700906 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
907 document.getNamespace(),
908 document.getId(),
909 document.getSchemaType(),
910 AppSearchResult.throwableToFailedResult(t))
911 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700912 }
Terry Wang623e3b02021-02-02 20:27:33 -0800913 }
914 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700915 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700916 invokeCallbackOnResult(callback,
917 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
918 } catch (Throwable t) {
919 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800920 }
Terry Wange04ceab2021-03-29 19:25:12 -0700921 });
Terry Wang623e3b02021-02-02 20:27:33 -0800922 }
923
924 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800925 public void reportUsage(
926 @NonNull String packageName,
927 @NonNull String databaseName,
928 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700929 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800930 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700931 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700932 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800933 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700934 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800935 Objects.requireNonNull(databaseName);
936 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700937 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700938 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800939 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700940
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800941 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700942 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700943 EXECUTOR.execute(() -> {
944 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700945 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700946 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700947 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
948 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700949 AppSearchUserInstance instance =
950 mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700951
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700952 if (systemUsage
953 && !instance.getVisibilityStore()
954 .doesCallerHaveSystemAccess(packageName)) {
955 throw new AppSearchException(
956 AppSearchResult.RESULT_SECURITY_ERROR,
957 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -0700958 }
959
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700960 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700961 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -0700962 usageTimeMillis, systemUsage);
963 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700964 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -0700965 } catch (Throwable t) {
966 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700967 }
Terry Wange04ceab2021-03-29 19:25:12 -0700968 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800969 }
970
971 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700972 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -0800973 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800974 @NonNull String databaseName,
975 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700976 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700977 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700978 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800979 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700980 Objects.requireNonNull(packageName);
981 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700982 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700983 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700984 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700985 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700986
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700987 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800988 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700989 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700990 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700991 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700992 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700993 int operationSuccessCount = 0;
994 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700995 try {
Cassie Wang84e33a02021-06-18 14:13:31 -0700996 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700997 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -0700998 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
999 verifyNotInstantApp(userContext, packageName);
Terry Wange04ceab2021-03-29 19:25:12 -07001000 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1001 new AppSearchBatchResult.Builder<>();
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001002 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001003 for (int i = 0; i < ids.size(); i++) {
1004 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001005 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001006 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001007 packageName,
1008 databaseName,
1009 namespace,
1010 id,
1011 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001012 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001013 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001014 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001015 AppSearchResult<Void> result = throwableToFailedResult(t);
1016 resultBuilder.setResult(id, result);
1017 // Since we can only include one status code in the atom,
1018 // for failures, we would just save the one for the last failure
1019 statusCode = result.getResultCode();
1020 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001021 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001022 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001023 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001024 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001025 invokeCallbackOnResult(callback, resultBuilder.build());
1026 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001027 ++operationFailureCount;
1028 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001029 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001030 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001031 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001032 int estimatedBinderLatencyMillis =
1033 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1034 int totalLatencyMillis =
1035 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001036 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001037 .setPackageName(packageName)
1038 .setDatabase(databaseName)
1039 .setStatusCode(statusCode)
1040 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001041 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1042 // TODO(b/173532925) check the existing binder call latency chart
1043 // is good enough for us:
1044 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1045 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1046 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001047 .setNumOperationsFailed(operationFailureCount)
1048 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001049 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001050 }
Terry Wange04ceab2021-03-29 19:25:12 -07001051 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001052 }
1053
1054 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001055 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001056 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001057 @NonNull String databaseName,
1058 @NonNull String queryExpression,
1059 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001060 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001061 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001062 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001063 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001064 Objects.requireNonNull(packageName);
1065 Objects.requireNonNull(databaseName);
1066 Objects.requireNonNull(queryExpression);
1067 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001068 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001069 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001070
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001071 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001072 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001073 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001074 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001075 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001076 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001077 int operationSuccessCount = 0;
1078 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001079 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001080 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001081 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001082 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1083 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001084 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
1085 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001086 packageName,
1087 databaseName,
1088 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001089 new SearchSpec(searchSpecBundle),
1090 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001091 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001092 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001093 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001094 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1095 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001096 ++operationFailureCount;
1097 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001098 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001099 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001100 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001101 int estimatedBinderLatencyMillis =
1102 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1103 int totalLatencyMillis =
1104 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001105 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001106 .setPackageName(packageName)
1107 .setDatabase(databaseName)
1108 .setStatusCode(statusCode)
1109 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001110 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1111 // TODO(b/173532925) check the existing binder call latency chart
1112 // is good enough for us:
1113 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1114 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1115 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001116 .setNumOperationsFailed(operationFailureCount)
1117 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001118 }
Terry Wange04ceab2021-03-29 19:25:12 -07001119 }
1120 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001121 }
1122
Terry Wangdbd1dca2020-11-03 17:03:56 -08001123 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001124 public void getStorageInfo(
1125 @NonNull String packageName,
1126 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001127 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001128 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001129 Objects.requireNonNull(packageName);
1130 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001131 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001132 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001133
Cassie Wang8f0df492021-03-24 09:23:18 -07001134 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001135 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001136 EXECUTOR.execute(() -> {
1137 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001138 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001139 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001140 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1141 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001142 AppSearchUserInstance instance =
1143 mAppSearchUserInstanceManager.getUserInstance(callingUser);
1144 StorageInfo storageInfo = instance.getAppSearchImpl()
1145 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001146 Bundle storageInfoBundle = storageInfo.getBundle();
1147 invokeCallbackOnResult(
1148 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1149 } catch (Throwable t) {
1150 invokeCallbackOnError(callback, t);
1151 }
1152 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001153 }
1154
1155 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001156 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001157 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001158 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001159 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001160 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001161 Objects.requireNonNull(userHandle);
1162
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001163 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wangb0d60122021-03-30 12:38:46 -07001164 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001165 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001166 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001167 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001168 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001169 int operationSuccessCount = 0;
1170 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001171 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001172 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001173 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001174 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1175 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001176 instance = mAppSearchUserInstanceManager.getUserInstance(callingUser);
1177 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001178 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001179 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001180 ++operationFailureCount;
1181 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001182 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001183 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001184 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001185 int estimatedBinderLatencyMillis =
1186 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1187 int totalLatencyMillis =
1188 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001189 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001190 .setStatusCode(statusCode)
1191 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001192 .setCallType(CallStats.CALL_TYPE_FLUSH)
1193 // TODO(b/173532925) check the existing binder call latency chart
1194 // is good enough for us:
1195 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1196 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1197 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001198 .setNumOperationsFailed(operationFailureCount)
1199 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001200 }
Terry Wange04ceab2021-03-29 19:25:12 -07001201 }
1202 });
Terry Wang2da17852020-12-16 19:59:08 -08001203 }
1204
1205 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001206 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001207 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001208 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001209 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1210 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001211 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001212 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001213 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001214
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001215 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -08001216 int callingUid = Binder.getCallingUid();
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001217 UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
Cassie Wang84e33a02021-06-18 14:13:31 -07001218
Terry Wange04ceab2021-03-29 19:25:12 -07001219 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001220 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001221 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001222 int operationSuccessCount = 0;
1223 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001224 try {
Cassie Wang84e33a02021-06-18 14:13:31 -07001225 Context userContext = mContext.createContextAsUser(callingUser, /*flags=*/ 0);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001226 verifyUserUnlocked(callingUser);
Cassie Wang84e33a02021-06-18 14:13:31 -07001227 verifyCallingPackage(userContext, callingUser, callingUid, packageName);
1228 verifyNotInstantApp(userContext, packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001229 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001230 userContext, callingUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001231 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001232 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1233 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001234 ++operationFailureCount;
1235 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001236 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001237 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001238 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001239 int estimatedBinderLatencyMillis =
1240 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1241 int totalLatencyMillis =
1242 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001243 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001244 .setStatusCode(statusCode)
1245 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001246 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1247 // TODO(b/173532925) check the existing binder call latency chart
1248 // is good enough for us:
1249 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1250 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1251 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001252 .setNumOperationsFailed(operationFailureCount)
1253 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001254 }
Terry Wange04ceab2021-03-29 19:25:12 -07001255 }
1256 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001257 }
1258
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001259 private void verifyCallingPackage(
Cassie Wang84e33a02021-06-18 14:13:31 -07001260 @NonNull Context userContext,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001261 @NonNull UserHandle actualCallingUser,
1262 int actualCallingUid,
1263 @NonNull String claimedCallingPackage) {
1264 Objects.requireNonNull(actualCallingUser);
1265 Objects.requireNonNull(claimedCallingPackage);
1266
Cassie Wang84e33a02021-06-18 14:13:31 -07001267 int claimedCallingUid = PackageUtil.getPackageUid(
1268 userContext, claimedCallingPackage);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001269 if (claimedCallingUid == INVALID_UID) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001270 throw new SecurityException(
1271 "Specified calling package [" + claimedCallingPackage + "] not found");
1272 }
1273 if (claimedCallingUid != actualCallingUid) {
Cassie Wang0c62d992021-01-15 14:39:30 -08001274 throw new SecurityException(
1275 "Specified calling package ["
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001276 + claimedCallingPackage
Cassie Wang0c62d992021-01-15 14:39:30 -08001277 + "] does not match the calling uid "
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001278 + actualCallingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001279 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001280 }
1281
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001282 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001283 private void invokeCallbackOnResult(
1284 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001285 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001286 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001287 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001288 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001289 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001290 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001291
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001292 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001293 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001294 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001295 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001296 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001297 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001298 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001299 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001300 }
1301
1302 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001303 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001304 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001305 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001306 */
1307 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001308 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001309 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001310 callback.onResult(new AppSearchResultParcel<>(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);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001313 }
1314 }
1315
1316 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001317 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001318 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001319 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001320 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001321 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001322 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001323 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001324 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001325 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001326 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001327 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001328 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001329 }
Terry Wangfebbead2019-10-17 17:05:18 -07001330 }
Terry Wangf2093072020-11-30 04:47:19 -08001331
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001332 /**
1333 * Helper for dealing with incoming user arguments to system service calls.
1334 *
1335 * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
1336 *
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001337 * @param requestedUser The user which the caller is requesting to execute as.
1338 * @param callingUid The actual uid of the caller as determined by Binder.
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001339 * @return the user handle that the call should run as. Will always be a concrete user.
1340 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001341 @NonNull
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001342 private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
Terry Wangf2093072020-11-30 04:47:19 -08001343 int callingPid = Binder.getCallingPid();
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001344 UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
1345 if (callingUser.equals(requestedUser)) {
1346 return requestedUser;
1347 }
1348 // Duplicates UserController#ensureNotSpecialUser
1349 if (requestedUser.getIdentifier() < 0) {
1350 throw new IllegalArgumentException(
1351 "Call does not support special user " + requestedUser);
1352 }
1353 boolean canInteractAcrossUsers = mContext.checkPermission(
1354 Manifest.permission.INTERACT_ACROSS_USERS,
Cassie Wang0c62d992021-01-15 14:39:30 -08001355 callingPid,
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001356 callingUid) == PackageManager.PERMISSION_GRANTED;
1357 if (!canInteractAcrossUsers) {
1358 canInteractAcrossUsers = mContext.checkPermission(
1359 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1360 callingPid,
1361 callingUid) == PackageManager.PERMISSION_GRANTED;
1362 }
1363 if (canInteractAcrossUsers) {
1364 return requestedUser;
1365 }
1366 throw new SecurityException(
1367 "Permission denied while calling from uid " + callingUid
1368 + " with " + requestedUser + "; Need to run as either the calling user ("
1369 + callingUser + "), or with one of the following permissions: "
1370 + Manifest.permission.INTERACT_ACROSS_USERS + " or "
1371 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001372 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001373
Cassie Wang84e33a02021-06-18 14:13:31 -07001374 /**
1375 * Helper for ensuring instant apps can't make calls to AppSearch.
1376 *
1377 * @param userContext Context of the user making the call.
1378 * @param packageName Package name of the caller.
1379 * @throws SecurityException if the caller is an instant app.
1380 */
1381 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1382 PackageManager callingPackageManager = userContext.getPackageManager();
1383 if (callingPackageManager.isInstantApp(packageName)) {
1384 throw new SecurityException("Caller not allowed to create AppSearch session"
1385 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1386 }
1387 }
1388
Yang Yu0fcd51a2021-04-23 11:25:44 -07001389 // TODO(b/179160886): Cache the previous storage stats.
1390 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1391 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001392 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001393 @NonNull PackageStats stats,
1394 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001395 @NonNull UserHandle userHandle,
1396 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001397 Objects.requireNonNull(stats);
1398 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001399 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001400
Yang Yu0fcd51a2021-04-23 11:25:44 -07001401 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001402 verifyUserUnlocked(userHandle);
Cassie Wang84e33a02021-06-18 14:13:31 -07001403 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001404 AppSearchUserInstance instance =
1405 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001406 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001407 stats.dataSize += instance.getAppSearchImpl()
1408 .getStorageInfoForPackage(packageName).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001409 } catch (Throwable t) {
1410 Log.e(
1411 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001412 "Unable to augment storage stats for "
1413 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001414 + " packageName "
1415 + packageName,
1416 t);
1417 }
1418 }
1419
1420 @Override
1421 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001422 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001423 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001424
1425 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001426 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001427 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001428 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1429 if (packagesForUid == null) {
1430 return;
1431 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001432 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001433 AppSearchUserInstance instance =
1434 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001435 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001436 for (int i = 0; i < packagesForUid.length; i++) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001437 stats.dataSize += instance.getAppSearchImpl()
1438 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001439 }
1440 } catch (Throwable t) {
1441 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1442 }
1443 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001444
1445 @Override
1446 public void augmentStatsForUser(
1447 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1448 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1449 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1450 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1451 Objects.requireNonNull(stats);
1452 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001453
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001454 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001455 verifyUserUnlocked(userHandle);
1456 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1457 /*flags=*/0, userHandle.getIdentifier());
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001458 if (packagesForUser == null) {
1459 return;
1460 }
Cassie Wang84e33a02021-06-18 14:13:31 -07001461 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001462 AppSearchUserInstance instance =
1463 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -07001464 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001465 for (int i = 0; i < packagesForUser.size(); i++) {
1466 String packageName = packagesForUser.get(i).packageName;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001467 stats.dataSize += instance.getAppSearchImpl()
1468 .getStorageInfoForPackage(packageName).getSizeBytes();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001469 }
1470 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001471 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001472 }
1473 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001474 }
Terry Wangfebbead2019-10-17 17:05:18 -07001475}