blob: 9699b72fab4f9eef15479f35f66ef74551ab9c58 [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(
438 callingPackageName, packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -0700439 invokeCallbackOnResult(
440 callback,
441 AppSearchResult.newSuccessfulResult(response.getBundle()));
442 } catch (Throwable t) {
443 invokeCallbackOnError(callback, t);
444 }
445 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700446 }
447
448 @Override
449 public void getNamespaces(
450 @NonNull String packageName,
451 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700452 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700453 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700454 Objects.requireNonNull(packageName);
455 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700456 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700457 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700458
Cassie Wang2e2d0552021-08-04 16:18:10 +0000459 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700460 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700461 EXECUTOR.execute(() -> {
462 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000463 verifyCaller(callingUid, packageName);
464
465 // Obtain the user where the client wants to run the operations in. This should
466 // end up being the same as userHandle, assuming it is not a special user and
467 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000468 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000469 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000470
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700471 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000472 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700473 List<String> namespaces =
474 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
475 invokeCallbackOnResult(
476 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700477 } catch (Throwable t) {
478 invokeCallbackOnError(callback, t);
479 }
480 });
Terry Wang83a24932020-12-09 21:00:18 -0800481 }
482
483 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800484 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800485 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700486 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700487 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700488 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800489 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800490 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700491 Objects.requireNonNull(packageName);
492 Objects.requireNonNull(databaseName);
493 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700494 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700495 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700496
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700497 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000498 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800499 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700500 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800501 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700502 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800503 int operationSuccessCount = 0;
504 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700505 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000506 verifyCaller(callingUid, packageName);
507
508 // Obtain the user where the client wants to run the operations in. This should
509 // end up being the same as userHandle, assuming it is not a special user and
510 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000511 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000512 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000513
Terry Wange04ceab2021-03-29 19:25:12 -0700514 AppSearchBatchResult.Builder<String, Void> resultBuilder =
515 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000516 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700517 for (int i = 0; i < documentBundles.size(); i++) {
518 GenericDocument document = new GenericDocument(documentBundles.get(i));
519 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700520 instance.getAppSearchImpl().putDocument(
521 packageName, databaseName, document, instance.getLogger());
522 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800523 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700524 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700525 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800526 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700527 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700528 // Since we can only include one status code in the atom,
529 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800530 statusCode = result.getResultCode();
531 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700532 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800533 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700534 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700535 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700536 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700537
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800538 // Schedule a task to dispatch change notifications. See requirements for where
539 // the method is called documented in the method description.
540 dispatchChangeNotifications(instance);
541
Terry Wangf4d219b2021-07-01 19:11:39 -0700542 // The existing documents with same ID will be deleted, so there may be some
543 // resources that could be released after optimize().
544 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700545 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700546 ++operationFailureCount;
547 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700548 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800549 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700550 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700551 int estimatedBinderLatencyMillis =
552 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
553 int totalLatencyMillis =
554 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700555 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700556 .setPackageName(packageName)
557 .setDatabase(databaseName)
558 .setStatusCode(statusCode)
559 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800560 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
561 // TODO(b/173532925) check the existing binder call latency chart
562 // is good enough for us:
563 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700564 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800565 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700566 .setNumOperationsFailed(operationFailureCount)
567 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800568 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800569 }
Terry Wange04ceab2021-03-29 19:25:12 -0700570 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800571 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800572
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800573 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800574 public void getDocuments(
Alex Saveliev87631932022-01-21 00:48:44 +0000575 @NonNull String callingPackageName,
576 @NonNull String targetPackageName,
Terry Wangf2093072020-11-30 04:47:19 -0800577 @NonNull String databaseName,
578 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700579 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800580 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700581 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700582 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alex Saveliev87631932022-01-21 00:48:44 +0000583 boolean global,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800584 @NonNull IAppSearchBatchResultCallback callback) {
Alex Saveliev87631932022-01-21 00:48:44 +0000585 Objects.requireNonNull(callingPackageName);
586 Objects.requireNonNull(targetPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700587 Objects.requireNonNull(databaseName);
588 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700589 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700590 Objects.requireNonNull(typePropertyPaths);
591 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700592 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700593
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700594 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000595 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800596 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700597 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700598 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700599 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700600 int operationSuccessCount = 0;
601 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700602 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000603 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000604
605 // Obtain the user where the client wants to run the operations in. This should
606 // end up being the same as userHandle, assuming it is not a special user and
607 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000608 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000609 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000610
Terry Wange04ceab2021-03-29 19:25:12 -0700611 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
612 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000613 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700614 for (int i = 0; i < ids.size(); i++) {
615 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700616 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000617 GenericDocument document;
618 if (global) {
619 // TODO(b/203819101) add test to try out security by binding
620 // directly to binder and passing callingpackage param
621 document = instance.getAppSearchImpl().globalGetDocument(
622 targetPackageName,
623 databaseName,
624 namespace,
625 id,
626 typePropertyPaths,
627 callingUid,
628 instance.getVisibilityCheckImpl()
629 .doesCallerHaveSystemAccess(callingPackageName));
630 } else {
631 document = instance.getAppSearchImpl().getDocument(
632 targetPackageName,
633 databaseName,
634 namespace,
635 id,
636 typePropertyPaths);
637 }
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700638 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700639 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700640 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700641 // Since we can only include one status code in the atom,
642 // for failures, we would just save the one for the last failure
643 AppSearchResult<Bundle> result = throwableToFailedResult(t);
644 resultBuilder.setResult(id, result);
645 statusCode = result.getResultCode();
646 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700647 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800648 }
Terry Wange04ceab2021-03-29 19:25:12 -0700649 invokeCallbackOnResult(callback, resultBuilder.build());
650 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700651 ++operationFailureCount;
652 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700653 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700654 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700655 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700656 int estimatedBinderLatencyMillis =
657 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
658 int totalLatencyMillis =
659 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700660 instance.getLogger().logStats(new CallStats.Builder()
Alex Saveliev87631932022-01-21 00:48:44 +0000661 .setPackageName(targetPackageName)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700662 .setDatabase(databaseName)
663 .setStatusCode(statusCode)
664 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700665 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
Alex Saveliev87631932022-01-21 00:48:44 +0000666 // TODO(b/203819101) need mark the call as a global getById
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700667 // TODO(b/173532925) check the existing binder call latency chart
668 // is good enough for us:
669 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
670 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
671 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700672 .setNumOperationsFailed(operationFailureCount)
673 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700674 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800675 }
Terry Wange04ceab2021-03-29 19:25:12 -0700676 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800677 }
678
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800679 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800680 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800681 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700682 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700683 @NonNull String queryExpression,
684 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700685 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700686 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700687 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700688 Objects.requireNonNull(packageName);
689 Objects.requireNonNull(databaseName);
690 Objects.requireNonNull(queryExpression);
691 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700692 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700693 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700694
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700695 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000696 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800697 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700698 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700699 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700700 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700701 int operationSuccessCount = 0;
702 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700703 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000704 verifyCaller(callingUid, packageName);
705
706 // Obtain the user where the client wants to run the operations in. This should
707 // end up being the same as userHandle, assuming it is not a special user and
708 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000709 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000710 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000711
Cassie Wang2feb34d2021-07-22 18:55:19 +0000712 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700713 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
714 packageName,
715 databaseName,
716 queryExpression,
717 new SearchSpec(searchSpecBundle),
718 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700719 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700720 invokeCallbackOnResult(
721 callback,
722 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
723 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700724 ++operationFailureCount;
725 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700726 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700727 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700728 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700729 int estimatedBinderLatencyMillis =
730 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
731 int totalLatencyMillis =
732 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700733 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700734 .setPackageName(packageName)
735 .setDatabase(databaseName)
736 .setStatusCode(statusCode)
737 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700738 .setCallType(CallStats.CALL_TYPE_SEARCH)
739 // TODO(b/173532925) check the existing binder call latency chart
740 // is good enough for us:
741 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
742 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
743 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700744 .setNumOperationsFailed(operationFailureCount)
745 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700746 }
Terry Wange04ceab2021-03-29 19:25:12 -0700747 }
748 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700749 }
750
Terry Wangf2093072020-11-30 04:47:19 -0800751 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800752 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800753 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800754 @NonNull String queryExpression,
755 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700756 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700757 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800758 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700759 Objects.requireNonNull(packageName);
760 Objects.requireNonNull(queryExpression);
761 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700762 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700763 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700764
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700765 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000766 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800767 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700768 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700769 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700770 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700771 int operationSuccessCount = 0;
772 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700773 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000774 verifyCaller(callingUid, packageName);
775
776 // Obtain the user where the client wants to run the operations in. This should
777 // end up being the same as userHandle, assuming it is not a special user and
778 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000779 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000780 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000781
Cassie Wang2feb34d2021-07-22 18:55:19 +0000782 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700783
Terry Wang0be9c302022-01-21 14:36:18 -0800784 boolean callerHasSystemAccess = instance.getVisibilityCheckImpl()
785 .doesCallerHaveSystemAccess(packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700786 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
787 queryExpression,
788 new SearchSpec(searchSpecBundle),
789 packageName,
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700790 callingUid,
791 callerHasSystemAccess,
792 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700793 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700794 invokeCallbackOnResult(
795 callback,
796 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700797 } catch (Throwable t) {
798 ++operationFailureCount;
799 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700800 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700801 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700802 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700803 int estimatedBinderLatencyMillis =
804 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
805 int totalLatencyMillis =
806 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700807 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700808 .setPackageName(packageName)
809 .setStatusCode(statusCode)
810 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700811 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
812 // TODO(b/173532925) check the existing binder call latency chart
813 // is good enough for us:
814 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
815 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
816 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700817 .setNumOperationsFailed(operationFailureCount)
818 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700819 }
Terry Wange04ceab2021-03-29 19:25:12 -0700820 }
821 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800822 }
823
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700824 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800825 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700826 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800827 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700828 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700829 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700830 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700831 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700832 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700833
Cassie Wang2e2d0552021-08-04 16:18:10 +0000834 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800835 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700836 EXECUTOR.execute(() -> {
837 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000838 verifyCaller(callingUid, packageName);
839
840 // Obtain the user where the client wants to run the operations in. This should
841 // end up being the same as userHandle, assuming it is not a special user and
842 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000843 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000844 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000845
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700846 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000847 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700848 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700849 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700850 instance.getAppSearchImpl().getNextPage(
851 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700852 invokeCallbackOnResult(
853 callback,
854 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
855 } catch (Throwable t) {
856 invokeCallbackOnError(callback, t);
857 }
858 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700859 }
860
861 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700862 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
863 @NonNull UserHandle userHandle) {
864 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700865 Objects.requireNonNull(userHandle);
866
Cassie Wang2e2d0552021-08-04 16:18:10 +0000867 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800868 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700869 EXECUTOR.execute(() -> {
870 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000871 verifyCaller(callingUid, packageName);
872
873 // Obtain the user where the client wants to run the operations in. This should
874 // end up being the same as userHandle, assuming it is not a special user and
875 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000876 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000877 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000878
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700879 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000880 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700881 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700882 } catch (Throwable t) {
883 Log.e(TAG, "Unable to invalidate the query page token", t);
884 }
885 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800886 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800887
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700888 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800889 public void writeQueryResultsToFile(
890 @NonNull String packageName,
891 @NonNull String databaseName,
892 @NonNull ParcelFileDescriptor fileDescriptor,
893 @NonNull String queryExpression,
894 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700895 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800896 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700897 Objects.requireNonNull(packageName);
898 Objects.requireNonNull(databaseName);
899 Objects.requireNonNull(fileDescriptor);
900 Objects.requireNonNull(queryExpression);
901 Objects.requireNonNull(searchSpecBundle);
902 Objects.requireNonNull(userHandle);
903 Objects.requireNonNull(callback);
904
Cassie Wang2e2d0552021-08-04 16:18:10 +0000905 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800906 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700907 EXECUTOR.execute(() -> {
908 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000909 verifyCaller(callingUid, packageName);
910
911 // Obtain the user where the client wants to run the operations in. This should
912 // end up being the same as userHandle, assuming it is not a special user and
913 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000914 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000915 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000916
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700917 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000918 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700919 // we don't need to append the file. The file is always brand new.
920 try (DataOutputStream outputStream = new DataOutputStream(
921 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700922 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700923 packageName,
924 databaseName,
925 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700926 new SearchSpec(searchSpecBundle),
927 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700928 while (!searchResultPage.getResults().isEmpty()) {
929 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
930 AppSearchMigrationHelper.writeBundleToOutputStream(
931 outputStream, searchResultPage.getResults().get(i)
932 .getGenericDocument().getBundle());
933 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700934 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700935 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700936 packageName,
937 searchResultPage.getNextPageToken(),
938 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800939 }
Terry Wang623e3b02021-02-02 20:27:33 -0800940 }
Terry Wange04ceab2021-03-29 19:25:12 -0700941 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
942 } catch (Throwable t) {
943 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800944 }
Terry Wange04ceab2021-03-29 19:25:12 -0700945 });
Terry Wang623e3b02021-02-02 20:27:33 -0800946 }
947
948 @Override
949 public void putDocumentsFromFile(
950 @NonNull String packageName,
951 @NonNull String databaseName,
952 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700953 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800954 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700955 Objects.requireNonNull(packageName);
956 Objects.requireNonNull(databaseName);
957 Objects.requireNonNull(fileDescriptor);
958 Objects.requireNonNull(userHandle);
959 Objects.requireNonNull(callback);
960
Cassie Wang2e2d0552021-08-04 16:18:10 +0000961 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800962 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700963 EXECUTOR.execute(() -> {
964 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000965 verifyCaller(callingUid, packageName);
966
967 // Obtain the user where the client wants to run the operations in. This should
968 // end up being the same as userHandle, assuming it is not a special user and
969 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000970 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000971 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000972
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700973 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000974 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800975
Terry Wange04ceab2021-03-29 19:25:12 -0700976 GenericDocument document;
977 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
978 try (DataInputStream inputStream = new DataInputStream(
979 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
980 while (true) {
981 try {
982 document = AppSearchMigrationHelper
983 .readDocumentFromInputStream(inputStream);
984 } catch (EOFException e) {
985 // nothing wrong, we just finish the reading.
986 break;
987 }
988 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700989 instance.getAppSearchImpl().putDocument(
990 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700991 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700992 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
993 document.getNamespace(),
994 document.getId(),
995 document.getSchemaType(),
996 AppSearchResult.throwableToFailedResult(t))
997 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700998 }
Terry Wang623e3b02021-02-02 20:27:33 -0800999 }
1000 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001001 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -07001002 invokeCallbackOnResult(callback,
1003 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
1004 } catch (Throwable t) {
1005 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -08001006 }
Terry Wange04ceab2021-03-29 19:25:12 -07001007 });
Terry Wang623e3b02021-02-02 20:27:33 -08001008 }
1009
1010 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001011 public void reportUsage(
1012 @NonNull String packageName,
1013 @NonNull String databaseName,
1014 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001015 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001016 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001017 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001018 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001019 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001020 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001021 Objects.requireNonNull(databaseName);
1022 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001023 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001024 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001025 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001026
Cassie Wang2e2d0552021-08-04 16:18:10 +00001027 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001028 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001029 EXECUTOR.execute(() -> {
1030 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001031 verifyCaller(callingUid, packageName);
1032
1033 // Obtain the user where the client wants to run the operations in. This should
1034 // end up being the same as userHandle, assuming it is not a special user and
1035 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001036 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001037 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001038
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001039 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001040 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001041
Terry Wang0be9c302022-01-21 14:36:18 -08001042 if (systemUsage && !instance.getVisibilityCheckImpl().
1043 doesCallerHaveSystemAccess(packageName)) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001044 throw new AppSearchException(
1045 AppSearchResult.RESULT_SECURITY_ERROR,
1046 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001047 }
1048
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001049 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001050 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001051 usageTimeMillis, systemUsage);
1052 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001053 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001054 } catch (Throwable t) {
1055 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001056 }
Terry Wange04ceab2021-03-29 19:25:12 -07001057 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001058 }
1059
1060 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001061 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001062 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001063 @NonNull String databaseName,
1064 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001065 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001066 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001067 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001068 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001069 Objects.requireNonNull(packageName);
1070 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001071 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001072 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001073 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001074 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001075
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001076 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001077 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001078 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001079 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001080 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001081 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001082 int operationSuccessCount = 0;
1083 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001084 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001085 verifyCaller(callingUid, packageName);
1086
1087 // Obtain the user where the client wants to run the operations in. This should
1088 // end up being the same as userHandle, assuming it is not a special user and
1089 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001090 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001091 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001092
Terry Wange04ceab2021-03-29 19:25:12 -07001093 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1094 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001095 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001096 for (int i = 0; i < ids.size(); i++) {
1097 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001098 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001099 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001100 packageName,
1101 databaseName,
1102 namespace,
1103 id,
1104 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001105 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001106 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001107 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001108 AppSearchResult<Void> result = throwableToFailedResult(t);
1109 resultBuilder.setResult(id, result);
1110 // Since we can only include one status code in the atom,
1111 // for failures, we would just save the one for the last failure
1112 statusCode = result.getResultCode();
1113 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001114 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001115 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001116 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001117 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001118 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001119
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001120 // Schedule a task to dispatch change notifications. See requirements for where
1121 // the method is called documented in the method description.
1122 dispatchChangeNotifications(instance);
1123
Terry Wangf4d219b2021-07-01 19:11:39 -07001124 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001125 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001126 ++operationFailureCount;
1127 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001128 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001129 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001130 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001131 int estimatedBinderLatencyMillis =
1132 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1133 int totalLatencyMillis =
1134 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001135 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001136 .setPackageName(packageName)
1137 .setDatabase(databaseName)
1138 .setStatusCode(statusCode)
1139 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001140 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1141 // TODO(b/173532925) check the existing binder call latency chart
1142 // is good enough for us:
1143 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1144 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1145 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001146 .setNumOperationsFailed(operationFailureCount)
1147 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001148 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001149 }
Terry Wange04ceab2021-03-29 19:25:12 -07001150 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001151 }
1152
1153 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001154 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001155 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001156 @NonNull String databaseName,
1157 @NonNull String queryExpression,
1158 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001159 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001160 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001161 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001162 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001163 Objects.requireNonNull(packageName);
1164 Objects.requireNonNull(databaseName);
1165 Objects.requireNonNull(queryExpression);
1166 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001167 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001168 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001169
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001170 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001171 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001172 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001173 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001174 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001175 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001176 int operationSuccessCount = 0;
1177 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001178 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001179 verifyCaller(callingUid, packageName);
1180
1181 // Obtain the user where the client wants to run the operations in. This should
1182 // end up being the same as userHandle, assuming it is not a special user and
1183 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001184 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001185 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001186
Cassie Wang2feb34d2021-07-22 18:55:19 +00001187 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001188 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001189 packageName,
1190 databaseName,
1191 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001192 new SearchSpec(searchSpecBundle),
1193 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001194 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001195 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001196 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001197 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001198
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001199 // Schedule a task to dispatch change notifications. See requirements for where
1200 // the method is called documented in the method description.
1201 dispatchChangeNotifications(instance);
1202
Terry Wangf4d219b2021-07-01 19:11:39 -07001203 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001204 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001205 ++operationFailureCount;
1206 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001207 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001208 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001209 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001210 int estimatedBinderLatencyMillis =
1211 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1212 int totalLatencyMillis =
1213 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001214 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001215 .setPackageName(packageName)
1216 .setDatabase(databaseName)
1217 .setStatusCode(statusCode)
1218 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001219 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1220 // TODO(b/173532925) check the existing binder call latency chart
1221 // is good enough for us:
1222 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1223 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1224 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001225 .setNumOperationsFailed(operationFailureCount)
1226 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001227 }
Terry Wange04ceab2021-03-29 19:25:12 -07001228 }
1229 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001230 }
1231
Terry Wangdbd1dca2020-11-03 17:03:56 -08001232 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001233 public void getStorageInfo(
1234 @NonNull String packageName,
1235 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001236 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001237 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001238 Objects.requireNonNull(packageName);
1239 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001240 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001241 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001242
Cassie Wang2e2d0552021-08-04 16:18:10 +00001243 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001244 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001245 EXECUTOR.execute(() -> {
1246 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001247 verifyCaller(callingUid, packageName);
1248
1249 // Obtain the user where the client wants to run the operations in. This should
1250 // end up being the same as userHandle, assuming it is not a special user and
1251 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001252 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001253 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001254
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001255 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001256 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001257 StorageInfo storageInfo = instance.getAppSearchImpl()
1258 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001259 Bundle storageInfoBundle = storageInfo.getBundle();
1260 invokeCallbackOnResult(
1261 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1262 } catch (Throwable t) {
1263 invokeCallbackOnError(callback, t);
1264 }
1265 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001266 }
1267
1268 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001269 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001270 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001271 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001272 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001273 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001274 Objects.requireNonNull(userHandle);
1275
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001276 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001277 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001278 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001279 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001280 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001281 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001282 int operationSuccessCount = 0;
1283 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001284 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001285 verifyCaller(callingUid, packageName);
1286
1287 // Obtain the user where the client wants to run the operations in. This should
1288 // end up being the same as userHandle, assuming it is not a special user and
1289 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001290 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001291 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001292
Cassie Wang2feb34d2021-07-22 18:55:19 +00001293 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001294 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001295 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001296 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001297 ++operationFailureCount;
1298 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001299 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001300 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001301 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001302 int estimatedBinderLatencyMillis =
1303 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1304 int totalLatencyMillis =
1305 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001306 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001307 .setStatusCode(statusCode)
1308 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001309 .setCallType(CallStats.CALL_TYPE_FLUSH)
1310 // TODO(b/173532925) check the existing binder call latency chart
1311 // is good enough for us:
1312 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1313 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1314 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001315 .setNumOperationsFailed(operationFailureCount)
1316 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001317 }
Terry Wange04ceab2021-03-29 19:25:12 -07001318 }
1319 });
Terry Wang2da17852020-12-16 19:59:08 -08001320 }
1321
1322 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001323 public AppSearchResultParcel<Void> addObserver(
1324 @NonNull String callingPackage,
1325 @NonNull String observedPackage,
1326 @NonNull Bundle observerSpecBundle,
1327 @NonNull UserHandle userHandle,
1328 @NonNull IAppSearchObserverProxy observerProxyStub) {
1329 Objects.requireNonNull(callingPackage);
1330 Objects.requireNonNull(observedPackage);
1331 Objects.requireNonNull(observerSpecBundle);
1332 Objects.requireNonNull(userHandle);
1333 Objects.requireNonNull(observerProxyStub);
1334
1335 int callingPid = Binder.getCallingPid();
1336 int callingUid = Binder.getCallingUid();
1337 long callingIdentity = Binder.clearCallingIdentity();
1338
1339 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1340 try {
1341 verifyCaller(callingUid, callingPackage);
1342 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1343 verifyUserUnlocked(targetUser);
1344
1345 AppSearchUserInstance instance =
1346 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1347 instance.getAppSearchImpl().addObserver(
1348 observedPackage,
1349 new ObserverSpec(observerSpecBundle),
1350 EXECUTOR,
1351 new AppSearchObserverProxy(observerProxyStub));
1352 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1353 } catch (Throwable t) {
1354 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1355 } finally {
1356 Binder.restoreCallingIdentity(callingIdentity);
1357 }
1358 }
1359
1360 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001361 public AppSearchResultParcel<Void> removeObserver(
1362 @NonNull String callingPackage,
1363 @NonNull String observedPackage,
1364 @NonNull UserHandle userHandle,
1365 @NonNull IAppSearchObserverProxy observerProxyStub) {
1366 Objects.requireNonNull(callingPackage);
1367 Objects.requireNonNull(observedPackage);
1368 Objects.requireNonNull(userHandle);
1369 Objects.requireNonNull(observerProxyStub);
1370
1371 int callingPid = Binder.getCallingPid();
1372 int callingUid = Binder.getCallingUid();
1373 long callingIdentity = Binder.clearCallingIdentity();
1374
1375 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1376 try {
1377 verifyCaller(callingUid, callingPackage);
1378 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1379 verifyUserUnlocked(targetUser);
1380
1381 AppSearchUserInstance instance =
1382 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1383 instance.getAppSearchImpl().removeObserver(
1384 observedPackage,
1385 new AppSearchObserverProxy(observerProxyStub));
1386 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1387 } catch (Throwable t) {
1388 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1389 } finally {
1390 Binder.restoreCallingIdentity(callingIdentity);
1391 }
1392 }
1393
1394 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001395 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001396 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001397 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001398 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1399 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001400 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001401 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001402 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001403
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001404 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001405 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001406 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001407
Terry Wange04ceab2021-03-29 19:25:12 -07001408 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001409 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001410 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001411 int operationSuccessCount = 0;
1412 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001413 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001414 verifyCaller(callingUid, packageName);
1415
1416 // Obtain the user where the client wants to run the operations in. This should
1417 // end up being the same as userHandle, assuming it is not a special user and
1418 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001419 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001420 verifyUserUnlocked(targetUser);
1421
Cassie Wang2feb34d2021-07-22 18:55:19 +00001422 Context targetUserContext = mContext.createContextAsUser(targetUser,
1423 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001424 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001425 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001426 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001427 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1428 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001429 ++operationFailureCount;
1430 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001431 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001432 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001433 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001434 int estimatedBinderLatencyMillis =
1435 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1436 int totalLatencyMillis =
1437 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001438 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001439 .setStatusCode(statusCode)
1440 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001441 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1442 // TODO(b/173532925) check the existing binder call latency chart
1443 // is good enough for us:
1444 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1445 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1446 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001447 .setNumOperationsFailed(operationFailureCount)
1448 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001449 }
Terry Wange04ceab2021-03-29 19:25:12 -07001450 }
1451 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001452 }
1453
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001454 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001455 private void invokeCallbackOnResult(
1456 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001457 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001458 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001459 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001460 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001461 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001462 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001463
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001464 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001465 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001466 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001467 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001468 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001469 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001470 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001471 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001472 }
1473
1474 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001475 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001476 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001477 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001478 */
1479 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001480 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001481 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001482 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001483 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001484 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001485 }
1486 }
1487
1488 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001489 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001490 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001491 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001492 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001493 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001494 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001495 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001496 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001497 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001498 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001499 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001500 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001501 }
Terry Wangfebbead2019-10-17 17:05:18 -07001502 }
Terry Wangf2093072020-11-30 04:47:19 -08001503
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001504 /**
1505 * Helper for dealing with incoming user arguments to system service calls.
1506 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001507 * <p>Takes care of checking permissions and if the target is special user, this method will
1508 * simply throw.
1509 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001510 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001511 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001512 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001513 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001514 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001515 *
1516 * @throws IllegalArgumentException if the target user is a special user.
1517 * @throws SecurityException if caller trying to interact across user without
1518 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001519 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001520 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001521 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1522 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001523 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1524 if (callingUserHandle.equals(targetUserHandle)) {
1525 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001526 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001527
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001528 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001529 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001530 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001531 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001532 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001533
Cassie Wang2e2d0552021-08-04 16:18:10 +00001534 if (mContext.checkPermission(
1535 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1536 callingPid,
1537 callingUid) == PackageManager.PERMISSION_GRANTED) {
1538 return targetUserHandle;
1539 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001540 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001541 "Permission denied while calling from uid " + callingUid
1542 + " with " + targetUserHandle + "; Requires permission: "
1543 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001544 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001545
Cassie Wang84e33a02021-06-18 14:13:31 -07001546 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001547 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001548 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001549 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1550 * @param claimedCallingPackage Package name the caller claims to be.
1551 */
1552 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1553 // Obtain the user where the client is running in. Note that this could be different from
1554 // the userHandle where the client wants to run the AppSearch operation in.
1555 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1556 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1557 /*flags=*/ 0);
1558
1559 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1560 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1561 }
1562
1563 /**
1564 * Check that the caller's supposed package name matches the uid making the call.
1565 *
1566 * @throws SecurityException if the package name and uid don't match.
1567 */
1568 private void verifyCallingPackage(
1569 @NonNull Context actualCallingUserContext,
1570 int actualCallingUid,
1571 @NonNull String claimedCallingPackage) {
1572 int claimedCallingUid = PackageUtil.getPackageUid(
1573 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001574 if (claimedCallingUid != actualCallingUid) {
1575 throw new SecurityException(
1576 "Specified calling package ["
1577 + claimedCallingPackage
1578 + "] does not match the calling uid "
1579 + actualCallingUid);
1580 }
1581 }
1582
1583 /**
1584 * Ensure instant apps can't make calls to AppSearch.
1585 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001586 * @throws SecurityException if the caller is an instant app.
1587 */
1588 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1589 PackageManager callingPackageManager = userContext.getPackageManager();
1590 if (callingPackageManager.isInstantApp(packageName)) {
1591 throw new SecurityException("Caller not allowed to create AppSearch session"
1592 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1593 }
1594 }
1595
Yang Yu0fcd51a2021-04-23 11:25:44 -07001596 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1597 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001598 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001599 @NonNull PackageStats stats,
1600 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001601 @NonNull UserHandle userHandle,
1602 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001603 Objects.requireNonNull(stats);
1604 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001605 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001606
Yang Yu0fcd51a2021-04-23 11:25:44 -07001607 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001608 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001609 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001610 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1611 if (instance == null) {
1612 // augment storage info from file
1613 UserStorageInfo userStorageInfo =
1614 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1615 userHandle);
1616 stats.dataSize +=
1617 userStorageInfo.getSizeBytesForPackage(packageName);
1618 } else {
1619 stats.dataSize += instance.getAppSearchImpl()
1620 .getStorageInfoForPackage(packageName).getSizeBytes();
1621 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001622 } catch (Throwable t) {
1623 Log.e(
1624 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001625 "Unable to augment storage stats for "
1626 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001627 + " packageName "
1628 + packageName,
1629 t);
1630 }
1631 }
1632
1633 @Override
1634 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001635 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001636 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001637
1638 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001639 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001640 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001641 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1642 if (packagesForUid == null) {
1643 return;
1644 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001645 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001646 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1647 if (instance == null) {
1648 // augment storage info from file
1649 UserStorageInfo userStorageInfo =
1650 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1651 userHandle);
1652 for (int i = 0; i < packagesForUid.length; i++) {
1653 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1654 packagesForUid[i]);
1655 }
1656 } else {
1657 for (int i = 0; i < packagesForUid.length; i++) {
1658 stats.dataSize += instance.getAppSearchImpl()
1659 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1660 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001661 }
1662 } catch (Throwable t) {
1663 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1664 }
1665 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001666
1667 @Override
1668 public void augmentStatsForUser(
1669 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1670 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1671 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1672 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1673 Objects.requireNonNull(stats);
1674 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001675
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001676 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001677 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001678 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001679 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1680 if (instance == null) {
1681 // augment storage info from file
1682 UserStorageInfo userStorageInfo =
1683 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1684 userHandle);
1685 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1686 } else {
1687 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1688 /*flags=*/0, userHandle.getIdentifier());
1689 if (packagesForUser != null) {
1690 for (int i = 0; i < packagesForUser.size(); i++) {
1691 String packageName = packagesForUser.get(i).packageName;
1692 stats.dataSize += instance.getAppSearchImpl()
1693 .getStorageInfoForPackage(packageName).getSizeBytes();
1694 }
1695 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001696 }
1697 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001698 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001699 }
1700 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001701 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001702
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001703 /**
1704 * Dispatches change notifications if there are any to dispatch.
1705 *
1706 * <p>This method is async; notifications are dispatched onto their own registered executors.
1707 *
1708 * <p>IMPORTANT: You must always call this within the background task that contains the
1709 * operation that mutated the index. If you called it outside of that task, it could start
1710 * before the task completes, causing notifications to be missed.
1711 */
1712 @WorkerThread
1713 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1714 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1715 }
1716
1717 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001718 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1719 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001720 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1721 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001722 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001723 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001724 } catch (AppSearchException e) {
1725 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001726 } finally {
1727 OptimizeStats oStats = builder
1728 .setTotalLatencyMillis(
1729 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1730 .build();
1731 if (oStats.getOriginalDocumentCount() > 0) {
1732 // see if optimize has been run by checking originalDocumentCount
1733 instance.getLogger().logStats(oStats);
1734 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001735 }
1736 });
1737 }
1738
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001739 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001740 private void checkForOptimize(AppSearchUserInstance instance) {
1741 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001742 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1743 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001744 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001745 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001746 } catch (AppSearchException e) {
1747 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001748 } finally {
1749 OptimizeStats oStats = builder
1750 .setTotalLatencyMillis(
1751 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1752 .build();
1753 if (oStats.getOriginalDocumentCount() > 0) {
1754 // see if optimize has been run by checking originalDocumentCount
1755 instance.getLogger().logStats(oStats);
1756 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001757 }
1758 });
1759 }
Terry Wangfebbead2019-10-17 17:05:18 -07001760}