blob: 375e7bde4d8616312750acea0145510972c024e6 [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 Dorokhine72f5e372022-02-07 17:23:49 -080066import com.android.server.appsearch.external.localstorage.visibilitystore.CallerAccess;
Alexander Dorokhine44c04972021-06-22 12:32:15 -070067import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore;
Alexander Dorokhinee0587d32021-12-07 17:02:17 -080068import com.android.server.appsearch.observer.AppSearchObserverProxy;
Xiaoyu Jin10329472021-06-23 16:50:03 -070069import com.android.server.appsearch.stats.StatsCollector;
Alexander Dorokhine5c416772021-06-04 09:05:00 -070070import com.android.server.appsearch.util.PackageUtil;
Alexander Dorokhine655aec02022-02-07 17:24:01 -080071import com.android.server.appsearch.visibilitystore.FrameworkCallerAccess;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070072import com.android.server.usage.StorageStatsManagerLocal;
73import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080074
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070075import com.google.android.icing.proto.PersistType;
76
Terry Wang623e3b02021-02-02 20:27:33 -080077import java.io.DataInputStream;
78import java.io.DataOutputStream;
79import java.io.EOFException;
80import java.io.FileInputStream;
81import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080082import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080083import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080084import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080085import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080086import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070087import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070088import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070089import java.util.concurrent.ThreadPoolExecutor;
90import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080091
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070092/**
93 * The main service implementation which contains AppSearch's platform functionality.
Yang Yuc047f7b2021-06-25 12:22:42 -070094 *
Alexander Dorokhine5d2bb0b2021-06-24 22:58:46 -070095 * @hide
96 */
Terry Wangfebbead2019-10-17 17:05:18 -070097public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070098 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070099 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700100 private PackageManager mPackageManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700101 private UserManager mUserManager;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700102 private AppSearchUserInstanceManager mAppSearchUserInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -0700103
Terry Wange04ceab2021-03-29 19:25:12 -0700104 // Never call shutdownNow(). It will cancel the futures it's returned. And since
105 // Executor#execute won't return anything, we will hang forever waiting for the execution.
106 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
107 // mutate requests will need to gain write lock and query requests need to gain read lock.
108 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
109 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700110 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700111
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700112 // Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
113 // suffix refers to the fact that access to the field should be locked; unrelated to the
114 // unlocked status of users.
115 @GuardedBy("mUnlockedUsersLocked")
116 private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800117
Terry Wangfebbead2019-10-17 17:05:18 -0700118 public AppSearchManagerService(Context context) {
119 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700120 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700121 }
122
123 @Override
124 public void onStart() {
125 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700126 mPackageManager = getContext().getPackageManager();
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700127 mAppSearchUserInstanceManager = AppSearchUserInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700128 mUserManager = mContext.getSystemService(UserManager.class);
129 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700130 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700131 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700132 }
133
Xiaoyu Jin10329472021-06-23 16:50:03 -0700134 @Override
135 public void onBootPhase(/* @BootPhase */ int phase) {
136 if (phase == PHASE_BOOT_COMPLETED) {
137 StatsCollector.getInstance(mContext, EXECUTOR);
138 }
139 }
140
Terry Wang12dc6c02021-03-31 19:26:16 -0700141 private void registerReceivers() {
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700142 mContext.registerReceiverForAllUsers(
143 new UserActionReceiver(),
144 new IntentFilter(Intent.ACTION_USER_REMOVED),
145 /*broadcastPermission=*/ null,
Terry Wang12dc6c02021-03-31 19:26:16 -0700146 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700147
148 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
149 // broadcasts
150 IntentFilter packageChangedFilter = new IntentFilter();
151 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
152 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
153 packageChangedFilter.addDataScheme("package");
154 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700155 mContext.registerReceiverForAllUsers(
156 new PackageChangedReceiver(),
157 packageChangedFilter,
158 /*broadcastPermission=*/ null,
Terry Wange201dc02021-04-16 01:03:20 -0700159 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700160 }
161
162 private class UserActionReceiver extends BroadcastReceiver {
163 @Override
164 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700165 Objects.requireNonNull(context);
166 Objects.requireNonNull(intent);
167
Terry Wang12dc6c02021-03-31 19:26:16 -0700168 switch (intent.getAction()) {
169 case Intent.ACTION_USER_REMOVED:
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700170 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
171 if (userHandle == null) {
172 Log.e(TAG, "Extra "
173 + Intent.EXTRA_USER + " is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700174 return;
175 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -0700176 handleUserRemoved(userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700177 break;
178 default:
Terry Wange201dc02021-04-16 01:03:20 -0700179 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700180 }
181 }
182 }
183
184 /**
185 * Handles user removed action.
186 *
187 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
188 * "credential encrypted" system directory of each user. That directory will be auto-deleted
189 * when a user is removed.
190 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700191 * @param userHandle The multi-user handle of the user that need to be removed.
Terry Wang12dc6c02021-03-31 19:26:16 -0700192 * @see android.os.Environment#getDataSystemCeDirectory
193 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700194 private void handleUserRemoved(@NonNull UserHandle userHandle) {
Terry Wang12dc6c02021-03-31 19:26:16 -0700195 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700196 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700197 Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
Terry Wang12dc6c02021-03-31 19:26:16 -0700198 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700199 Log.e(TAG, "Unable to remove data for: " + userHandle, t);
Terry Wange201dc02021-04-16 01:03:20 -0700200 }
201 }
202
203 private class PackageChangedReceiver extends BroadcastReceiver {
204 @Override
205 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700206 Objects.requireNonNull(context);
207 Objects.requireNonNull(intent);
208
Terry Wange201dc02021-04-16 01:03:20 -0700209 switch (intent.getAction()) {
210 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
211 case Intent.ACTION_PACKAGE_DATA_CLEARED:
212 String packageName = intent.getData().getSchemeSpecificPart();
213 if (packageName == null) {
214 Log.e(TAG, "Package name is missing in the intent: " + intent);
215 return;
216 }
217 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
218 if (uid == INVALID_UID) {
219 Log.e(TAG, "uid is missing in the intent: " + intent);
220 return;
221 }
222 handlePackageRemoved(packageName, uid);
223 break;
224 default:
225 Log.e(TAG, "Received unknown intent: " + intent);
226 }
227 }
228 }
229
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700230 private void handlePackageRemoved(@NonNull String packageName, int uid) {
231 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Terry Wange201dc02021-04-16 01:03:20 -0700232 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700233 if (isUserLocked(userHandle)) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700234 // We cannot access a locked user's directry and remove package data from it.
235 // We should remove those uninstalled package data when the user is unlocking.
Terry Wange201dc02021-04-16 01:03:20 -0700236 return;
237 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700238 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700239 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700240 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700241 AppSearchUserInstance instance =
242 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700243 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
Terry Wange201dc02021-04-16 01:03:20 -0700244 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700245 instance.getAppSearchImpl().clearPackageData(packageName);
246 instance.getLogger().removeCachedUidForPackage(packageName);
Terry Wange201dc02021-04-16 01:03:20 -0700247 }
248 } catch (Throwable t) {
249 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700250 }
Terry Wangfebbead2019-10-17 17:05:18 -0700251 }
252
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800253 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700254 public void onUserUnlocking(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700255 Objects.requireNonNull(user);
Terry Wanga9e6e212021-04-23 15:51:37 -0700256 UserHandle userHandle = user.getUserHandle();
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700257 synchronized (mUnlockedUsersLocked) {
Terry Wanga9e6e212021-04-23 15:51:37 -0700258 mUnlockedUsersLocked.add(userHandle);
Cassie Wang15c86972021-02-09 13:43:25 -0800259 }
Terry Wanga9e6e212021-04-23 15:51:37 -0700260 EXECUTOR.execute(() -> {
261 try {
262 // Only clear the package's data if AppSearch exists for this user.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700263 if (AppSearchUserInstanceManager.getAppSearchDir(userHandle).exists()) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700264 Context userContext = mContext.createContextAsUser(userHandle, /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700265 AppSearchUserInstance instance =
266 mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang84e33a02021-06-18 14:13:31 -0700267 userContext, userHandle, AppSearchConfig.getInstance(EXECUTOR));
268 List<PackageInfo> installedPackageInfos = userContext
Terry Wanga9e6e212021-04-23 15:51:37 -0700269 .getPackageManager()
270 .getInstalledPackages(/*flags=*/0);
271 Set<String> packagesToKeep = new ArraySet<>(installedPackageInfos.size());
272 for (int i = 0; i < installedPackageInfos.size(); i++) {
273 packagesToKeep.add(installedPackageInfos.get(i).packageName);
274 }
Terry Wang0be9c302022-01-21 14:36:18 -0800275 packagesToKeep.add(VisibilityStore.VISIBILITY_PACKAGE_NAME);
Terry Wanga9e6e212021-04-23 15:51:37 -0700276 //TODO(b/145759910) clear visibility setting for package.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700277 instance.getAppSearchImpl().prunePackageData(packagesToKeep);
Terry Wanga9e6e212021-04-23 15:51:37 -0700278 }
279 } catch (Throwable t) {
280 Log.e(TAG, "Unable to prune packages for " + user, t);
281 }
282 });
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800283 }
284
Terry Wangde9f3382021-04-28 19:45:07 -0700285 @Override
286 public void onUserStopping(@NonNull TargetUser user) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700287 Objects.requireNonNull(user);
288
289 synchronized (mUnlockedUsersLocked) {
290 UserHandle userHandle = user.getUserHandle();
291 mUnlockedUsersLocked.remove(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700292 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700293 mAppSearchUserInstanceManager.closeAndRemoveUserInstance(userHandle);
Terry Wangde9f3382021-04-28 19:45:07 -0700294 } catch (Throwable t) {
295 Log.e(TAG, "Error handling user stopping.", t);
296 }
297 }
298 }
299
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700300 private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
301 if (isUserLocked(callingUser)) {
302 throw new IllegalStateException(callingUser + " is locked or not running.");
Terry Wange201dc02021-04-16 01:03:20 -0700303 }
304 }
305
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700306 private boolean isUserLocked(@NonNull UserHandle callingUser) {
307 synchronized (mUnlockedUsersLocked) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700308 // First, check the local copy.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700309 if (mUnlockedUsersLocked.contains(callingUser)) {
Terry Wange201dc02021-04-16 01:03:20 -0700310 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700311 }
312 // If the local copy says the user is locked, check with UM for the actual state,
313 // since the user might just have been unlocked.
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700314 return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
Yang Yu0fcd51a2021-04-23 11:25:44 -0700315 }
316 }
317
Terry Wangfebbead2019-10-17 17:05:18 -0700318 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800319 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800320 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800321 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700322 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700323 @NonNull List<Bundle> schemaBundles,
Terry Wang5b0c5612021-12-23 15:57:19 -0800324 @NonNull List<Bundle> visibilityBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800325 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700326 int schemaVersion,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700327 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700328 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800329 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700330 Objects.requireNonNull(packageName);
331 Objects.requireNonNull(databaseName);
332 Objects.requireNonNull(schemaBundles);
Terry Wang5b0c5612021-12-23 15:57:19 -0800333 Objects.requireNonNull(visibilityBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700334 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700335 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700336
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700337 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000338 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800339 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700340 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700341 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700342 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700343 int operationSuccessCount = 0;
344 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700345 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000346 verifyCaller(callingUid, packageName);
347
348 // Obtain the user where the client wants to run the operations in. This should
349 // end up being the same as userHandle, assuming it is not a special user and
350 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000351 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000352 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000353
Terry Wange04ceab2021-03-29 19:25:12 -0700354 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
355 for (int i = 0; i < schemaBundles.size(); i++) {
356 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800357 }
Terry Wang5b0c5612021-12-23 15:57:19 -0800358 List<VisibilityDocument> visibilityDocuments =
359 new ArrayList<>(visibilityBundles.size());
360 for (int i = 0; i < visibilityBundles.size(); i++) {
361 visibilityDocuments.add(
362 new VisibilityDocument(visibilityBundles.get(i)));
Terry Wange04ceab2021-03-29 19:25:12 -0700363 }
Cassie Wang2feb34d2021-07-22 18:55:19 +0000364 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700365 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700366 SetSchemaResponse setSchemaResponse = instance.getAppSearchImpl().setSchema(
Terry Wange04ceab2021-03-29 19:25:12 -0700367 packageName,
368 databaseName,
369 schemas,
Terry Wange15ea582021-10-21 18:59:21 -0700370 visibilityDocuments,
Terry Wange04ceab2021-03-29 19:25:12 -0700371 forceOverride,
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700372 schemaVersion,
373 /*setSchemaStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700374 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700375 invokeCallbackOnResult(callback,
376 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Terry Wangf4d219b2021-07-01 19:11:39 -0700377
378 // setSchema will sync the schemas in the request to AppSearch, any existing
379 // schemas which is not included in the request will be delete if we force
380 // override incompatible schemas. And all documents of these types will be
381 // deleted as well. We should checkForOptimize for these deletion.
382 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -0700383 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700384 ++operationFailureCount;
385 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700386 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700387 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700388 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700389 int estimatedBinderLatencyMillis =
390 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
391 int totalLatencyMillis =
392 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700393 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700394 .setPackageName(packageName)
395 .setDatabase(databaseName)
396 .setStatusCode(statusCode)
397 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700398 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
399 // TODO(b/173532925) check the existing binder call latency chart
400 // is good enough for us:
401 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
402 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
403 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700404 .setNumOperationsFailed(operationFailureCount)
405 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700406 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800407 }
Terry Wange04ceab2021-03-29 19:25:12 -0700408 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800409 }
410
411 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800412 public void getSchema(
Alexander Dorokhined41def42022-01-25 15:45:34 -0800413 @NonNull String callingPackageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800414 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800415 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700416 @NonNull UserHandle userHandle,
Terry Wang83a24932020-12-09 21:00:18 -0800417 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800418 Objects.requireNonNull(callingPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700419 Objects.requireNonNull(packageName);
420 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700421 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700422 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700423
Cassie Wang2e2d0552021-08-04 16:18:10 +0000424 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700425 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700426 EXECUTOR.execute(() -> {
427 try {
Alexander Dorokhined41def42022-01-25 15:45:34 -0800428 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000429
430 // Obtain the user where the client wants to run the operations in. This should
431 // end up being the same as userHandle, assuming it is not a special user and
432 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000433 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000434 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000435
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700436 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000437 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700438 GetSchemaResponse response =
Alexander Dorokhined41def42022-01-25 15:45:34 -0800439 instance.getAppSearchImpl().getSchema(
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800440 packageName,
441 databaseName,
Alexander Dorokhine655aec02022-02-07 17:24:01 -0800442 new FrameworkCallerAccess(
Alexander Dorokhine72f5e372022-02-07 17:23:49 -0800443 callingPackageName,
444 callingUid,
445 instance.getVisibilityChecker()
446 .doesCallerHaveSystemAccess(
447 callingPackageName)));
Terry Wange04ceab2021-03-29 19:25:12 -0700448 invokeCallbackOnResult(
449 callback,
450 AppSearchResult.newSuccessfulResult(response.getBundle()));
451 } catch (Throwable t) {
452 invokeCallbackOnError(callback, t);
453 }
454 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700455 }
456
457 @Override
458 public void getNamespaces(
459 @NonNull String packageName,
460 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700461 @NonNull UserHandle userHandle,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700462 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700463 Objects.requireNonNull(packageName);
464 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700465 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700466 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700467
Cassie Wang2e2d0552021-08-04 16:18:10 +0000468 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -0700469 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700470 EXECUTOR.execute(() -> {
471 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000472 verifyCaller(callingUid, packageName);
473
474 // Obtain the user where the client wants to run the operations in. This should
475 // end up being the same as userHandle, assuming it is not a special user and
476 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000477 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000478 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000479
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700480 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000481 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700482 List<String> namespaces =
483 instance.getAppSearchImpl().getNamespaces(packageName, databaseName);
484 invokeCallbackOnResult(
485 callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wange04ceab2021-03-29 19:25:12 -0700486 } catch (Throwable t) {
487 invokeCallbackOnError(callback, t);
488 }
489 });
Terry Wang83a24932020-12-09 21:00:18 -0800490 }
491
492 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800493 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800494 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700495 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700496 @NonNull List<Bundle> documentBundles,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700497 @NonNull UserHandle userHandle,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800498 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800499 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700500 Objects.requireNonNull(packageName);
501 Objects.requireNonNull(databaseName);
502 Objects.requireNonNull(documentBundles);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700503 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700504 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700505
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700506 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000507 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800508 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700509 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800510 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700511 AppSearchUserInstance instance = null;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800512 int operationSuccessCount = 0;
513 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700514 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000515 verifyCaller(callingUid, packageName);
516
517 // Obtain the user where the client wants to run the operations in. This should
518 // end up being the same as userHandle, assuming it is not a special user and
519 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000520 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000521 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000522
Terry Wange04ceab2021-03-29 19:25:12 -0700523 AppSearchBatchResult.Builder<String, Void> resultBuilder =
524 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000525 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700526 for (int i = 0; i < documentBundles.size(); i++) {
527 GenericDocument document = new GenericDocument(documentBundles.get(i));
528 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700529 instance.getAppSearchImpl().putDocument(
530 packageName, databaseName, document, instance.getLogger());
531 resultBuilder.setSuccess(document.getId(), /*value=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800532 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700533 } catch (Throwable t) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700534 resultBuilder.setResult(document.getId(), throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800535 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700536 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700537 // Since we can only include one status code in the atom,
538 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800539 statusCode = result.getResultCode();
540 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700541 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800542 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700543 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700544 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700545 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -0700546
Alexander Dorokhinee0587d32021-12-07 17:02:17 -0800547 // Schedule a task to dispatch change notifications. See requirements for where
548 // the method is called documented in the method description.
549 dispatchChangeNotifications(instance);
550
Terry Wangf4d219b2021-07-01 19:11:39 -0700551 // The existing documents with same ID will be deleted, so there may be some
552 // resources that could be released after optimize().
553 checkForOptimize(instance, /*mutateBatchSize=*/ documentBundles.size());
Terry Wange04ceab2021-03-29 19:25:12 -0700554 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700555 ++operationFailureCount;
556 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700557 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800558 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700559 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700560 int estimatedBinderLatencyMillis =
561 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
562 int totalLatencyMillis =
563 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700564 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700565 .setPackageName(packageName)
566 .setDatabase(databaseName)
567 .setStatusCode(statusCode)
568 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800569 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
570 // TODO(b/173532925) check the existing binder call latency chart
571 // is good enough for us:
572 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -0700573 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800574 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700575 .setNumOperationsFailed(operationFailureCount)
576 .build());
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800577 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800578 }
Terry Wange04ceab2021-03-29 19:25:12 -0700579 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800580 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800581
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800582 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800583 public void getDocuments(
Alex Saveliev87631932022-01-21 00:48:44 +0000584 @NonNull String callingPackageName,
585 @NonNull String targetPackageName,
Terry Wangf2093072020-11-30 04:47:19 -0800586 @NonNull String databaseName,
587 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700588 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800589 @NonNull Map<String, List<String>> typePropertyPaths,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700590 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700591 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alex Saveliev87631932022-01-21 00:48:44 +0000592 boolean global,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800593 @NonNull IAppSearchBatchResultCallback callback) {
Alex Saveliev87631932022-01-21 00:48:44 +0000594 Objects.requireNonNull(callingPackageName);
595 Objects.requireNonNull(targetPackageName);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700596 Objects.requireNonNull(databaseName);
597 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700598 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700599 Objects.requireNonNull(typePropertyPaths);
600 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700601 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700602
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700603 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000604 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800605 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700606 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700607 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700608 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700609 int operationSuccessCount = 0;
610 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700611 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000612 verifyCaller(callingUid, callingPackageName);
Cassie Wangd51ed162021-07-29 22:22:30 +0000613
614 // Obtain the user where the client wants to run the operations in. This should
615 // end up being the same as userHandle, assuming it is not a special user and
616 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000617 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000618 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000619
Terry Wange04ceab2021-03-29 19:25:12 -0700620 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
621 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +0000622 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700623 for (int i = 0; i < ids.size(); i++) {
624 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700625 try {
Alex Saveliev87631932022-01-21 00:48:44 +0000626 GenericDocument document;
627 if (global) {
628 // TODO(b/203819101) add test to try out security by binding
629 // directly to binder and passing callingpackage param
630 document = instance.getAppSearchImpl().globalGetDocument(
631 targetPackageName,
632 databaseName,
633 namespace,
634 id,
635 typePropertyPaths,
Alexander Dorokhine655aec02022-02-07 17:24:01 -0800636 new FrameworkCallerAccess(
Alexander Dorokhine72f5e372022-02-07 17:23:49 -0800637 callingPackageName,
638 callingUid,
639 instance.getVisibilityChecker()
640 .doesCallerHaveSystemAccess(
641 callingPackageName)));
Alex Saveliev87631932022-01-21 00:48:44 +0000642 } else {
643 document = instance.getAppSearchImpl().getDocument(
644 targetPackageName,
645 databaseName,
646 namespace,
647 id,
648 typePropertyPaths);
649 }
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700650 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700651 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700652 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700653 // Since we can only include one status code in the atom,
654 // for failures, we would just save the one for the last failure
655 AppSearchResult<Bundle> result = throwableToFailedResult(t);
656 resultBuilder.setResult(id, result);
657 statusCode = result.getResultCode();
658 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700659 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800660 }
Terry Wange04ceab2021-03-29 19:25:12 -0700661 invokeCallbackOnResult(callback, resultBuilder.build());
662 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700663 ++operationFailureCount;
664 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700665 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700666 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700667 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700668 int estimatedBinderLatencyMillis =
669 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
670 int totalLatencyMillis =
671 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700672 instance.getLogger().logStats(new CallStats.Builder()
Alex Saveliev87631932022-01-21 00:48:44 +0000673 .setPackageName(targetPackageName)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700674 .setDatabase(databaseName)
675 .setStatusCode(statusCode)
676 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700677 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
Alex Saveliev87631932022-01-21 00:48:44 +0000678 // TODO(b/203819101) need mark the call as a global getById
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700679 // TODO(b/173532925) check the existing binder call latency chart
680 // is good enough for us:
681 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
682 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
683 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700684 .setNumOperationsFailed(operationFailureCount)
685 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700686 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800687 }
Terry Wange04ceab2021-03-29 19:25:12 -0700688 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800689 }
690
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800691 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800692 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800693 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700694 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700695 @NonNull String queryExpression,
696 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700697 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700698 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700699 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700700 Objects.requireNonNull(packageName);
701 Objects.requireNonNull(databaseName);
702 Objects.requireNonNull(queryExpression);
703 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700704 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700705 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700706
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700707 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000708 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800709 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700710 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700711 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700712 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700713 int operationSuccessCount = 0;
714 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700715 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000716 verifyCaller(callingUid, packageName);
717
718 // Obtain the user where the client wants to run the operations in. This should
719 // end up being the same as userHandle, assuming it is not a special user and
720 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000721 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000722 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000723
Cassie Wang2feb34d2021-07-22 18:55:19 +0000724 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700725 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
726 packageName,
727 databaseName,
728 queryExpression,
729 new SearchSpec(searchSpecBundle),
730 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700731 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700732 invokeCallbackOnResult(
733 callback,
734 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
735 } catch (Throwable t) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700736 ++operationFailureCount;
737 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700738 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700739 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700740 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700741 int estimatedBinderLatencyMillis =
742 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
743 int totalLatencyMillis =
744 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700745 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700746 .setPackageName(packageName)
747 .setDatabase(databaseName)
748 .setStatusCode(statusCode)
749 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700750 .setCallType(CallStats.CALL_TYPE_SEARCH)
751 // TODO(b/173532925) check the existing binder call latency chart
752 // is good enough for us:
753 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
754 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
755 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700756 .setNumOperationsFailed(operationFailureCount)
757 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700758 }
Terry Wange04ceab2021-03-29 19:25:12 -0700759 }
760 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700761 }
762
Terry Wangf2093072020-11-30 04:47:19 -0800763 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800764 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800765 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800766 @NonNull String queryExpression,
767 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700768 @NonNull UserHandle userHandle,
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700769 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800770 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700771 Objects.requireNonNull(packageName);
772 Objects.requireNonNull(queryExpression);
773 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700774 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700775 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700776
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700777 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +0000778 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800779 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700780 EXECUTOR.execute(() -> {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700781 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700782 AppSearchUserInstance instance = null;
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700783 int operationSuccessCount = 0;
784 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700785 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000786 verifyCaller(callingUid, packageName);
787
788 // Obtain the user where the client wants to run the operations in. This should
789 // end up being the same as userHandle, assuming it is not a special user and
790 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000791 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000792 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000793
Cassie Wang2feb34d2021-07-22 18:55:19 +0000794 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700795
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -0800796 boolean callerHasSystemAccess = instance.getVisibilityChecker()
Terry Wang0be9c302022-01-21 14:36:18 -0800797 .doesCallerHaveSystemAccess(packageName);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700798 SearchResultPage searchResultPage = instance.getAppSearchImpl().globalQuery(
799 queryExpression,
800 new SearchSpec(searchSpecBundle),
Alexander Dorokhine655aec02022-02-07 17:24:01 -0800801 new FrameworkCallerAccess(
Alexander Dorokhine72f5e372022-02-07 17:23:49 -0800802 packageName,
803 callingUid,
804 callerHasSystemAccess),
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700805 instance.getLogger());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700806 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700807 invokeCallbackOnResult(
808 callback,
809 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700810 } catch (Throwable t) {
811 ++operationFailureCount;
812 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700813 invokeCallbackOnError(callback, t);
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700814 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700815 if (instance != null) {
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700816 int estimatedBinderLatencyMillis =
817 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
818 int totalLatencyMillis =
819 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700820 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700821 .setPackageName(packageName)
822 .setStatusCode(statusCode)
823 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700824 .setCallType(CallStats.CALL_TYPE_GLOBAL_SEARCH)
825 // TODO(b/173532925) check the existing binder call latency chart
826 // is good enough for us:
827 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
828 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
829 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -0700830 .setNumOperationsFailed(operationFailureCount)
831 .build());
Xiaoyu Jinef66a422021-05-09 17:38:59 -0700832 }
Terry Wange04ceab2021-03-29 19:25:12 -0700833 }
834 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800835 }
836
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700837 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800838 public void getNextPage(
Cassie Wang84e33a02021-06-18 14:13:31 -0700839 @NonNull String packageName,
Cassie Wang0c62d992021-01-15 14:39:30 -0800840 long nextPageToken,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700841 @NonNull UserHandle userHandle,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700842 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -0700843 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700844 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700845 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700846
Cassie Wang2e2d0552021-08-04 16:18:10 +0000847 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800848 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700849 EXECUTOR.execute(() -> {
850 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000851 verifyCaller(callingUid, packageName);
852
853 // Obtain the user where the client wants to run the operations in. This should
854 // end up being the same as userHandle, assuming it is not a special user and
855 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000856 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000857 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000858
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700859 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000860 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700861 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700862 SearchResultPage searchResultPage =
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700863 instance.getAppSearchImpl().getNextPage(
864 packageName, nextPageToken, /*statsBuilder=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700865 invokeCallbackOnResult(
866 callback,
867 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
868 } catch (Throwable t) {
869 invokeCallbackOnError(callback, t);
870 }
871 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700872 }
873
874 @Override
Cassie Wang84e33a02021-06-18 14:13:31 -0700875 public void invalidateNextPageToken(@NonNull String packageName, long nextPageToken,
876 @NonNull UserHandle userHandle) {
877 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700878 Objects.requireNonNull(userHandle);
879
Cassie Wang2e2d0552021-08-04 16:18:10 +0000880 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -0800881 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700882 EXECUTOR.execute(() -> {
883 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000884 verifyCaller(callingUid, packageName);
885
886 // Obtain the user where the client wants to run the operations in. This should
887 // end up being the same as userHandle, assuming it is not a special user and
888 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000889 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000890 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000891
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700892 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000893 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhined7e39892021-07-02 14:50:05 -0700894 instance.getAppSearchImpl().invalidateNextPageToken(packageName, nextPageToken);
Terry Wange04ceab2021-03-29 19:25:12 -0700895 } catch (Throwable t) {
896 Log.e(TAG, "Unable to invalidate the query page token", t);
897 }
898 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800899 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800900
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700901 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800902 public void writeQueryResultsToFile(
903 @NonNull String packageName,
904 @NonNull String databaseName,
905 @NonNull ParcelFileDescriptor fileDescriptor,
906 @NonNull String queryExpression,
907 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700908 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800909 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700910 Objects.requireNonNull(packageName);
911 Objects.requireNonNull(databaseName);
912 Objects.requireNonNull(fileDescriptor);
913 Objects.requireNonNull(queryExpression);
914 Objects.requireNonNull(searchSpecBundle);
915 Objects.requireNonNull(userHandle);
916 Objects.requireNonNull(callback);
917
Cassie Wang2e2d0552021-08-04 16:18:10 +0000918 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800919 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700920 EXECUTOR.execute(() -> {
921 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000922 verifyCaller(callingUid, packageName);
923
924 // Obtain the user where the client wants to run the operations in. This should
925 // end up being the same as userHandle, assuming it is not a special user and
926 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000927 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000928 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000929
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700930 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000931 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wange04ceab2021-03-29 19:25:12 -0700932 // we don't need to append the file. The file is always brand new.
933 try (DataOutputStream outputStream = new DataOutputStream(
934 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700935 SearchResultPage searchResultPage = instance.getAppSearchImpl().query(
Terry Wange04ceab2021-03-29 19:25:12 -0700936 packageName,
937 databaseName,
938 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700939 new SearchSpec(searchSpecBundle),
940 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700941 while (!searchResultPage.getResults().isEmpty()) {
942 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
943 AppSearchMigrationHelper.writeBundleToOutputStream(
944 outputStream, searchResultPage.getResults().get(i)
945 .getGenericDocument().getBundle());
946 }
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700947 // TODO(b/173532925): Implement logging for statsBuilder
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700948 searchResultPage = instance.getAppSearchImpl().getNextPage(
Alexander Dorokhineba42f392021-08-17 15:17:40 -0700949 packageName,
950 searchResultPage.getNextPageToken(),
951 /*statsBuilder=*/ null);
Terry Wang623e3b02021-02-02 20:27:33 -0800952 }
Terry Wang623e3b02021-02-02 20:27:33 -0800953 }
Terry Wange04ceab2021-03-29 19:25:12 -0700954 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
955 } catch (Throwable t) {
956 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800957 }
Terry Wange04ceab2021-03-29 19:25:12 -0700958 });
Terry Wang623e3b02021-02-02 20:27:33 -0800959 }
960
961 @Override
962 public void putDocumentsFromFile(
963 @NonNull String packageName,
964 @NonNull String databaseName,
965 @NonNull ParcelFileDescriptor fileDescriptor,
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700966 @NonNull UserHandle userHandle,
Terry Wang623e3b02021-02-02 20:27:33 -0800967 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -0700968 Objects.requireNonNull(packageName);
969 Objects.requireNonNull(databaseName);
970 Objects.requireNonNull(fileDescriptor);
971 Objects.requireNonNull(userHandle);
972 Objects.requireNonNull(callback);
973
Cassie Wang2e2d0552021-08-04 16:18:10 +0000974 int callingPid = Binder.getCallingPid();
Terry Wang623e3b02021-02-02 20:27:33 -0800975 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -0700976 EXECUTOR.execute(() -> {
977 try {
Cassie Wangd51ed162021-07-29 22:22:30 +0000978 verifyCaller(callingUid, packageName);
979
980 // Obtain the user where the client wants to run the operations in. This should
981 // end up being the same as userHandle, assuming it is not a special user and
982 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +0000983 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +0000984 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +0000985
Alexander Dorokhine4d051632021-06-18 10:48:58 -0700986 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +0000987 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Terry Wang623e3b02021-02-02 20:27:33 -0800988
Terry Wange04ceab2021-03-29 19:25:12 -0700989 GenericDocument document;
990 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
991 try (DataInputStream inputStream = new DataInputStream(
992 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
993 while (true) {
994 try {
995 document = AppSearchMigrationHelper
996 .readDocumentFromInputStream(inputStream);
997 } catch (EOFException e) {
998 // nothing wrong, we just finish the reading.
999 break;
1000 }
1001 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001002 instance.getAppSearchImpl().putDocument(
1003 packageName, databaseName, document, /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001004 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001005 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
1006 document.getNamespace(),
1007 document.getId(),
1008 document.getSchemaType(),
1009 AppSearchResult.throwableToFailedResult(t))
1010 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -07001011 }
Terry Wang623e3b02021-02-02 20:27:33 -08001012 }
1013 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001014 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -07001015 invokeCallbackOnResult(callback,
1016 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
1017 } catch (Throwable t) {
1018 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -08001019 }
Terry Wange04ceab2021-03-29 19:25:12 -07001020 });
Terry Wang623e3b02021-02-02 20:27:33 -08001021 }
1022
1023 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001024 public void reportUsage(
1025 @NonNull String packageName,
1026 @NonNull String databaseName,
1027 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001028 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001029 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001030 boolean systemUsage,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001031 @NonNull UserHandle userHandle,
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001032 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001033 Objects.requireNonNull(packageName);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001034 Objects.requireNonNull(databaseName);
1035 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001036 Objects.requireNonNull(documentId);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001037 Objects.requireNonNull(userHandle);
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001038 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001039
Cassie Wang2e2d0552021-08-04 16:18:10 +00001040 int callingPid = Binder.getCallingPid();
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001041 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001042 EXECUTOR.execute(() -> {
1043 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001044 verifyCaller(callingUid, packageName);
1045
1046 // Obtain the user where the client wants to run the operations in. This should
1047 // end up being the same as userHandle, assuming it is not a special user and
1048 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001049 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001050 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001051
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001052 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001053 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001054
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001055 if (systemUsage && !instance.getVisibilityChecker().
Terry Wang0be9c302022-01-21 14:36:18 -08001056 doesCallerHaveSystemAccess(packageName)) {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001057 throw new AppSearchException(
1058 AppSearchResult.RESULT_SECURITY_ERROR,
1059 packageName + " does not have access to report system usage");
Terry Wange04ceab2021-03-29 19:25:12 -07001060 }
1061
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001062 instance.getAppSearchImpl().reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001063 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -07001064 usageTimeMillis, systemUsage);
1065 invokeCallbackOnResult(
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001066 callback, AppSearchResult.newSuccessfulResult(/*value=*/ null));
Terry Wange04ceab2021-03-29 19:25:12 -07001067 } catch (Throwable t) {
1068 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -07001069 }
Terry Wange04ceab2021-03-29 19:25:12 -07001070 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -08001071 }
1072
1073 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001074 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -08001075 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -08001076 @NonNull String databaseName,
1077 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001078 @NonNull List<String> ids,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001079 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001080 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -08001081 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001082 Objects.requireNonNull(packageName);
1083 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001084 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001085 Objects.requireNonNull(ids);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001086 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001087 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001088
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001089 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001090 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001091 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001092 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001093 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001094 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001095 int operationSuccessCount = 0;
1096 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001097 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001098 verifyCaller(callingUid, packageName);
1099
1100 // Obtain the user where the client wants to run the operations in. This should
1101 // end up being the same as userHandle, assuming it is not a special user and
1102 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001103 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001104 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001105
Terry Wange04ceab2021-03-29 19:25:12 -07001106 AppSearchBatchResult.Builder<String, Void> resultBuilder =
1107 new AppSearchBatchResult.Builder<>();
Cassie Wang2feb34d2021-07-22 18:55:19 +00001108 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001109 for (int i = 0; i < ids.size(); i++) {
1110 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -07001111 try {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001112 instance.getAppSearchImpl().remove(
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001113 packageName,
1114 databaseName,
1115 namespace,
1116 id,
1117 /*removeStatsBuilder=*/ null);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001118 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -07001119 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -07001120 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001121 AppSearchResult<Void> result = throwableToFailedResult(t);
1122 resultBuilder.setResult(id, result);
1123 // Since we can only include one status code in the atom,
1124 // for failures, we would just save the one for the last failure
1125 statusCode = result.getResultCode();
1126 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001127 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001128 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001129 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001130 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -07001131 invokeCallbackOnResult(callback, resultBuilder.build());
Terry Wangf4d219b2021-07-01 19:11:39 -07001132
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001133 // Schedule a task to dispatch change notifications. See requirements for where
1134 // the method is called documented in the method description.
1135 dispatchChangeNotifications(instance);
1136
Terry Wangf4d219b2021-07-01 19:11:39 -07001137 checkForOptimize(instance, ids.size());
Terry Wange04ceab2021-03-29 19:25:12 -07001138 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001139 ++operationFailureCount;
1140 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001141 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001142 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001143 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001144 int estimatedBinderLatencyMillis =
1145 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1146 int totalLatencyMillis =
1147 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001148 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001149 .setPackageName(packageName)
1150 .setDatabase(databaseName)
1151 .setStatusCode(statusCode)
1152 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001153 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
1154 // TODO(b/173532925) check the existing binder call latency chart
1155 // is good enough for us:
1156 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1157 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1158 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001159 .setNumOperationsFailed(operationFailureCount)
1160 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001161 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001162 }
Terry Wange04ceab2021-03-29 19:25:12 -07001163 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -07001164 }
1165
1166 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -07001167 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -08001168 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -07001169 @NonNull String databaseName,
1170 @NonNull String queryExpression,
1171 @NonNull Bundle searchSpecBundle,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001172 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001173 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -07001174 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001175 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001176 Objects.requireNonNull(packageName);
1177 Objects.requireNonNull(databaseName);
1178 Objects.requireNonNull(queryExpression);
1179 Objects.requireNonNull(searchSpecBundle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001180 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001181 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001182
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001183 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001184 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001185 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001186 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001187 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001188 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001189 int operationSuccessCount = 0;
1190 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001191 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001192 verifyCaller(callingUid, packageName);
1193
1194 // Obtain the user where the client wants to run the operations in. This should
1195 // end up being the same as userHandle, assuming it is not a special user and
1196 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001197 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001198 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001199
Cassie Wang2feb34d2021-07-22 18:55:19 +00001200 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001201 instance.getAppSearchImpl().removeByQuery(
Terry Wange04ceab2021-03-29 19:25:12 -07001202 packageName,
1203 databaseName,
1204 queryExpression,
Alexander Dorokhinea4b5bab2021-05-20 14:24:50 -07001205 new SearchSpec(searchSpecBundle),
1206 /*removeStatsBuilder=*/ null);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -07001207 // Now that the batch has been written. Persist the newly written data.
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001208 instance.getAppSearchImpl().persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001209 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001210 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Terry Wangf4d219b2021-07-01 19:11:39 -07001211
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001212 // Schedule a task to dispatch change notifications. See requirements for where
1213 // the method is called documented in the method description.
1214 dispatchChangeNotifications(instance);
1215
Terry Wangf4d219b2021-07-01 19:11:39 -07001216 checkForOptimize(instance);
Terry Wange04ceab2021-03-29 19:25:12 -07001217 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001218 ++operationFailureCount;
1219 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001220 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001221 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001222 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001223 int estimatedBinderLatencyMillis =
1224 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1225 int totalLatencyMillis =
1226 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001227 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001228 .setPackageName(packageName)
1229 .setDatabase(databaseName)
1230 .setStatusCode(statusCode)
1231 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001232 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
1233 // TODO(b/173532925) check the existing binder call latency chart
1234 // is good enough for us:
1235 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1236 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1237 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001238 .setNumOperationsFailed(operationFailureCount)
1239 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001240 }
Terry Wange04ceab2021-03-29 19:25:12 -07001241 }
1242 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -07001243 }
1244
Terry Wangdbd1dca2020-11-03 17:03:56 -08001245 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -07001246 public void getStorageInfo(
1247 @NonNull String packageName,
1248 @NonNull String databaseName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001249 @NonNull UserHandle userHandle,
Cassie Wang8f0df492021-03-24 09:23:18 -07001250 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001251 Objects.requireNonNull(packageName);
1252 Objects.requireNonNull(databaseName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001253 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001254 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001255
Cassie Wang2e2d0552021-08-04 16:18:10 +00001256 int callingPid = Binder.getCallingPid();
Cassie Wang8f0df492021-03-24 09:23:18 -07001257 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001258 EXECUTOR.execute(() -> {
1259 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001260 verifyCaller(callingUid, packageName);
1261
1262 // Obtain the user where the client wants to run the operations in. This should
1263 // end up being the same as userHandle, assuming it is not a special user and
1264 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001265 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001266 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001267
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001268 AppSearchUserInstance instance =
Cassie Wang2feb34d2021-07-22 18:55:19 +00001269 mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001270 StorageInfo storageInfo = instance.getAppSearchImpl()
1271 .getStorageInfoForDatabase(packageName, databaseName);
Terry Wange04ceab2021-03-29 19:25:12 -07001272 Bundle storageInfoBundle = storageInfo.getBundle();
1273 invokeCallbackOnResult(
1274 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
1275 } catch (Throwable t) {
1276 invokeCallbackOnError(callback, t);
1277 }
1278 });
Cassie Wang8f0df492021-03-24 09:23:18 -07001279 }
1280
1281 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001282 public void persistToDisk(
Cassie Wang84e33a02021-06-18 14:13:31 -07001283 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001284 @NonNull UserHandle userHandle,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001285 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001286 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001287 Objects.requireNonNull(userHandle);
1288
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001289 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001290 int callingPid = Binder.getCallingPid();
Cassie Wangb0d60122021-03-30 12:38:46 -07001291 int callingUid = Binder.getCallingUid();
Terry Wange04ceab2021-03-29 19:25:12 -07001292 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001293 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001294 AppSearchUserInstance instance = null;
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001295 int operationSuccessCount = 0;
1296 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001297 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001298 verifyCaller(callingUid, packageName);
1299
1300 // Obtain the user where the client wants to run the operations in. This should
1301 // end up being the same as userHandle, assuming it is not a special user and
1302 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001303 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wang2feb34d2021-07-22 18:55:19 +00001304 verifyUserUnlocked(targetUser);
Cassie Wangd51ed162021-07-29 22:22:30 +00001305
Cassie Wang2feb34d2021-07-22 18:55:19 +00001306 instance = mAppSearchUserInstanceManager.getUserInstance(targetUser);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001307 instance.getAppSearchImpl().persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001308 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001309 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001310 ++operationFailureCount;
1311 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001312 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001313 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001314 if (instance != null) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001315 int estimatedBinderLatencyMillis =
1316 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1317 int totalLatencyMillis =
1318 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001319 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001320 .setStatusCode(statusCode)
1321 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001322 .setCallType(CallStats.CALL_TYPE_FLUSH)
1323 // TODO(b/173532925) check the existing binder call latency chart
1324 // is good enough for us:
1325 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1326 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1327 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001328 .setNumOperationsFailed(operationFailureCount)
1329 .build());
Xiaoyu Jinc5a75772021-05-09 20:12:44 -07001330 }
Terry Wange04ceab2021-03-29 19:25:12 -07001331 }
1332 });
Terry Wang2da17852020-12-16 19:59:08 -08001333 }
1334
1335 @Override
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001336 public AppSearchResultParcel<Void> addObserver(
1337 @NonNull String callingPackage,
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001338 @NonNull String targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001339 @NonNull Bundle observerSpecBundle,
1340 @NonNull UserHandle userHandle,
1341 @NonNull IAppSearchObserverProxy observerProxyStub) {
1342 Objects.requireNonNull(callingPackage);
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001343 Objects.requireNonNull(targetPackageName);
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001344 Objects.requireNonNull(observerSpecBundle);
1345 Objects.requireNonNull(userHandle);
1346 Objects.requireNonNull(observerProxyStub);
1347
1348 int callingPid = Binder.getCallingPid();
1349 int callingUid = Binder.getCallingUid();
1350 long callingIdentity = Binder.clearCallingIdentity();
1351
1352 // Note: addObserver is performed on the binder thread, unlike most AppSearch APIs
1353 try {
1354 verifyCaller(callingUid, callingPackage);
1355 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1356 verifyUserUnlocked(targetUser);
1357
1358 AppSearchUserInstance instance =
1359 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1360 instance.getAppSearchImpl().addObserver(
Alexander Dorokhine655aec02022-02-07 17:24:01 -08001361 new FrameworkCallerAccess(
Alexander Dorokhine72f5e372022-02-07 17:23:49 -08001362 callingPackage,
1363 callingUid,
1364 instance.getVisibilityChecker()
1365 .doesCallerHaveSystemAccess(callingPackage)),
Alexander Dorokhine661ef9a2022-01-28 11:30:45 -08001366 targetPackageName,
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001367 new ObserverSpec(observerSpecBundle),
1368 EXECUTOR,
1369 new AppSearchObserverProxy(observerProxyStub));
1370 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1371 } catch (Throwable t) {
1372 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1373 } finally {
1374 Binder.restoreCallingIdentity(callingIdentity);
1375 }
1376 }
1377
1378 @Override
Alexander Dorokhine04f94d22022-01-24 23:38:50 -08001379 public AppSearchResultParcel<Void> removeObserver(
1380 @NonNull String callingPackage,
1381 @NonNull String observedPackage,
1382 @NonNull UserHandle userHandle,
1383 @NonNull IAppSearchObserverProxy observerProxyStub) {
1384 Objects.requireNonNull(callingPackage);
1385 Objects.requireNonNull(observedPackage);
1386 Objects.requireNonNull(userHandle);
1387 Objects.requireNonNull(observerProxyStub);
1388
1389 int callingPid = Binder.getCallingPid();
1390 int callingUid = Binder.getCallingUid();
1391 long callingIdentity = Binder.clearCallingIdentity();
1392
1393 // Note: removeObserver is performed on the binder thread, unlike most AppSearch APIs
1394 try {
1395 verifyCaller(callingUid, callingPackage);
1396 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
1397 verifyUserUnlocked(targetUser);
1398
1399 AppSearchUserInstance instance =
1400 mAppSearchUserInstanceManager.getUserInstance(targetUser);
1401 instance.getAppSearchImpl().removeObserver(
1402 observedPackage,
1403 new AppSearchObserverProxy(observerProxyStub));
1404 return new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null));
1405 } catch (Throwable t) {
1406 return new AppSearchResultParcel<>(throwableToFailedResult(t));
1407 } finally {
1408 Binder.restoreCallingIdentity(callingIdentity);
1409 }
1410 }
1411
1412 @Override
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001413 public void initialize(
Cassie Wang84e33a02021-06-18 14:13:31 -07001414 @NonNull String packageName,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001415 @NonNull UserHandle userHandle,
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001416 @ElapsedRealtimeLong long binderCallStartTimeMillis,
1417 @NonNull IAppSearchResultCallback callback) {
Cassie Wang84e33a02021-06-18 14:13:31 -07001418 Objects.requireNonNull(packageName);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001419 Objects.requireNonNull(userHandle);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001420 Objects.requireNonNull(callback);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001421
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001422 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wang2e2d0552021-08-04 16:18:10 +00001423 int callingPid = Binder.getCallingPid();
Terry Wangf2093072020-11-30 04:47:19 -08001424 int callingUid = Binder.getCallingUid();
Cassie Wang84e33a02021-06-18 14:13:31 -07001425
Terry Wange04ceab2021-03-29 19:25:12 -07001426 EXECUTOR.execute(() -> {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001427 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001428 AppSearchUserInstance instance = null;
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001429 int operationSuccessCount = 0;
1430 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -07001431 try {
Cassie Wangd51ed162021-07-29 22:22:30 +00001432 verifyCaller(callingUid, packageName);
1433
1434 // Obtain the user where the client wants to run the operations in. This should
1435 // end up being the same as userHandle, assuming it is not a special user and
1436 // the client is allowed to run operations in that user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001437 UserHandle targetUser = handleIncomingUser(userHandle, callingPid, callingUid);
Cassie Wangd51ed162021-07-29 22:22:30 +00001438 verifyUserUnlocked(targetUser);
1439
Cassie Wang2feb34d2021-07-22 18:55:19 +00001440 Context targetUserContext = mContext.createContextAsUser(targetUser,
1441 /*flags=*/ 0);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001442 instance = mAppSearchUserInstanceManager.getOrCreateUserInstance(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001443 targetUserContext, targetUser, AppSearchConfig.getInstance(EXECUTOR));
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001444 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -07001445 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1446 } catch (Throwable t) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001447 ++operationFailureCount;
1448 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -07001449 invokeCallbackOnError(callback, t);
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001450 } finally {
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001451 if (instance != null) {
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001452 int estimatedBinderLatencyMillis =
1453 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
1454 int totalLatencyMillis =
1455 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001456 instance.getLogger().logStats(new CallStats.Builder()
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001457 .setStatusCode(statusCode)
1458 .setTotalLatencyMillis(totalLatencyMillis)
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001459 .setCallType(CallStats.CALL_TYPE_INITIALIZE)
1460 // TODO(b/173532925) check the existing binder call latency chart
1461 // is good enough for us:
1462 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1463 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1464 .setNumOperationsSucceeded(operationSuccessCount)
Alexander Dorokhine82a38722021-06-09 16:35:22 -07001465 .setNumOperationsFailed(operationFailureCount)
1466 .build());
Xiaoyu Jinc410c4f2021-05-09 14:15:50 -07001467 }
Terry Wange04ceab2021-03-29 19:25:12 -07001468 }
1469 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001470 }
1471
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001472 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001473 private void invokeCallbackOnResult(
1474 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001475 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001476 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001477 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001478 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001479 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001480 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001481
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001482 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001483 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001484 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001485 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001486 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001487 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001488 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001489 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001490 }
1491
1492 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001493 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001494 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001495 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001496 */
1497 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001498 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001499 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001500 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001501 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001502 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001503 }
1504 }
1505
1506 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001507 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001508 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001509 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001510 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001511 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001512 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001513 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001514 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001515 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001516 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001517 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001518 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001519 }
Terry Wangfebbead2019-10-17 17:05:18 -07001520 }
Terry Wangf2093072020-11-30 04:47:19 -08001521
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001522 /**
1523 * Helper for dealing with incoming user arguments to system service calls.
1524 *
Cassie Wang2e2d0552021-08-04 16:18:10 +00001525 * <p>Takes care of checking permissions and if the target is special user, this method will
1526 * simply throw.
1527 *
Cassie Wang2feb34d2021-07-22 18:55:19 +00001528 * @param targetUserHandle The user which the caller is requesting to execute as.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001529 * @param callingPid The actual pid of the caller as determined by Binder.
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001530 * @param callingUid The actual uid of the caller as determined by Binder.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001531 *
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001532 * @return the user handle that the call should run as. Will always be a concrete user.
Cassie Wang2e2d0552021-08-04 16:18:10 +00001533 *
1534 * @throws IllegalArgumentException if the target user is a special user.
1535 * @throws SecurityException if caller trying to interact across user without
1536 * {@link Manifest.permission#INTERACT_ACROSS_USERS_FULL}
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001537 */
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001538 @NonNull
Cassie Wang2e2d0552021-08-04 16:18:10 +00001539 private UserHandle handleIncomingUser(@NonNull UserHandle targetUserHandle, int callingPid,
1540 int callingUid) {
Cassie Wang2feb34d2021-07-22 18:55:19 +00001541 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1542 if (callingUserHandle.equals(targetUserHandle)) {
1543 return targetUserHandle;
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001544 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001545
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001546 // Duplicates UserController#ensureNotSpecialUser
Cassie Wang2feb34d2021-07-22 18:55:19 +00001547 if (targetUserHandle.getIdentifier() < 0) {
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001548 throw new IllegalArgumentException(
Cassie Wang2feb34d2021-07-22 18:55:19 +00001549 "Call does not support special user " + targetUserHandle);
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001550 }
Cassie Wang4bff4ff2021-07-16 13:03:19 -07001551
Cassie Wang2e2d0552021-08-04 16:18:10 +00001552 if (mContext.checkPermission(
1553 Manifest.permission.INTERACT_ACROSS_USERS_FULL,
1554 callingPid,
1555 callingUid) == PackageManager.PERMISSION_GRANTED) {
1556 return targetUserHandle;
1557 }
Alexander Dorokhine5c416772021-06-04 09:05:00 -07001558 throw new SecurityException(
Cassie Wang2e2d0552021-08-04 16:18:10 +00001559 "Permission denied while calling from uid " + callingUid
1560 + " with " + targetUserHandle + "; Requires permission: "
1561 + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
Terry Wangf2093072020-11-30 04:47:19 -08001562 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001563
Cassie Wang84e33a02021-06-18 14:13:31 -07001564 /**
Cassie Wangd51ed162021-07-29 22:22:30 +00001565 * Verify various aspects of the calling user.
Cassie Wang84e33a02021-06-18 14:13:31 -07001566 *
Cassie Wangd51ed162021-07-29 22:22:30 +00001567 * @param callingUid Uid of the caller, usually retrieved from Binder for authenticity.
1568 * @param claimedCallingPackage Package name the caller claims to be.
1569 */
1570 private void verifyCaller(int callingUid, @NonNull String claimedCallingPackage) {
1571 // Obtain the user where the client is running in. Note that this could be different from
1572 // the userHandle where the client wants to run the AppSearch operation in.
1573 UserHandle callingUserHandle = UserHandle.getUserHandleForUid(callingUid);
1574 Context callingUserContext = mContext.createContextAsUser(callingUserHandle,
1575 /*flags=*/ 0);
1576
1577 verifyCallingPackage(callingUserContext, callingUid, claimedCallingPackage);
1578 verifyNotInstantApp(callingUserContext, claimedCallingPackage);
1579 }
1580
1581 /**
1582 * Check that the caller's supposed package name matches the uid making the call.
1583 *
1584 * @throws SecurityException if the package name and uid don't match.
1585 */
1586 private void verifyCallingPackage(
1587 @NonNull Context actualCallingUserContext,
1588 int actualCallingUid,
1589 @NonNull String claimedCallingPackage) {
1590 int claimedCallingUid = PackageUtil.getPackageUid(
1591 actualCallingUserContext, claimedCallingPackage);
Cassie Wangd51ed162021-07-29 22:22:30 +00001592 if (claimedCallingUid != actualCallingUid) {
1593 throw new SecurityException(
1594 "Specified calling package ["
1595 + claimedCallingPackage
1596 + "] does not match the calling uid "
1597 + actualCallingUid);
1598 }
1599 }
1600
1601 /**
1602 * Ensure instant apps can't make calls to AppSearch.
1603 *
Cassie Wang84e33a02021-06-18 14:13:31 -07001604 * @throws SecurityException if the caller is an instant app.
1605 */
1606 private void verifyNotInstantApp(@NonNull Context userContext, @NonNull String packageName) {
1607 PackageManager callingPackageManager = userContext.getPackageManager();
1608 if (callingPackageManager.isInstantApp(packageName)) {
1609 throw new SecurityException("Caller not allowed to create AppSearch session"
1610 + "; userHandle=" + userContext.getUser() + ", callingPackage=" + packageName);
1611 }
1612 }
1613
Yang Yu0fcd51a2021-04-23 11:25:44 -07001614 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1615 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001616 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001617 @NonNull PackageStats stats,
1618 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001619 @NonNull UserHandle userHandle,
1620 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001621 Objects.requireNonNull(stats);
1622 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001623 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001624
Yang Yu0fcd51a2021-04-23 11:25:44 -07001625 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001626 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001627 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001628 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1629 if (instance == null) {
1630 // augment storage info from file
1631 UserStorageInfo userStorageInfo =
1632 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1633 userHandle);
1634 stats.dataSize +=
1635 userStorageInfo.getSizeBytesForPackage(packageName);
1636 } else {
1637 stats.dataSize += instance.getAppSearchImpl()
1638 .getStorageInfoForPackage(packageName).getSizeBytes();
1639 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001640 } catch (Throwable t) {
1641 Log.e(
1642 TAG,
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001643 "Unable to augment storage stats for "
1644 + userHandle
Yang Yu0fcd51a2021-04-23 11:25:44 -07001645 + " packageName "
1646 + packageName,
1647 t);
1648 }
1649 }
1650
1651 @Override
1652 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001653 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001654 Objects.requireNonNull(stats);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001655
1656 UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001657 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001658 verifyUserUnlocked(userHandle);
Yang Yu0fcd51a2021-04-23 11:25:44 -07001659 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1660 if (packagesForUid == null) {
1661 return;
1662 }
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001663 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001664 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1665 if (instance == null) {
1666 // augment storage info from file
1667 UserStorageInfo userStorageInfo =
1668 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1669 userHandle);
1670 for (int i = 0; i < packagesForUid.length; i++) {
1671 stats.dataSize += userStorageInfo.getSizeBytesForPackage(
1672 packagesForUid[i]);
1673 }
1674 } else {
1675 for (int i = 0; i < packagesForUid.length; i++) {
1676 stats.dataSize += instance.getAppSearchImpl()
1677 .getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
1678 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001679 }
1680 } catch (Throwable t) {
1681 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1682 }
1683 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001684
1685 @Override
1686 public void augmentStatsForUser(
1687 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1688 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1689 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1690 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1691 Objects.requireNonNull(stats);
1692 Objects.requireNonNull(userHandle);
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001693
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001694 try {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001695 verifyUserUnlocked(userHandle);
Alexander Dorokhine4d051632021-06-18 10:48:58 -07001696 AppSearchUserInstance instance =
Yang Yuc047f7b2021-06-25 12:22:42 -07001697 mAppSearchUserInstanceManager.getUserInstanceOrNull(userHandle);
1698 if (instance == null) {
1699 // augment storage info from file
1700 UserStorageInfo userStorageInfo =
1701 mAppSearchUserInstanceManager.getOrCreateUserStorageInfoInstance(
1702 userHandle);
1703 stats.dataSize += userStorageInfo.getTotalSizeBytes();
1704 } else {
1705 List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
1706 /*flags=*/0, userHandle.getIdentifier());
1707 if (packagesForUser != null) {
1708 for (int i = 0; i < packagesForUser.size(); i++) {
1709 String packageName = packagesForUser.get(i).packageName;
1710 stats.dataSize += instance.getAppSearchImpl()
1711 .getStorageInfoForPackage(packageName).getSizeBytes();
1712 }
1713 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001714 }
1715 } catch (Throwable t) {
Alexander Dorokhinebea55602021-05-19 13:59:45 -07001716 Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001717 }
1718 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001719 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001720
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001721 /**
1722 * Dispatches change notifications if there are any to dispatch.
1723 *
1724 * <p>This method is async; notifications are dispatched onto their own registered executors.
1725 *
1726 * <p>IMPORTANT: You must always call this within the background task that contains the
1727 * operation that mutated the index. If you called it outside of that task, it could start
1728 * before the task completes, causing notifications to be missed.
1729 */
1730 @WorkerThread
1731 private void dispatchChangeNotifications(@NonNull AppSearchUserInstance instance) {
1732 instance.getAppSearchImpl().dispatchAndClearChangeNotifications();
1733 }
1734
1735 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001736 private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) {
1737 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001738 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1739 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001740 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001741 instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001742 } catch (AppSearchException e) {
1743 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001744 } finally {
1745 OptimizeStats oStats = builder
1746 .setTotalLatencyMillis(
1747 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1748 .build();
1749 if (oStats.getOriginalDocumentCount() > 0) {
1750 // see if optimize has been run by checking originalDocumentCount
1751 instance.getLogger().logStats(oStats);
1752 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001753 }
1754 });
1755 }
1756
Alexander Dorokhinee0587d32021-12-07 17:02:17 -08001757 @WorkerThread
Terry Wangf4d219b2021-07-01 19:11:39 -07001758 private void checkForOptimize(AppSearchUserInstance instance) {
1759 EXECUTOR.execute(() -> {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001760 long totalLatencyStartMillis = SystemClock.elapsedRealtime();
1761 OptimizeStats.Builder builder = new OptimizeStats.Builder();
Terry Wangf4d219b2021-07-01 19:11:39 -07001762 try {
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001763 instance.getAppSearchImpl().checkForOptimize(builder);
Terry Wangf4d219b2021-07-01 19:11:39 -07001764 } catch (AppSearchException e) {
1765 Log.w(TAG, "Error occurred when check for optimize", e);
Alexander Dorokhine14816e22021-07-12 10:53:24 -07001766 } finally {
1767 OptimizeStats oStats = builder
1768 .setTotalLatencyMillis(
1769 (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
1770 .build();
1771 if (oStats.getOriginalDocumentCount() > 0) {
1772 // see if optimize has been run by checking originalDocumentCount
1773 instance.getLogger().logStats(oStats);
1774 }
Terry Wangf4d219b2021-07-01 19:11:39 -07001775 }
1776 });
1777 }
Terry Wangfebbead2019-10-17 17:05:18 -07001778}