blob: c16021c4c68f158bba4b96f2694963c7757e7a7d [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,
Alex Saveliev87631932022-01-21 00:48:44 +0000588 boolean global,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800589 @NonNull IAppSearchBatchResultCallback callback) {
Alex Saveliev87631932022-01-21 00:48:44 +0000590 Objects.requireNonNull(callingPackageName);
591 Objects.requireNonNull(targetPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700592 Objects.requireNonNull(databaseName);
593 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700594 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700595 Objects.requireNonNull(typePropertyPaths);
596 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700597 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700598
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700599 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000600 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800601 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700602 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700603 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700604 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700605 int operationSuccessCount = 0;
606 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700607 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000608 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000609
610 // Obtain the user where the client wants to run the operations in. This should
611 // end up being the same as userHandle, assuming it is not a special user and
612 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000613 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000614 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000615
Terry Wange04ceab2021-03-29 19:25:12 -0700616 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
617 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000618 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700619 for (int i = 0; i < ids.size(); i++) {
620 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700621 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000622 GenericDocument document;
623 if (global) {
624 // TODO(b/203819101) add test to try out security by binding
625 // directly to binder and passing callingpackage param
626 document = instance.getAppSearchImpl().globalGetDocument(
627 targetPackageName,
628 databaseName,
629 namespace,
630 id,
631 typePropertyPaths,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800632 callingPackageName,
Alex Saveliev87631932022-01-21 00:48:44 +0000633 callingUid,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800634 instance.getVisibilityChecker()
Alex Saveliev87631932022-01-21 00:48:44 +0000635 .doesCallerHaveSystemAccess(callingPackageName));
636 } else {
637 document = instance.getAppSearchImpl().getDocument(
638 targetPackageName,
639 databaseName,
640 namespace,
641 id,
642 typePropertyPaths);
643 }
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700644 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700645 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700646 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700647 // Since we can only include one status code in the atom,
648 // for failures, we would just save the one for the last failure
649 AppSearchResult<Bundle> result = throwableToFailedResult(t);
650 resultBuilder.setResult(id, result);
651 statusCode = result.getResultCode();
652 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700653 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800654 }
Terry Wange04ceab2021-03-29 19:25:12 -0700655 invokeCallbackOnResult(callback, resultBuilder.build());
656 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700657 ++operationFailureCount;
658 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700659 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700660 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700661 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700662 int estimatedBinderLatencyMillis =
663 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
664 int totalLatencyMillis =
665 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700666 instance.getLogger().logStats(new CallStats.Builder()
Alex Saveliev87631932022-01-21 00:48:44 +0000667 .setPackageName(targetPackageName)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700668 .setDatabase(databaseName)
669 .setStatusCode(statusCode)
670 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700671 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
Alex Saveliev87631932022-01-21 00:48:44 +0000672 // TODO(b/203819101) need mark the call as a global getById
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700673 // TODO(b/173532925) check the existing binder call latency chart
674 // is good enough for us:
675 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
676 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
677 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700678 .setNumOperationsFailed(operationFailureCount)
679 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700680 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800681 }
Terry Wange04ceab2021-03-29 19:25:12 -0700682 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800683 }
684
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800685 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800686 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800687 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700688 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700689 @NonNull String queryExpression,
690 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700691 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700692 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700693 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700694 Objects.requireNonNull(packageName);
695 Objects.requireNonNull(databaseName);
696 Objects.requireNonNull(queryExpression);
697 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700698 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700699 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700700
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700701 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000702 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800703 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700704 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700705 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700706 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700707 int operationSuccessCount = 0;
708 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700709 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000710 verifyCaller(callingUid, packageName);
711
712 // Obtain the user where the client wants to run the operations in. This should
713 // end up being the same as userHandle, assuming it is not a special user and
714 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000715 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000716 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000717
Cassie Wang2feb34d2021-07-22 18:55:19 +0000718 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700719 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
720 packageName,
721 databaseName,
722 queryExpression,
723 new SearchSpec(searchSpecBundle),
724 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700725 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700726 invokeCallbackOnResult(
727 callback,
728 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
729 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700730 ++operationFailureCount;
731 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700732 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700733 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700734 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700735 int estimatedBinderLatencyMillis =
736 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
737 int totalLatencyMillis =
738 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700739 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700740 .setPackageName(packageName)
741 .setDatabase(databaseName)
742 .setStatusCode(statusCode)
743 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700744 .setCallType(CallStats.CALL_TYPE_SEARCH)
745 // TODO(b/173532925) check the existing binder call latency chart
746 // is good enough for us:
747 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
748 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
749 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700750 .setNumOperationsFailed(operationFailureCount)
751 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700752 }
Terry Wange04ceab2021-03-29 19:25:12 -0700753 }
754 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700755 }
756
Terry Wangf2093072020-11-30 04:47:19 -0800757 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800758 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800759 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800760 @NonNull String queryExpression,
761 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700762 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700763 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800764 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700765 Objects.requireNonNull(packageName);
766 Objects.requireNonNull(queryExpression);
767 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700768 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700769 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700770
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700771 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000772 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800773 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700774 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700775 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700776 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700777 int operationSuccessCount = 0;
778 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700779 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000780 verifyCaller(callingUid, packageName);
781
782 // Obtain the user where the client wants to run the operations in. This should
783 // end up being the same as userHandle, assuming it is not a special user and
784 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000785 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000786 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000787
Cassie Wang2feb34d2021-07-22 18:55:19 +0000788 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700789
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800790 boolean callerHasSystemAccess = instance.getVisibilityChecker()
Terry Wang0be9c302022-01-21 14:36:18 -0800791 .doesCallerHaveSystemAccess(packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700792 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
793 queryExpression,
794 new SearchSpec(searchSpecBundle),
795 packageName,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700796 callingUid,
797 callerHasSystemAccess,
798 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700799 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700800 invokeCallbackOnResult(
801 callback,
802 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700803 } catch (Throwable t) {
804 ++operationFailureCount;
805 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700806 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700807 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700808 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700809 int estimatedBinderLatencyMillis =
810 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
811 int totalLatencyMillis =
812 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700813 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700814 .setPackageName(packageName)
815 .setStatusCode(statusCode)
816 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700817 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
818 // TODO(b/173532925) check the existing binder call latency chart
819 // is good enough for us:
820 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
821 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
822 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700823 .setNumOperationsFailed(operationFailureCount)
824 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700825 }
Terry Wange04ceab2021-03-29 19:25:12 -0700826 }
827 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800828 }
829
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700830 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800831 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700832 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800833 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700834 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700835 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700836 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700837 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700838 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700839
Cassie Wang2e2d0552021-08-04 16:18:10 +0000840 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800841 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700842 EXECUTOR.execute(() -> {
843 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000844 verifyCaller(callingUid, packageName);
845
846 // Obtain the user where the client wants to run the operations in. This should
847 // end up being the same as userHandle, assuming it is not a special user and
848 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000849 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000850 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000851
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700852 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000853 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700854 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700855 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700856 instance.getAppSearchImpl().getNextPage(
857 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700858 invokeCallbackOnResult(
859 callback,
860 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
861 } catch (Throwable t) {
862 invokeCallbackOnError(callback, t);
863 }
864 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700865 }
866
867 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700868 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
869 @NonNull UserHandle userHandle) {
870 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700871 Objects.requireNonNull(userHandle);
872
Cassie Wang2e2d0552021-08-04 16:18:10 +0000873 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800874 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700875 EXECUTOR.execute(() -> {
876 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000877 verifyCaller(callingUid, packageName);
878
879 // Obtain the user where the client wants to run the operations in. This should
880 // end up being the same as userHandle, assuming it is not a special user and
881 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000882 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000883 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000884
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700885 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000886 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700887 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700888 } catch (Throwable t) {
889 Log.e(TAG, "Unable to invalidate the query page token", t);
890 }
891 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800892 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800893
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700894 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800895 public void writeQueryResultsToFile(
896 @NonNull String packageName,
897 @NonNull String databaseName,
898 @NonNull ParcelFileDescriptor fileDescriptor,
899 @NonNull String queryExpression,
900 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700901 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800902 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700903 Objects.requireNonNull(packageName);
904 Objects.requireNonNull(databaseName);
905 Objects.requireNonNull(fileDescriptor);
906 Objects.requireNonNull(queryExpression);
907 Objects.requireNonNull(searchSpecBundle);
908 Objects.requireNonNull(userHandle);
909 Objects.requireNonNull(callback);
910
Cassie Wang2e2d0552021-08-04 16:18:10 +0000911 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800912 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700913 EXECUTOR.execute(() -> {
914 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000915 verifyCaller(callingUid, packageName);
916
917 // Obtain the user where the client wants to run the operations in. This should
918 // end up being the same as userHandle, assuming it is not a special user and
919 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000920 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000921 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000922
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700923 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000924 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700925 // we don't need to append the file. The file is always brand new.
926 try (DataOutputStream outputStream = new DataOutputStream(
927 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700928 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700929 packageName,
930 databaseName,
931 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700932 new SearchSpec(searchSpecBundle),
933 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700934 while (!searchResultPage.getResults().isEmpty()) {
935 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
936 AppSearchMigrationHelper.writeBundleToOutputStream(
937 outputStream, searchResultPage.getResults().get(i)
938 .getGenericDocument().getBundle());
939 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700940 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700941 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700942 packageName,
943 searchResultPage.getNextPageToken(),
944 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800945 }
Terry Wang623e3b02021-02-02 20:27:33 -0800946 }
Terry Wange04ceab2021-03-29 19:25:12 -0700947 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
948 } catch (Throwable t) {
949 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800950 }
Terry Wange04ceab2021-03-29 19:25:12 -0700951 });
Terry Wang623e3b02021-02-02 20:27:33 -0800952 }
953
954 @Override
955 public void putDocumentsFromFile(
956 @NonNull String packageName,
957 @NonNull String databaseName,
958 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700959 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800960 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700961 Objects.requireNonNull(packageName);
962 Objects.requireNonNull(databaseName);
963 Objects.requireNonNull(fileDescriptor);
964 Objects.requireNonNull(userHandle);
965 Objects.requireNonNull(callback);
966
Cassie Wang2e2d0552021-08-04 16:18:10 +0000967 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800968 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700969 EXECUTOR.execute(() -> {
970 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000971 verifyCaller(callingUid, packageName);
972
973 // Obtain the user where the client wants to run the operations in. This should
974 // end up being the same as userHandle, assuming it is not a special user and
975 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000976 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000977 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000978
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700979 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000980 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800981
Terry Wange04ceab2021-03-29 19:25:12 -0700982 GenericDocument document;
983 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
984 try (DataInputStream inputStream = new DataInputStream(
985 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
986 while (true) {
987 try {
988 document = AppSearchMigrationHelper
989 .readDocumentFromInputStream(inputStream);
990 } catch (EOFException e) {
991 // nothing wrong, we just finish the reading.
992 break;
993 }
994 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700995 instance.getAppSearchImpl().putDocument(
996 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700997 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700998 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
999 document.getNamespace(),
1000 document.getId(),
1001 document.getSchemaType(),
1002 AppSearchResult.throwableToFailedResult(t))
1003 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -07001004 }
Terry Wang623e3b02021-02-02 20:27:33 -08001005 }
1006 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001007 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -07001008 invokeCallbackOnResult(callback,
1009 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
1010 } catch (Throwable t) {
1011 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -08001012 }
Terry Wange04ceab2021-03-29 19:25:12 -07001013 });
Terry Wang623e3b02021-02-02 20:27:33 -08001014 }
1015
1016 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001017 public void reportUsage(
1018 @NonNull String packageName,
1019 @NonNull String databaseName,
1020 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001021 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001022 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001023 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001024 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001025 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001026 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001027 Objects.requireNonNull(databaseName);
1028 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001029 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001030 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001031 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001032
Cassie Wang2e2d0552021-08-04 16:18:10 +00001033 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001034 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001035 EXECUTOR.execute(() -> {
1036 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001037 verifyCaller(callingUid, packageName);
1038
1039 // Obtain the user where the client wants to run the operations in. This should
1040 // end up being the same as userHandle, assuming it is not a special user and
1041 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001042 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001043 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001044
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001045 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001046 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001047
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001048 if (systemUsage && !instance.getVisibilityChecker().
Terry Wang0be9c302022-01-21 14:36:18 -08001049 doesCallerHaveSystemAccess(packageName)) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001050 throw new AppSearchException(
1051 AppSearchResult.RESULT_SECURITY_ERROR,
1052 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001053 }
1054
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001055 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001056 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001057 usageTimeMillis, systemUsage);
1058 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001059 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001060 } catch (Throwable t) {
1061 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001062 }
Terry Wange04ceab2021-03-29 19:25:12 -07001063 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001064 }
1065
1066 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001067 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001068 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001069 @NonNull String databaseName,
1070 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001071 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001072 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001073 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001074 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001075 Objects.requireNonNull(packageName);
1076 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001077 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001078 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001079 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001080 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001081
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001082 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001083 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001084 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001085 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001086 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001087 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001088 int operationSuccessCount = 0;
1089 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001090 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001091 verifyCaller(callingUid, packageName);
1092
1093 // Obtain the user where the client wants to run the operations in. This should
1094 // end up being the same as userHandle, assuming it is not a special user and
1095 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001096 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001097 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001098
Terry Wange04ceab2021-03-29 19:25:12 -07001099 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1100 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001101 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001102 for (int i = 0; i < ids.size(); i++) {
1103 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001104 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001105 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001106 packageName,
1107 databaseName,
1108 namespace,
1109 id,
1110 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001111 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001112 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001113 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001114 AppSearchResult<Void> result = throwableToFailedResult(t);
1115 resultBuilder.setResult(id, result);
1116 // Since we can only include one status code in the atom,
1117 // for failures, we would just save the one for the last failure
1118 statusCode = result.getResultCode();
1119 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001120 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001121 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001122 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001123 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001124 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001125
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001126 // Schedule a task to dispatch change notifications. See requirements for where
1127 // the method is called documented in the method description.
1128 dispatchChangeNotifications(instance);
1129
Terry Wangf4d219b2021-07-01 19:11:39 -07001130 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001131 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001132 ++operationFailureCount;
1133 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001134 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001135 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001136 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001137 int estimatedBinderLatencyMillis =
1138 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1139 int totalLatencyMillis =
1140 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001141 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001142 .setPackageName(packageName)
1143 .setDatabase(databaseName)
1144 .setStatusCode(statusCode)
1145 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001146 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1147 // TODO(b/173532925) check the existing binder call latency chart
1148 // is good enough for us:
1149 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1150 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1151 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001152 .setNumOperationsFailed(operationFailureCount)
1153 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001154 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001155 }
Terry Wange04ceab2021-03-29 19:25:12 -07001156 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001157 }
1158
1159 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001160 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001161 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001162 @NonNull String databaseName,
1163 @NonNull String queryExpression,
1164 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001165 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001166 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001167 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001168 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001169 Objects.requireNonNull(packageName);
1170 Objects.requireNonNull(databaseName);
1171 Objects.requireNonNull(queryExpression);
1172 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001173 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001174 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001175
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001176 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001177 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001178 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001179 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001180 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001181 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001182 int operationSuccessCount = 0;
1183 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001184 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001185 verifyCaller(callingUid, packageName);
1186
1187 // Obtain the user where the client wants to run the operations in. This should
1188 // end up being the same as userHandle, assuming it is not a special user and
1189 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001190 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001191 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001192
Cassie Wang2feb34d2021-07-22 18:55:19 +00001193 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001194 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001195 packageName,
1196 databaseName,
1197 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001198 new SearchSpec(searchSpecBundle),
1199 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001200 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001201 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001202 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001203 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001204
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001205 // Schedule a task to dispatch change notifications. See requirements for where
1206 // the method is called documented in the method description.
1207 dispatchChangeNotifications(instance);
1208
Terry Wangf4d219b2021-07-01 19:11:39 -07001209 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001210 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001211 ++operationFailureCount;
1212 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001213 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001214 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001215 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001216 int estimatedBinderLatencyMillis =
1217 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1218 int totalLatencyMillis =
1219 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001220 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001221 .setPackageName(packageName)
1222 .setDatabase(databaseName)
1223 .setStatusCode(statusCode)
1224 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001225 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1226 // TODO(b/173532925) check the existing binder call latency chart
1227 // is good enough for us:
1228 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1229 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1230 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001231 .setNumOperationsFailed(operationFailureCount)
1232 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001233 }
Terry Wange04ceab2021-03-29 19:25:12 -07001234 }
1235 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001236 }
1237
Terry Wangdbd1dca2020-11-03 17:03:56 -08001238 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001239 public void getStorageInfo(
1240 @NonNull String packageName,
1241 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001242 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001243 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001244 Objects.requireNonNull(packageName);
1245 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001246 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001247 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001248
Cassie Wang2e2d0552021-08-04 16:18:10 +00001249 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001250 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001251 EXECUTOR.execute(() -> {
1252 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001253 verifyCaller(callingUid, packageName);
1254
1255 // Obtain the user where the client wants to run the operations in. This should
1256 // end up being the same as userHandle, assuming it is not a special user and
1257 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001258 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001259 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001260
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001261 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001262 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001263 StorageInfo storageInfo = instance.getAppSearchImpl()
1264 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001265 Bundle storageInfoBundle = storageInfo.getBundle();
1266 invokeCallbackOnResult(
1267 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1268 } catch (Throwable t) {
1269 invokeCallbackOnError(callback, t);
1270 }
1271 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001272 }
1273
1274 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001275 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001276 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001277 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001278 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001279 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001280 Objects.requireNonNull(userHandle);
1281
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001282 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001283 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001284 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001285 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001286 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001287 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001288 int operationSuccessCount = 0;
1289 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001290 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001291 verifyCaller(callingUid, packageName);
1292
1293 // Obtain the user where the client wants to run the operations in. This should
1294 // end up being the same as userHandle, assuming it is not a special user and
1295 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001296 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001297 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001298
Cassie Wang2feb34d2021-07-22 18:55:19 +00001299 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001300 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001301 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001302 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001303 ++operationFailureCount;
1304 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001305 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001306 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001307 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001308 int estimatedBinderLatencyMillis =
1309 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1310 int totalLatencyMillis =
1311 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001312 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001313 .setStatusCode(statusCode)
1314 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001315 .setCallType(CallStats.CALL_TYPE_FLUSH)
1316 // TODO(b/173532925) check the existing binder call latency chart
1317 // is good enough for us:
1318 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1319 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1320 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001321 .setNumOperationsFailed(operationFailureCount)
1322 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001323 }
Terry Wange04ceab2021-03-29 19:25:12 -07001324 }
1325 });
Terry Wang2da17852020-12-16 19:59:08 -08001326 }
1327
1328 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001329 public AppSearchResultParcel<Void> addObserver(
1330 @NonNull String callingPackage,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001331 @NonNull String targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001332 @NonNull Bundle observerSpecBundle,
1333 @NonNull UserHandle userHandle,
1334 @NonNull IAppSearchObserverProxy observerProxyStub) {
1335 Objects.requireNonNull(callingPackage);
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001336 Objects.requireNonNull(targetPackageName);
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001337 Objects.requireNonNull(observerSpecBundle);
1338 Objects.requireNonNull(userHandle);
1339 Objects.requireNonNull(observerProxyStub);
1340
1341 int callingPid = Binder.getCallingPid();
1342 int callingUid = Binder.getCallingUid();
1343 long callingIdentity = Binder.clearCallingIdentity();
1344
1345 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1346 try {
1347 verifyCaller(callingUid, callingPackage);
1348 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1349 verifyUserUnlocked(targetUser);
1350
1351 AppSearchUserInstance instance =
1352 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1353 instance.getAppSearchImpl().addObserver(
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001354 callingPackage,
1355 callingUid,
1356 instance.getVisibilityChecker().doesCallerHaveSystemAccess(callingPackage),
1357 targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001358 new ObserverSpec(observerSpecBundle),
1359 EXECUTOR,
1360 new AppSearchObserverProxy(observerProxyStub));
1361 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1362 } catch (Throwable t) {
1363 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1364 } finally {
1365 Binder.restoreCallingIdentity(callingIdentity);
1366 }
1367 }
1368
1369 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001370 public AppSearchResultParcel<Void> removeObserver(
1371 @NonNull String callingPackage,
1372 @NonNull String observedPackage,
1373 @NonNull UserHandle userHandle,
1374 @NonNull IAppSearchObserverProxy observerProxyStub) {
1375 Objects.requireNonNull(callingPackage);
1376 Objects.requireNonNull(observedPackage);
1377 Objects.requireNonNull(userHandle);
1378 Objects.requireNonNull(observerProxyStub);
1379
1380 int callingPid = Binder.getCallingPid();
1381 int callingUid = Binder.getCallingUid();
1382 long callingIdentity = Binder.clearCallingIdentity();
1383
1384 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1385 try {
1386 verifyCaller(callingUid, callingPackage);
1387 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1388 verifyUserUnlocked(targetUser);
1389
1390 AppSearchUserInstance instance =
1391 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1392 instance.getAppSearchImpl().removeObserver(
1393 observedPackage,
1394 new AppSearchObserverProxy(observerProxyStub));
1395 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1396 } catch (Throwable t) {
1397 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1398 } finally {
1399 Binder.restoreCallingIdentity(callingIdentity);
1400 }
1401 }
1402
1403 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001404 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001405 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001406 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001407 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1408 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001409 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001410 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001411 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001412
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001413 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001414 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001415 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001416
Terry Wange04ceab2021-03-29 19:25:12 -07001417 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001418 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001419 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001420 int operationSuccessCount = 0;
1421 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001422 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001423 verifyCaller(callingUid, packageName);
1424
1425 // Obtain the user where the client wants to run the operations in. This should
1426 // end up being the same as userHandle, assuming it is not a special user and
1427 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001428 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001429 verifyUserUnlocked(targetUser);
1430
Cassie Wang2feb34d2021-07-22 18:55:19 +00001431 Context targetUserContext = mContext.createContextAsUser(targetUser,
1432 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001433 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001434 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001435 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001436 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1437 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001438 ++operationFailureCount;
1439 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001440 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001441 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001442 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001443 int estimatedBinderLatencyMillis =
1444 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1445 int totalLatencyMillis =
1446 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001447 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001448 .setStatusCode(statusCode)
1449 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001450 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1451 // TODO(b/173532925) check the existing binder call latency chart
1452 // is good enough for us:
1453 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1454 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1455 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001456 .setNumOperationsFailed(operationFailureCount)
1457 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001458 }
Terry Wange04ceab2021-03-29 19:25:12 -07001459 }
1460 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001461 }
1462
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001463 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001464 private void invokeCallbackOnResult(
1465 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001466 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001467 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001468 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001469 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001470 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001471 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001472
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001473 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001474 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001475 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001476 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001477 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001478 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001479 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001480 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001481 }
1482
1483 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001484 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001485 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001486 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001487 */
1488 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001489 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001490 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001491 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001492 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001493 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001494 }
1495 }
1496
1497 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001498 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001499 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001500 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001501 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001502 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001503 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001504 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001505 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001506 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001507 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001508 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001509 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001510 }
Terry Wangfebbead2019-10-17 17:05:18 -07001511 }
Terry Wangf2093072020-11-30 04:47:19 -08001512
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001513 /**
1514 * Helper for dealing with incoming user arguments to system service calls.
1515 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001516 * <p>Takes care of checking permissions and if the target is special user, this method will
1517 * simply throw.
1518 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001519 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001520 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001521 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001522 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001523 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001524 *
1525 * @throws IllegalArgumentException if the target user is a special user.
1526 * @throws SecurityException if caller trying to interact across user without
1527 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001528 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001529 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001530 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1531 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001532 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1533 if (callingUserHandle.equals(targetUserHandle)) {
1534 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001535 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001536
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001537 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001538 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001539 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001540 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001541 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001542
Cassie Wang2e2d0552021-08-04 16:18:10 +00001543 if (mContext.checkPermission(
1544 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1545 callingPid,
1546 callingUid) == PackageManager.PERMISSION_GRANTED) {
1547 return targetUserHandle;
1548 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001549 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001550 "Permission denied while calling from uid " + callingUid
1551 + " with " + targetUserHandle + "; Requires permission: "
1552 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001553 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001554
Cassie Wang84e33a02021-06-18 14:13:31 -07001555 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001556 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001557 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001558 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1559 * @param claimedCallingPackage Package name the caller claims to be.
1560 */
1561 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1562 // Obtain the user where the client is running in. Note that this could be different from
1563 // the userHandle where the client wants to run the AppSearch operation in.
1564 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1565 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1566 /*flags=*/ 0);
1567
1568 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1569 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1570 }
1571
1572 /**
1573 * Check that the caller's supposed package name matches the uid making the call.
1574 *
1575 * @throws SecurityException if the package name and uid don't match.
1576 */
1577 private void verifyCallingPackage(
1578 @NonNull Context actualCallingUserContext,
1579 int actualCallingUid,
1580 @NonNull String claimedCallingPackage) {
1581 int claimedCallingUid = PackageUtil.getPackageUid(
1582 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001583 if (claimedCallingUid != actualCallingUid) {
1584 throw new SecurityException(
1585 "Specified calling package ["
1586 + claimedCallingPackage
1587 + "] does not match the calling uid "
1588 + actualCallingUid);
1589 }
1590 }
1591
1592 /**
1593 * Ensure instant apps can't make calls to AppSearch.
1594 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001595 * @throws SecurityException if the caller is an instant app.
1596 */
1597 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1598 PackageManager callingPackageManager = userContext.getPackageManager();
1599 if (callingPackageManager.isInstantApp(packageName)) {
1600 throw new SecurityException("Caller not allowed to create AppSearch session"
1601 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1602 }
1603 }
1604
Yang Yu0fcd51a2021-04-23 11:25:44 -07001605 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1606 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001607 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001608 @NonNull PackageStats stats,
1609 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001610 @NonNull UserHandle userHandle,
1611 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001612 Objects.requireNonNull(stats);
1613 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001614 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001615
Yang Yu0fcd51a2021-04-23 11:25:44 -07001616 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001617 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001618 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001619 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1620 if (instance == null) {
1621 // augment storage info from file
1622 UserStorageInfo userStorageInfo =
1623 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1624 userHandle);
1625 stats.dataSize +=
1626 userStorageInfo.getSizeBytesForPackage(packageName);
1627 } else {
1628 stats.dataSize += instance.getAppSearchImpl()
1629 .getStorageInfoForPackage(packageName).getSizeBytes();
1630 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001631 } catch (Throwable t) {
1632 Log.e(
1633 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001634 "Unable to augment storage stats for "
1635 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001636 + " packageName "
1637 + packageName,
1638 t);
1639 }
1640 }
1641
1642 @Override
1643 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001644 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001645 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001646
1647 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001648 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001649 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001650 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1651 if (packagesForUid == null) {
1652 return;
1653 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001654 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001655 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1656 if (instance == null) {
1657 // augment storage info from file
1658 UserStorageInfo userStorageInfo =
1659 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1660 userHandle);
1661 for (int i = 0; i < packagesForUid.length; i++) {
1662 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1663 packagesForUid[i]);
1664 }
1665 } else {
1666 for (int i = 0; i < packagesForUid.length; i++) {
1667 stats.dataSize += instance.getAppSearchImpl()
1668 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1669 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001670 }
1671 } catch (Throwable t) {
1672 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1673 }
1674 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001675
1676 @Override
1677 public void augmentStatsForUser(
1678 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1679 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1680 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1681 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1682 Objects.requireNonNull(stats);
1683 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001684
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001685 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001686 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001687 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001688 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1689 if (instance == null) {
1690 // augment storage info from file
1691 UserStorageInfo userStorageInfo =
1692 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1693 userHandle);
1694 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1695 } else {
1696 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1697 /*flags=*/0, userHandle.getIdentifier());
1698 if (packagesForUser != null) {
1699 for (int i = 0; i < packagesForUser.size(); i++) {
1700 String packageName = packagesForUser.get(i).packageName;
1701 stats.dataSize += instance.getAppSearchImpl()
1702 .getStorageInfoForPackage(packageName).getSizeBytes();
1703 }
1704 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001705 }
1706 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001707 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001708 }
1709 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001710 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001711
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001712 /**
1713 * Dispatches change notifications if there are any to dispatch.
1714 *
1715 * <p>This method is async; notifications are dispatched onto their own registered executors.
1716 *
1717 * <p>IMPORTANT: You must always call this within the background task that contains the
1718 * operation that mutated the index. If you called it outside of that task, it could start
1719 * before the task completes, causing notifications to be missed.
1720 */
1721 @WorkerThread
1722 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1723 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1724 }
1725
1726 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001727 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1728 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001729 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1730 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001731 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001732 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001733 } catch (AppSearchException e) {
1734 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001735 } finally {
1736 OptimizeStats oStats = builder
1737 .setTotalLatencyMillis(
1738 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1739 .build();
1740 if (oStats.getOriginalDocumentCount() > 0) {
1741 // see if optimize has been run by checking originalDocumentCount
1742 instance.getLogger().logStats(oStats);
1743 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001744 }
1745 });
1746 }
1747
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001748 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001749 private void checkForOptimize(AppSearchUserInstance instance) {
1750 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001751 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1752 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001753 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001754 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001755 } catch (AppSearchException e) {
1756 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001757 } finally {
1758 OptimizeStats oStats = builder
1759 .setTotalLatencyMillis(
1760 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1761 .build();
1762 if (oStats.getOriginalDocumentCount() > 0) {
1763 // see if optimize has been run by checking originalDocumentCount
1764 instance.getLogger().logStats(oStats);
1765 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001766 }
1767 });
1768 }
Terry Wangfebbead2019-10-17 17:05:18 -07001769}