blob: e2e7315a1915e9e0314076b5f5b34d01e7442387 [file] [log] [blame]
Terry Wangfebbead2019-10-17 17:05:18 -07001/*
sidchhabraa7c8f8a2020-01-16 18:38:17 -08002 * Copyright (C) 2020 The Android Open Source Project
Terry Wangfebbead2019-10-17 17:05:18 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.server.appsearch;
17
Terry Wangdbd1dca2020-11-03 17:03:56 -080018import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
Terry Wange201dc02021-04-16 01:03:20 -070019import static android.os.Process.INVALID_UID;
Terry Wangdbd1dca2020-11-03 17:03:56 -080020
Cassie Wang2e2d0552021-08-04 16:18:10 +000021import android.Manifest;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080022import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080023import android.annotation.NonNull;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080024import android.annotation.WorkerThread;
Alexander Dorokhine18465842020-01-21 01:08:57 -080025import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080026import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080027import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070028import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070029import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070030import android.app.appsearch.GetSchemaResponse;
Terry Wang26b9e5c2020-10-23 02:05:01 -070031import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070032import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080033import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070034import android.app.appsearch.StorageInfo;
Terry Wang5b0c5612021-12-23 15:57:19 -080035import android.app.appsearch.VisibilityDocument;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070036import android.app.appsearch.aidl.AppSearchBatchResultParcel;
37import android.app.appsearch.aidl.AppSearchResultParcel;
38import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
39import android.app.appsearch.aidl.IAppSearchManager;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080040import android.app.appsearch.aidl.IAppSearchObserverProxy;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070041import android.app.appsearch.aidl.IAppSearchResultCallback;
Alexander Dorokhine4d051632021-06-18 10:48:58 -070042import android.app.appsearch.exceptions.AppSearchException;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080043import android.app.appsearch.observer.ObserverSpec;
Terry Wang12dc6c02021-03-31 19:26:16 -070044import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070045import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070046import android.content.Intent;
47import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070048import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070049import android.content.pm.PackageManager;
Yang Yu0fcd51a2021-04-23 11:25:44 -070050import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080051import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070052import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080053import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080054import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080055import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080056import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070057import android.os.UserManager;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080058import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080059import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070060
Cassie Wang15c86972021-02-09 13:43:25 -080061import com.android.internal.annotations.GuardedBy;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070062import com.android.server.LocalManagerRegistry;
Terry Wangfebbead2019-10-17 17:05:18 -070063import com.android.server.SystemService;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080064import com.android.server.appsearch.external.localstorage.stats.CallStats;
Alexander Dorokhine14816e22021-07-12 10:53:24 -070065import com.android.server.appsearch.external.localstorage.stats.OptimizeStats;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070066import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080067import com.android.server.appsearch.observer.AppSearchObserverProxy;
Xiaoyu Jin10329472021-06-23 16:50:03 -070068import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070069import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070070import com.android.server.usage.StorageStatsManagerLocal;
71import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080072
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070073import com.google.android.icing.proto.PersistType;
74
Terry Wang623e3b02021-02-02 20:27:33 -080075import java.io.DataInputStream;
76import java.io.DataOutputStream;
77import java.io.EOFException;
78import java.io.FileInputStream;
79import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080080import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080081import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080082import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080083import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080084import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070085import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070086import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070087import java.util.concurrent.ThreadPoolExecutor;
88import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080089
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070090/**
91 * The main service implementation which contains AppSearch's platform functionality.
Yang Yuc047f7b2021-06-25 12:22:42 -070092 *
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070093 * @hide
94 */
Terry Wangfebbead2019-10-17 17:05:18 -070095public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070096 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070097 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070098 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070099 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700100 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -0700101
Terry Wange04ceab2021-03-29 19:25:12 -0700102 // Never call shutdownNow(). It will cancel the futures it's returned. And since
103 // Executor#execute won't return anything, we will hang forever waiting for the execution.
104 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
105 // mutate requests will need to gain write lock and query requests need to gain read lock.
106 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
107 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700108 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700109
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700110 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
111 // suffix refers to the fact that access to the field should be locked; unrelated to the
112 // unlocked status of users.
113 @GuardedBy("mUnlockedUsersLocked")
114 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800115
Terry Wangfebbead2019-10-17 17:05:18 -0700116 public AppSearchManagerService(Context context) {
117 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700118 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700119 }
120
121 @Override
122 public void onStart() {
123 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700124 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700125 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700126 mUserManager = mContext.getSystemService(UserManager.class);
127 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700128 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700129 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700130 }
131
Xiaoyu Jin10329472021-06-23 16:50:03 -0700132 @Override
133 public void onBootPhase(/* @BootPhase */ int phase) {
134 if (phase == PHASE_BOOT_COMPLETED) {
135 StatsCollector.getInstance(mContext, EXECUTOR);
136 }
137 }
138
Terry Wang12dc6c02021-03-31 19:26:16 -0700139 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700140 mContext.registerReceiverForAllUsers(
141 new UserActionReceiver(),
142 new IntentFilter(Intent.ACTION_USER_REMOVED),
143 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700144 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700145
146 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
147 // broadcasts
148 IntentFilter packageChangedFilter = new IntentFilter();
149 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
150 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
151 packageChangedFilter.addDataScheme("package");
152 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700153 mContext.registerReceiverForAllUsers(
154 new PackageChangedReceiver(),
155 packageChangedFilter,
156 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700157 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700158 }
159
160 private class UserActionReceiver extends BroadcastReceiver {
161 @Override
162 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700163 Objects.requireNonNull(context);
164 Objects.requireNonNull(intent);
165
Terry Wang12dc6c02021-03-31 19:26:16 -0700166 switch (intent.getAction()) {
167 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700168 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
169 if (userHandle == null) {
170 Log.e(TAG, "Extra "
171 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700172 return;
173 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700174 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700175 break;
176 default:
Terry Wange201dc02021-04-16 01:03:20 -0700177 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700178 }
179 }
180 }
181
182 /**
183 * Handles user removed action.
184 *
185 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
186 * "credential encrypted" system directory of each user. That directory will be auto-deleted
187 * when a user is removed.
188 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700189 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700190 * @see android.os.Environment#getDataSystemCeDirectory
191 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700192 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700193 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700194 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700195 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700196 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700197 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700198 }
199 }
200
201 private class PackageChangedReceiver extends BroadcastReceiver {
202 @Override
203 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700204 Objects.requireNonNull(context);
205 Objects.requireNonNull(intent);
206
Terry Wange201dc02021-04-16 01:03:20 -0700207 switch (intent.getAction()) {
208 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
209 case Intent.ACTION_PACKAGE_DATA_CLEARED:
210 String packageName = intent.getData().getSchemeSpecificPart();
211 if (packageName == null) {
212 Log.e(TAG, "Package name is missing in the intent: " + intent);
213 return;
214 }
215 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
216 if (uid == INVALID_UID) {
217 Log.e(TAG, "uid is missing in the intent: " + intent);
218 return;
219 }
220 handlePackageRemoved(packageName, uid);
221 break;
222 default:
223 Log.e(TAG, "Received unknown intent: " + intent);
224 }
225 }
226 }
227
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700228 private void handlePackageRemoved(@NonNull String packageName, int uid) {
229 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700230 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700231 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700232 // We cannot access a locked user's directry and remove package data from it.
233 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700234 return;
235 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700236 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700237 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700238 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700239 AppSearchUserInstance instance =
240 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700241 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700242 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700243 instance.getAppSearchImpl().clearPackageData(packageName);
244 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700245 }
246 } catch (Throwable t) {
247 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700248 }
Terry Wangfebbead2019-10-17 17:05:18 -0700249 }
250
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800251 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700252 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700253 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700254 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700255 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700256 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800257 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700258 EXECUTOR.execute(() -> {
259 try {
260 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700261 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700262 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700263 AppSearchUserInstance instance =
264 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700265 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
266 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700267 .getPackageManager()
268 .getInstalledPackages(/*flags=*/0);
269 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
270 for (int i = 0; i < installedPackageInfos.size(); i++) {
271 packagesToKeep.add(installedPackageInfos.get(i).packageName);
272 }
Terry Wang0be9c302022-01-21 14:36:18 -0800273 packagesToKeep.add(VisibilityStore.VISIBILITY_PACKAGE_NAME);
Terry Wanga9e6e212021-04-23 15:51:37 -0700274 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700275 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700276 }
277 } catch (Throwable t) {
278 Log.e(TAG, "Unable to prune packages for " + user, t);
279 }
280 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800281 }
282
Terry Wangde9f3382021-04-28 19:45:07 -0700283 @Override
284 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700285 Objects.requireNonNull(user);
286
287 synchronized (mUnlockedUsersLocked) {
288 UserHandle userHandle = user.getUserHandle();
289 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700290 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700291 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700292 } catch (Throwable t) {
293 Log.e(TAG, "Error handling user stopping.", t);
294 }
295 }
296 }
297
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700298 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
299 if (isUserLocked(callingUser)) {
300 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700301 }
302 }
303
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700304 private boolean isUserLocked(@NonNull UserHandle callingUser) {
305 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700306 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700307 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700308 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700309 }
310 // If the local copy says the user is locked, check with UM for the actual state,
311 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700312 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700313 }
314 }
315
Terry Wangfebbead2019-10-17 17:05:18 -0700316 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800317 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800318 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800319 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700320 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700321 @NonNull List<Bundle> schemaBundles,
Terry Wang5b0c5612021-12-23 15:57:19 -0800322 @NonNull List<Bundle> visibilityBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800323 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700324 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700325 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700326 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800327 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700328 Objects.requireNonNull(packageName);
329 Objects.requireNonNull(databaseName);
330 Objects.requireNonNull(schemaBundles);
Terry Wang5b0c5612021-12-23 15:57:19 -0800331 Objects.requireNonNull(visibilityBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700332 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700333 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700334
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700335 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000336 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800337 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700338 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700339 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700340 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700341 int operationSuccessCount = 0;
342 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700343 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000344 verifyCaller(callingUid, packageName);
345
346 // Obtain the user where the client wants to run the operations in. This should
347 // end up being the same as userHandle, assuming it is not a special user and
348 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000349 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000350 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000351
Terry Wange04ceab2021-03-29 19:25:12 -0700352 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
353 for (int i = 0; i < schemaBundles.size(); i++) {
354 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800355 }
Terry Wang5b0c5612021-12-23 15:57:19 -0800356 List<VisibilityDocument> visibilityDocuments =
357 new ArrayList<>(visibilityBundles.size());
358 for (int i = 0; i < visibilityBundles.size(); i++) {
359 visibilityDocuments.add(
360 new VisibilityDocument(visibilityBundles.get(i)));
Terry Wange04ceab2021-03-29 19:25:12 -0700361 }
Cassie Wang2feb34d2021-07-22 18:55:19 +0000362 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700363 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700364 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700365 packageName,
366 databaseName,
367 schemas,
Terry Wange15ea582021-10-21 18:59:21 -0700368 visibilityDocuments,
Terry Wange04ceab2021-03-29 19:25:12 -0700369 forceOverride,
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700370 schemaVersion,
371 /*setSchemaStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700372 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700373 invokeCallbackOnResult(callback,
374 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700375
376 // setSchema will sync the schemas in the request to AppSearch, any existing
377 // schemas which is not included in the request will be delete if we force
378 // override incompatible schemas. And all documents of these types will be
379 // deleted as well. We should checkForOptimize for these deletion.
380 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700381 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700382 ++operationFailureCount;
383 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700384 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700385 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700386 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700387 int estimatedBinderLatencyMillis =
388 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
389 int totalLatencyMillis =
390 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700391 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700392 .setPackageName(packageName)
393 .setDatabase(databaseName)
394 .setStatusCode(statusCode)
395 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700396 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
397 // TODO(b/173532925) check the existing binder call latency chart
398 // is good enough for us:
399 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
400 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
401 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700402 .setNumOperationsFailed(operationFailureCount)
403 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700404 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800405 }
Terry Wange04ceab2021-03-29 19:25:12 -0700406 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800407 }
408
409 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800410 public void getSchema(
Alexander Dorokhined41def42022-01-25 15:45:34 -0800411 @NonNull String callingPackageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800412 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800413 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700414 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800415 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800416 Objects.requireNonNull(callingPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700417 Objects.requireNonNull(packageName);
418 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700419 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700420 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700421
Cassie Wang2e2d0552021-08-04 16:18:10 +0000422 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700423 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700424 EXECUTOR.execute(() -> {
425 try {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800426 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000427
428 // Obtain the user where the client wants to run the operations in. This should
429 // end up being the same as userHandle, assuming it is not a special user and
430 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000431 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000432 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000433
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700434 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000435 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700436 GetSchemaResponse response =
Alexander Dorokhined41def42022-01-25 15:45:34 -0800437 instance.getAppSearchImpl().getSchema(
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800438 packageName,
439 databaseName,
440 callingPackageName,
441 callingUid,
442 instance.getVisibilityChecker()
443 .doesCallerHaveSystemAccess(callingPackageName));
Terry Wange04ceab2021-03-29 19:25:12 -0700444 invokeCallbackOnResult(
445 callback,
446 AppSearchResult.newSuccessfulResult(response.getBundle()));
447 } catch (Throwable t) {
448 invokeCallbackOnError(callback, t);
449 }
450 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700451 }
452
453 @Override
454 public void getNamespaces(
455 @NonNull String packageName,
456 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700457 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700458 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700459 Objects.requireNonNull(packageName);
460 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700461 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700462 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700463
Cassie Wang2e2d0552021-08-04 16:18:10 +0000464 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700465 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700466 EXECUTOR.execute(() -> {
467 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000468 verifyCaller(callingUid, packageName);
469
470 // Obtain the user where the client wants to run the operations in. This should
471 // end up being the same as userHandle, assuming it is not a special user and
472 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000473 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000474 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000475
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700476 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000477 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700478 List<String> namespaces =
479 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
480 invokeCallbackOnResult(
481 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700482 } catch (Throwable t) {
483 invokeCallbackOnError(callback, t);
484 }
485 });
Terry Wang83a24932020-12-09 21:00:18 -0800486 }
487
488 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800489 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800490 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700491 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700492 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700493 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800494 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800495 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700496 Objects.requireNonNull(packageName);
497 Objects.requireNonNull(databaseName);
498 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700499 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700500 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700501
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700502 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000503 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800504 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700505 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800506 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700507 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800508 int operationSuccessCount = 0;
509 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700510 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000511 verifyCaller(callingUid, packageName);
512
513 // Obtain the user where the client wants to run the operations in. This should
514 // end up being the same as userHandle, assuming it is not a special user and
515 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000516 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000517 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000518
Terry Wange04ceab2021-03-29 19:25:12 -0700519 AppSearchBatchResult.Builder<String, Void> resultBuilder =
520 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000521 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700522 for (int i = 0; i < documentBundles.size(); i++) {
523 GenericDocument document = new GenericDocument(documentBundles.get(i));
524 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700525 instance.getAppSearchImpl().putDocument(
526 packageName, databaseName, document, instance.getLogger());
527 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800528 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700529 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700530 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800531 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700532 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700533 // Since we can only include one status code in the atom,
534 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800535 statusCode = result.getResultCode();
536 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700537 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800538 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700539 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700540 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700541 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700542
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800543 // Schedule a task to dispatch change notifications. See requirements for where
544 // the method is called documented in the method description.
545 dispatchChangeNotifications(instance);
546
Terry Wangf4d219b2021-07-01 19:11:39 -0700547 // The existing documents with same ID will be deleted, so there may be some
548 // resources that could be released after optimize().
549 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700550 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700551 ++operationFailureCount;
552 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700553 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800554 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700555 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700556 int estimatedBinderLatencyMillis =
557 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
558 int totalLatencyMillis =
559 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700560 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700561 .setPackageName(packageName)
562 .setDatabase(databaseName)
563 .setStatusCode(statusCode)
564 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800565 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
566 // TODO(b/173532925) check the existing binder call latency chart
567 // is good enough for us:
568 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700569 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800570 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700571 .setNumOperationsFailed(operationFailureCount)
572 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800573 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800574 }
Terry Wange04ceab2021-03-29 19:25:12 -0700575 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800576 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800577
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800578 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800579 public void getDocuments(
Alex Saveliev87631932022-01-21 00:48:44 +0000580 @NonNull String callingPackageName,
581 @NonNull String targetPackageName,
Terry Wangf2093072020-11-30 04:47:19 -0800582 @NonNull String databaseName,
583 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700584 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800585 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700586 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700587 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800588 @NonNull IAppSearchBatchResultCallback callback) {
Alex Saveliev87631932022-01-21 00:48:44 +0000589 Objects.requireNonNull(callingPackageName);
590 Objects.requireNonNull(targetPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700591 Objects.requireNonNull(databaseName);
592 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700593 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700594 Objects.requireNonNull(typePropertyPaths);
595 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700596 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700597
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700598 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000599 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800600 int callingUid = Binder.getCallingUid();
Alex Saveliev6af06242022-02-01 13:50:35 -0800601
602 boolean global = !callingPackageName.equals(targetPackageName);
Terry Wange04ceab2021-03-29 19:25:12 -0700603 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700604 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700605 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700606 int operationSuccessCount = 0;
607 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700608 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000609 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000610
611 // Obtain the user where the client wants to run the operations in. This should
612 // end up being the same as userHandle, assuming it is not a special user and
613 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000614 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000615 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000616
Terry Wange04ceab2021-03-29 19:25:12 -0700617 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
618 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000619 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700620 for (int i = 0; i < ids.size(); i++) {
621 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700622 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000623 GenericDocument document;
624 if (global) {
Alex Saveliev87631932022-01-21 00:48:44 +0000625 document = instance.getAppSearchImpl().globalGetDocument(
626 targetPackageName,
627 databaseName,
628 namespace,
629 id,
630 typePropertyPaths,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800631 callingPackageName,
Alex Saveliev87631932022-01-21 00:48:44 +0000632 callingUid,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800633 instance.getVisibilityChecker()
Alex Saveliev87631932022-01-21 00:48:44 +0000634 .doesCallerHaveSystemAccess(callingPackageName));
635 } else {
636 document = instance.getAppSearchImpl().getDocument(
637 targetPackageName,
638 databaseName,
639 namespace,
640 id,
641 typePropertyPaths);
642 }
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700643 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700644 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700645 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700646 // Since we can only include one status code in the atom,
647 // for failures, we would just save the one for the last failure
648 AppSearchResult<Bundle> result = throwableToFailedResult(t);
649 resultBuilder.setResult(id, result);
650 statusCode = result.getResultCode();
651 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700652 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800653 }
Terry Wange04ceab2021-03-29 19:25:12 -0700654 invokeCallbackOnResult(callback, resultBuilder.build());
655 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700656 ++operationFailureCount;
657 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700658 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700659 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700660 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700661 int estimatedBinderLatencyMillis =
662 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
663 int totalLatencyMillis =
664 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alex Saveliev6af06242022-02-01 13:50:35 -0800665 int callType = global?
666 CallStats.CALL_TYPE_GLOBAL_GET_DOCUMENT_BY_ID:
667 CallStats.CALL_TYPE_GET_DOCUMENTS;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700668 instance.getLogger().logStats(new CallStats.Builder()
Alex Saveliev87631932022-01-21 00:48:44 +0000669 .setPackageName(targetPackageName)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700670 .setDatabase(databaseName)
671 .setStatusCode(statusCode)
672 .setTotalLatencyMillis(totalLatencyMillis)
Alex Saveliev6af06242022-02-01 13:50:35 -0800673 .setCallType(callType)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700674 // TODO(b/173532925) check the existing binder call latency chart
675 // is good enough for us:
676 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
677 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
678 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700679 .setNumOperationsFailed(operationFailureCount)
680 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700681 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800682 }
Terry Wange04ceab2021-03-29 19:25:12 -0700683 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800684 }
685
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800686 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800687 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800688 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700689 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700690 @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,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700694 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700695 Objects.requireNonNull(packageName);
696 Objects.requireNonNull(databaseName);
697 Objects.requireNonNull(queryExpression);
698 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700699 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700700 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700701
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700702 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000703 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800704 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700705 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700706 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700707 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700708 int operationSuccessCount = 0;
709 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700710 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000711 verifyCaller(callingUid, packageName);
712
713 // Obtain the user where the client wants to run the operations in. This should
714 // end up being the same as userHandle, assuming it is not a special user and
715 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000716 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000717 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000718
Cassie Wang2feb34d2021-07-22 18:55:19 +0000719 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700720 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
721 packageName,
722 databaseName,
723 queryExpression,
724 new SearchSpec(searchSpecBundle),
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()));
730 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700731 ++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 .setDatabase(databaseName)
743 .setStatusCode(statusCode)
744 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700745 .setCallType(CallStats.CALL_TYPE_SEARCH)
746 // TODO(b/173532925) check the existing binder call latency chart
747 // is good enough for us:
748 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
749 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
750 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700751 .setNumOperationsFailed(operationFailureCount)
752 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700753 }
Terry Wange04ceab2021-03-29 19:25:12 -0700754 }
755 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700756 }
757
Terry Wangf2093072020-11-30 04:47:19 -0800758 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800759 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800760 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800761 @NonNull String queryExpression,
762 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700763 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700764 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800765 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700766 Objects.requireNonNull(packageName);
767 Objects.requireNonNull(queryExpression);
768 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700769 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700770 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700771
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700772 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000773 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800774 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700775 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700776 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700777 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700778 int operationSuccessCount = 0;
779 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700780 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000781 verifyCaller(callingUid, packageName);
782
783 // Obtain the user where the client wants to run the operations in. This should
784 // end up being the same as userHandle, assuming it is not a special user and
785 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000786 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000787 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000788
Cassie Wang2feb34d2021-07-22 18:55:19 +0000789 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700790
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800791 boolean callerHasSystemAccess = instance.getVisibilityChecker()
Terry Wang0be9c302022-01-21 14:36:18 -0800792 .doesCallerHaveSystemAccess(packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700793 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
794 queryExpression,
795 new SearchSpec(searchSpecBundle),
796 packageName,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700797 callingUid,
798 callerHasSystemAccess,
799 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700800 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700801 invokeCallbackOnResult(
802 callback,
803 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700804 } catch (Throwable t) {
805 ++operationFailureCount;
806 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700807 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700808 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700809 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700810 int estimatedBinderLatencyMillis =
811 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
812 int totalLatencyMillis =
813 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700814 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700815 .setPackageName(packageName)
816 .setStatusCode(statusCode)
817 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700818 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
819 // TODO(b/173532925) check the existing binder call latency chart
820 // is good enough for us:
821 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
822 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
823 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700824 .setNumOperationsFailed(operationFailureCount)
825 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700826 }
Terry Wange04ceab2021-03-29 19:25:12 -0700827 }
828 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800829 }
830
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700831 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800832 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700833 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800834 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700835 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700836 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700837 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700838 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700839 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700840
Cassie Wang2e2d0552021-08-04 16:18:10 +0000841 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800842 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700843 EXECUTOR.execute(() -> {
844 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000845 verifyCaller(callingUid, packageName);
846
847 // Obtain the user where the client wants to run the operations in. This should
848 // end up being the same as userHandle, assuming it is not a special user and
849 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000850 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000851 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000852
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700853 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000854 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700855 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700856 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700857 instance.getAppSearchImpl().getNextPage(
858 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700859 invokeCallbackOnResult(
860 callback,
861 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
862 } catch (Throwable t) {
863 invokeCallbackOnError(callback, t);
864 }
865 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700866 }
867
868 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700869 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
870 @NonNull UserHandle userHandle) {
871 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700872 Objects.requireNonNull(userHandle);
873
Cassie Wang2e2d0552021-08-04 16:18:10 +0000874 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800875 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700876 EXECUTOR.execute(() -> {
877 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000878 verifyCaller(callingUid, packageName);
879
880 // Obtain the user where the client wants to run the operations in. This should
881 // end up being the same as userHandle, assuming it is not a special user and
882 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000883 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000884 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000885
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700886 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000887 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700888 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700889 } catch (Throwable t) {
890 Log.e(TAG, "Unable to invalidate the query page token", t);
891 }
892 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800893 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800894
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700895 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800896 public void writeQueryResultsToFile(
897 @NonNull String packageName,
898 @NonNull String databaseName,
899 @NonNull ParcelFileDescriptor fileDescriptor,
900 @NonNull String queryExpression,
901 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700902 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800903 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700904 Objects.requireNonNull(packageName);
905 Objects.requireNonNull(databaseName);
906 Objects.requireNonNull(fileDescriptor);
907 Objects.requireNonNull(queryExpression);
908 Objects.requireNonNull(searchSpecBundle);
909 Objects.requireNonNull(userHandle);
910 Objects.requireNonNull(callback);
911
Cassie Wang2e2d0552021-08-04 16:18:10 +0000912 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800913 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700914 EXECUTOR.execute(() -> {
915 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000916 verifyCaller(callingUid, packageName);
917
918 // Obtain the user where the client wants to run the operations in. This should
919 // end up being the same as userHandle, assuming it is not a special user and
920 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000921 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000922 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000923
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700924 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000925 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700926 // we don't need to append the file. The file is always brand new.
927 try (DataOutputStream outputStream = new DataOutputStream(
928 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700929 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700930 packageName,
931 databaseName,
932 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700933 new SearchSpec(searchSpecBundle),
934 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700935 while (!searchResultPage.getResults().isEmpty()) {
936 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
937 AppSearchMigrationHelper.writeBundleToOutputStream(
938 outputStream, searchResultPage.getResults().get(i)
939 .getGenericDocument().getBundle());
940 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700941 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700942 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700943 packageName,
944 searchResultPage.getNextPageToken(),
945 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800946 }
Terry Wang623e3b02021-02-02 20:27:33 -0800947 }
Terry Wange04ceab2021-03-29 19:25:12 -0700948 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
949 } catch (Throwable t) {
950 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800951 }
Terry Wange04ceab2021-03-29 19:25:12 -0700952 });
Terry Wang623e3b02021-02-02 20:27:33 -0800953 }
954
955 @Override
956 public void putDocumentsFromFile(
957 @NonNull String packageName,
958 @NonNull String databaseName,
959 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700960 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800961 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700962 Objects.requireNonNull(packageName);
963 Objects.requireNonNull(databaseName);
964 Objects.requireNonNull(fileDescriptor);
965 Objects.requireNonNull(userHandle);
966 Objects.requireNonNull(callback);
967
Cassie Wang2e2d0552021-08-04 16:18:10 +0000968 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800969 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700970 EXECUTOR.execute(() -> {
971 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000972 verifyCaller(callingUid, packageName);
973
974 // Obtain the user where the client wants to run the operations in. This should
975 // end up being the same as userHandle, assuming it is not a special user and
976 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000977 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000978 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000979
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700980 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000981 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800982
Terry Wange04ceab2021-03-29 19:25:12 -0700983 GenericDocument document;
984 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
985 try (DataInputStream inputStream = new DataInputStream(
986 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
987 while (true) {
988 try {
989 document = AppSearchMigrationHelper
990 .readDocumentFromInputStream(inputStream);
991 } catch (EOFException e) {
992 // nothing wrong, we just finish the reading.
993 break;
994 }
995 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700996 instance.getAppSearchImpl().putDocument(
997 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700998 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700999 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
1000 document.getNamespace(),
1001 document.getId(),
1002 document.getSchemaType(),
1003 AppSearchResult.throwableToFailedResult(t))
1004 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -07001005 }
Terry Wang623e3b02021-02-02 20:27:33 -08001006 }
1007 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001008 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -07001009 invokeCallbackOnResult(callback,
1010 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
1011 } catch (Throwable t) {
1012 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -08001013 }
Terry Wange04ceab2021-03-29 19:25:12 -07001014 });
Terry Wang623e3b02021-02-02 20:27:33 -08001015 }
1016
1017 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001018 public void reportUsage(
1019 @NonNull String packageName,
1020 @NonNull String databaseName,
1021 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001022 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001023 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001024 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001025 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001026 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001027 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001028 Objects.requireNonNull(databaseName);
1029 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001030 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001031 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001032 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001033
Cassie Wang2e2d0552021-08-04 16:18:10 +00001034 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001035 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001036 EXECUTOR.execute(() -> {
1037 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001038 verifyCaller(callingUid, packageName);
1039
1040 // Obtain the user where the client wants to run the operations in. This should
1041 // end up being the same as userHandle, assuming it is not a special user and
1042 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001043 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001044 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001045
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001046 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001047 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001048
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001049 if (systemUsage && !instance.getVisibilityChecker().
Terry Wang0be9c302022-01-21 14:36:18 -08001050 doesCallerHaveSystemAccess(packageName)) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001051 throw new AppSearchException(
1052 AppSearchResult.RESULT_SECURITY_ERROR,
1053 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001054 }
1055
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001056 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001057 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001058 usageTimeMillis, systemUsage);
1059 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001060 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001061 } catch (Throwable t) {
1062 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001063 }
Terry Wange04ceab2021-03-29 19:25:12 -07001064 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001065 }
1066
1067 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001068 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001069 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001070 @NonNull String databaseName,
1071 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001072 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001073 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001074 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001075 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001076 Objects.requireNonNull(packageName);
1077 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001078 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001079 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001080 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001081 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001082
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001083 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001084 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001085 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001086 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001087 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001088 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001089 int operationSuccessCount = 0;
1090 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001091 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001092 verifyCaller(callingUid, packageName);
1093
1094 // Obtain the user where the client wants to run the operations in. This should
1095 // end up being the same as userHandle, assuming it is not a special user and
1096 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001097 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001098 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001099
Terry Wange04ceab2021-03-29 19:25:12 -07001100 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1101 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001102 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001103 for (int i = 0; i < ids.size(); i++) {
1104 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001105 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001106 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001107 packageName,
1108 databaseName,
1109 namespace,
1110 id,
1111 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001112 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001113 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001114 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001115 AppSearchResult<Void> result = throwableToFailedResult(t);
1116 resultBuilder.setResult(id, result);
1117 // Since we can only include one status code in the atom,
1118 // for failures, we would just save the one for the last failure
1119 statusCode = result.getResultCode();
1120 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001121 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001122 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001123 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001124 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001125 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001126
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001127 // Schedule a task to dispatch change notifications. See requirements for where
1128 // the method is called documented in the method description.
1129 dispatchChangeNotifications(instance);
1130
Terry Wangf4d219b2021-07-01 19:11:39 -07001131 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001132 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001133 ++operationFailureCount;
1134 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001135 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001136 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001137 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001138 int estimatedBinderLatencyMillis =
1139 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1140 int totalLatencyMillis =
1141 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001142 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001143 .setPackageName(packageName)
1144 .setDatabase(databaseName)
1145 .setStatusCode(statusCode)
1146 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001147 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1148 // TODO(b/173532925) check the existing binder call latency chart
1149 // is good enough for us:
1150 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1151 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1152 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001153 .setNumOperationsFailed(operationFailureCount)
1154 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001155 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001156 }
Terry Wange04ceab2021-03-29 19:25:12 -07001157 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001158 }
1159
1160 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001161 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001162 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001163 @NonNull String databaseName,
1164 @NonNull String queryExpression,
1165 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001166 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001167 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001168 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001169 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001170 Objects.requireNonNull(packageName);
1171 Objects.requireNonNull(databaseName);
1172 Objects.requireNonNull(queryExpression);
1173 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001174 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001175 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001176
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001177 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001178 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001179 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001180 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001181 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001182 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001183 int operationSuccessCount = 0;
1184 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001185 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001186 verifyCaller(callingUid, packageName);
1187
1188 // Obtain the user where the client wants to run the operations in. This should
1189 // end up being the same as userHandle, assuming it is not a special user and
1190 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001191 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001192 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001193
Cassie Wang2feb34d2021-07-22 18:55:19 +00001194 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001195 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001196 packageName,
1197 databaseName,
1198 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001199 new SearchSpec(searchSpecBundle),
1200 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001201 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001202 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001203 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001204 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001205
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001206 // Schedule a task to dispatch change notifications. See requirements for where
1207 // the method is called documented in the method description.
1208 dispatchChangeNotifications(instance);
1209
Terry Wangf4d219b2021-07-01 19:11:39 -07001210 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001211 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001212 ++operationFailureCount;
1213 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001214 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001215 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001216 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001217 int estimatedBinderLatencyMillis =
1218 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1219 int totalLatencyMillis =
1220 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001221 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001222 .setPackageName(packageName)
1223 .setDatabase(databaseName)
1224 .setStatusCode(statusCode)
1225 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001226 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1227 // TODO(b/173532925) check the existing binder call latency chart
1228 // is good enough for us:
1229 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1230 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1231 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001232 .setNumOperationsFailed(operationFailureCount)
1233 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001234 }
Terry Wange04ceab2021-03-29 19:25:12 -07001235 }
1236 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001237 }
1238
Terry Wangdbd1dca2020-11-03 17:03:56 -08001239 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001240 public void getStorageInfo(
1241 @NonNull String packageName,
1242 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001243 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001244 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001245 Objects.requireNonNull(packageName);
1246 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001247 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001248 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001249
Cassie Wang2e2d0552021-08-04 16:18:10 +00001250 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001251 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001252 EXECUTOR.execute(() -> {
1253 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001254 verifyCaller(callingUid, packageName);
1255
1256 // Obtain the user where the client wants to run the operations in. This should
1257 // end up being the same as userHandle, assuming it is not a special user and
1258 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001259 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001260 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001261
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001262 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001263 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001264 StorageInfo storageInfo = instance.getAppSearchImpl()
1265 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001266 Bundle storageInfoBundle = storageInfo.getBundle();
1267 invokeCallbackOnResult(
1268 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1269 } catch (Throwable t) {
1270 invokeCallbackOnError(callback, t);
1271 }
1272 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001273 }
1274
1275 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001276 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001277 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001278 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001279 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001280 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001281 Objects.requireNonNull(userHandle);
1282
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001283 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001284 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001285 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001286 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001287 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001288 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001289 int operationSuccessCount = 0;
1290 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001291 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001292 verifyCaller(callingUid, packageName);
1293
1294 // Obtain the user where the client wants to run the operations in. This should
1295 // end up being the same as userHandle, assuming it is not a special user and
1296 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001297 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001298 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001299
Cassie Wang2feb34d2021-07-22 18:55:19 +00001300 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001301 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001302 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001303 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001304 ++operationFailureCount;
1305 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001306 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001307 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001308 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001309 int estimatedBinderLatencyMillis =
1310 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1311 int totalLatencyMillis =
1312 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001313 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001314 .setStatusCode(statusCode)
1315 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001316 .setCallType(CallStats.CALL_TYPE_FLUSH)
1317 // TODO(b/173532925) check the existing binder call latency chart
1318 // is good enough for us:
1319 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1320 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1321 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001322 .setNumOperationsFailed(operationFailureCount)
1323 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001324 }
Terry Wange04ceab2021-03-29 19:25:12 -07001325 }
1326 });
Terry Wang2da17852020-12-16 19:59:08 -08001327 }
1328
1329 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001330 public AppSearchResultParcel<Void> addObserver(
1331 @NonNull String callingPackage,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001332 @NonNull String targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001333 @NonNull Bundle observerSpecBundle,
1334 @NonNull UserHandle userHandle,
1335 @NonNull IAppSearchObserverProxy observerProxyStub) {
1336 Objects.requireNonNull(callingPackage);
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001337 Objects.requireNonNull(targetPackageName);
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001338 Objects.requireNonNull(observerSpecBundle);
1339 Objects.requireNonNull(userHandle);
1340 Objects.requireNonNull(observerProxyStub);
1341
1342 int callingPid = Binder.getCallingPid();
1343 int callingUid = Binder.getCallingUid();
1344 long callingIdentity = Binder.clearCallingIdentity();
1345
1346 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1347 try {
1348 verifyCaller(callingUid, callingPackage);
1349 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1350 verifyUserUnlocked(targetUser);
1351
1352 AppSearchUserInstance instance =
1353 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1354 instance.getAppSearchImpl().addObserver(
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001355 callingPackage,
1356 callingUid,
1357 instance.getVisibilityChecker().doesCallerHaveSystemAccess(callingPackage),
1358 targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001359 new ObserverSpec(observerSpecBundle),
1360 EXECUTOR,
1361 new AppSearchObserverProxy(observerProxyStub));
1362 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1363 } catch (Throwable t) {
1364 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1365 } finally {
1366 Binder.restoreCallingIdentity(callingIdentity);
1367 }
1368 }
1369
1370 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001371 public AppSearchResultParcel<Void> removeObserver(
1372 @NonNull String callingPackage,
1373 @NonNull String observedPackage,
1374 @NonNull UserHandle userHandle,
1375 @NonNull IAppSearchObserverProxy observerProxyStub) {
1376 Objects.requireNonNull(callingPackage);
1377 Objects.requireNonNull(observedPackage);
1378 Objects.requireNonNull(userHandle);
1379 Objects.requireNonNull(observerProxyStub);
1380
1381 int callingPid = Binder.getCallingPid();
1382 int callingUid = Binder.getCallingUid();
1383 long callingIdentity = Binder.clearCallingIdentity();
1384
1385 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1386 try {
1387 verifyCaller(callingUid, callingPackage);
1388 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1389 verifyUserUnlocked(targetUser);
1390
1391 AppSearchUserInstance instance =
1392 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1393 instance.getAppSearchImpl().removeObserver(
1394 observedPackage,
1395 new AppSearchObserverProxy(observerProxyStub));
1396 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1397 } catch (Throwable t) {
1398 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1399 } finally {
1400 Binder.restoreCallingIdentity(callingIdentity);
1401 }
1402 }
1403
1404 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001405 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001406 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001407 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001408 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1409 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001410 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001411 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001412 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001413
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001414 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001415 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001416 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001417
Terry Wange04ceab2021-03-29 19:25:12 -07001418 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001419 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001420 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001421 int operationSuccessCount = 0;
1422 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001423 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001424 verifyCaller(callingUid, packageName);
1425
1426 // Obtain the user where the client wants to run the operations in. This should
1427 // end up being the same as userHandle, assuming it is not a special user and
1428 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001429 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001430 verifyUserUnlocked(targetUser);
1431
Cassie Wang2feb34d2021-07-22 18:55:19 +00001432 Context targetUserContext = mContext.createContextAsUser(targetUser,
1433 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001434 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001435 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001436 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001437 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1438 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001439 ++operationFailureCount;
1440 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001441 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001442 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001443 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001444 int estimatedBinderLatencyMillis =
1445 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1446 int totalLatencyMillis =
1447 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001448 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001449 .setStatusCode(statusCode)
1450 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001451 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1452 // TODO(b/173532925) check the existing binder call latency chart
1453 // is good enough for us:
1454 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1455 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1456 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001457 .setNumOperationsFailed(operationFailureCount)
1458 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001459 }
Terry Wange04ceab2021-03-29 19:25:12 -07001460 }
1461 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001462 }
1463
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001464 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001465 private void invokeCallbackOnResult(
1466 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001467 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001468 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001469 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001470 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001471 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001472 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001473
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001474 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001475 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001476 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001477 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001478 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001479 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001480 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001481 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001482 }
1483
1484 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001485 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001486 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001487 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001488 */
1489 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001490 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001491 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001492 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001493 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001494 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001495 }
1496 }
1497
1498 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001499 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001500 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001501 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001502 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001503 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001504 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001505 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001506 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001507 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001508 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001509 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001510 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001511 }
Terry Wangfebbead2019-10-17 17:05:18 -07001512 }
Terry Wangf2093072020-11-30 04:47:19 -08001513
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001514 /**
1515 * Helper for dealing with incoming user arguments to system service calls.
1516 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001517 * <p>Takes care of checking permissions and if the target is special user, this method will
1518 * simply throw.
1519 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001520 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001521 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001522 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001523 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001524 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001525 *
1526 * @throws IllegalArgumentException if the target user is a special user.
1527 * @throws SecurityException if caller trying to interact across user without
1528 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001529 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001530 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001531 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1532 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001533 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1534 if (callingUserHandle.equals(targetUserHandle)) {
1535 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001536 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001537
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001538 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001539 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001540 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001541 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001542 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001543
Cassie Wang2e2d0552021-08-04 16:18:10 +00001544 if (mContext.checkPermission(
1545 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1546 callingPid,
1547 callingUid) == PackageManager.PERMISSION_GRANTED) {
1548 return targetUserHandle;
1549 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001550 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001551 "Permission denied while calling from uid " + callingUid
1552 + " with " + targetUserHandle + "; Requires permission: "
1553 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001554 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001555
Cassie Wang84e33a02021-06-18 14:13:31 -07001556 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001557 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001558 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001559 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1560 * @param claimedCallingPackage Package name the caller claims to be.
1561 */
1562 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1563 // Obtain the user where the client is running in. Note that this could be different from
1564 // the userHandle where the client wants to run the AppSearch operation in.
1565 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1566 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1567 /*flags=*/ 0);
1568
1569 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1570 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1571 }
1572
1573 /**
1574 * Check that the caller's supposed package name matches the uid making the call.
1575 *
1576 * @throws SecurityException if the package name and uid don't match.
1577 */
1578 private void verifyCallingPackage(
1579 @NonNull Context actualCallingUserContext,
1580 int actualCallingUid,
1581 @NonNull String claimedCallingPackage) {
1582 int claimedCallingUid = PackageUtil.getPackageUid(
1583 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001584 if (claimedCallingUid != actualCallingUid) {
1585 throw new SecurityException(
1586 "Specified calling package ["
1587 + claimedCallingPackage
1588 + "] does not match the calling uid "
1589 + actualCallingUid);
1590 }
1591 }
1592
1593 /**
1594 * Ensure instant apps can't make calls to AppSearch.
1595 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001596 * @throws SecurityException if the caller is an instant app.
1597 */
1598 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1599 PackageManager callingPackageManager = userContext.getPackageManager();
1600 if (callingPackageManager.isInstantApp(packageName)) {
1601 throw new SecurityException("Caller not allowed to create AppSearch session"
1602 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1603 }
1604 }
1605
Yang Yu0fcd51a2021-04-23 11:25:44 -07001606 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1607 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001608 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001609 @NonNull PackageStats stats,
1610 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001611 @NonNull UserHandle userHandle,
1612 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001613 Objects.requireNonNull(stats);
1614 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001615 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001616
Yang Yu0fcd51a2021-04-23 11:25:44 -07001617 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001618 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001619 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001620 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1621 if (instance == null) {
1622 // augment storage info from file
1623 UserStorageInfo userStorageInfo =
1624 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1625 userHandle);
1626 stats.dataSize +=
1627 userStorageInfo.getSizeBytesForPackage(packageName);
1628 } else {
1629 stats.dataSize += instance.getAppSearchImpl()
1630 .getStorageInfoForPackage(packageName).getSizeBytes();
1631 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001632 } catch (Throwable t) {
1633 Log.e(
1634 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001635 "Unable to augment storage stats for "
1636 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001637 + " packageName "
1638 + packageName,
1639 t);
1640 }
1641 }
1642
1643 @Override
1644 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001645 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001646 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001647
1648 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001649 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001650 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001651 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1652 if (packagesForUid == null) {
1653 return;
1654 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001655 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001656 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1657 if (instance == null) {
1658 // augment storage info from file
1659 UserStorageInfo userStorageInfo =
1660 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1661 userHandle);
1662 for (int i = 0; i < packagesForUid.length; i++) {
1663 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1664 packagesForUid[i]);
1665 }
1666 } else {
1667 for (int i = 0; i < packagesForUid.length; i++) {
1668 stats.dataSize += instance.getAppSearchImpl()
1669 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1670 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001671 }
1672 } catch (Throwable t) {
1673 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1674 }
1675 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001676
1677 @Override
1678 public void augmentStatsForUser(
1679 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1680 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1681 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1682 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1683 Objects.requireNonNull(stats);
1684 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001685
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001686 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001687 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001688 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001689 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1690 if (instance == null) {
1691 // augment storage info from file
1692 UserStorageInfo userStorageInfo =
1693 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1694 userHandle);
1695 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1696 } else {
1697 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1698 /*flags=*/0, userHandle.getIdentifier());
1699 if (packagesForUser != null) {
1700 for (int i = 0; i < packagesForUser.size(); i++) {
1701 String packageName = packagesForUser.get(i).packageName;
1702 stats.dataSize += instance.getAppSearchImpl()
1703 .getStorageInfoForPackage(packageName).getSizeBytes();
1704 }
1705 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001706 }
1707 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001708 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001709 }
1710 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001711 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001712
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001713 /**
1714 * Dispatches change notifications if there are any to dispatch.
1715 *
1716 * <p>This method is async; notifications are dispatched onto their own registered executors.
1717 *
1718 * <p>IMPORTANT: You must always call this within the background task that contains the
1719 * operation that mutated the index. If you called it outside of that task, it could start
1720 * before the task completes, causing notifications to be missed.
1721 */
1722 @WorkerThread
1723 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1724 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1725 }
1726
1727 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001728 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1729 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001730 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1731 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001732 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001733 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001734 } catch (AppSearchException e) {
1735 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001736 } finally {
1737 OptimizeStats oStats = builder
1738 .setTotalLatencyMillis(
1739 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1740 .build();
1741 if (oStats.getOriginalDocumentCount() > 0) {
1742 // see if optimize has been run by checking originalDocumentCount
1743 instance.getLogger().logStats(oStats);
1744 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001745 }
1746 });
1747 }
1748
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001749 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001750 private void checkForOptimize(AppSearchUserInstance instance) {
1751 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001752 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1753 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001754 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001755 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001756 } catch (AppSearchException e) {
1757 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001758 } finally {
1759 OptimizeStats oStats = builder
1760 .setTotalLatencyMillis(
1761 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1762 .build();
1763 if (oStats.getOriginalDocumentCount() > 0) {
1764 // see if optimize has been run by checking originalDocumentCount
1765 instance.getLogger().logStats(oStats);
1766 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001767 }
1768 });
1769 }
Terry Wangfebbead2019-10-17 17:05:18 -07001770}