blob: 58ce6e56de595cd0e7ea63adeccc4cd55d302cc8 [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 Wang12dc6c02021-03-31 19:26:16 -070020import static android.os.UserHandle.USER_NULL;
Terry Wangdbd1dca2020-11-03 17:03:56 -080021
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080022import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080023import android.annotation.NonNull;
Terry Wangf2093072020-11-30 04:47:19 -080024import android.annotation.UserIdInt;
25import android.app.ActivityManager;
Alexander Dorokhine18465842020-01-21 01:08:57 -080026import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080027import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080028import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070029import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070030import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070031import android.app.appsearch.GetSchemaResponse;
Alexander Dorokhineab789062021-01-11 21:00:00 -080032import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070033import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070034import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080035import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070036import android.app.appsearch.StorageInfo;
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -070037import android.app.appsearch.aidl.AppSearchBatchResultParcel;
38import android.app.appsearch.aidl.AppSearchResultParcel;
39import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
40import android.app.appsearch.aidl.IAppSearchManager;
41import android.app.appsearch.aidl.IAppSearchResultCallback;
Terry Wang12dc6c02021-03-31 19:26:16 -070042import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070043import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070044import android.content.Intent;
45import android.content.IntentFilter;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070046import android.content.pm.PackageInfo;
Yang Yu0fcd51a2021-04-23 11:25:44 -070047import android.content.pm.PackageManager;
Cassie Wang0c62d992021-01-15 14:39:30 -080048import android.content.pm.PackageManagerInternal;
Yang Yu0fcd51a2021-04-23 11:25:44 -070049import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080050import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070051import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080052import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080053import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080054import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080055import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070056import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080057import android.util.ArrayMap;
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;
Cassie Wang0c62d992021-01-15 14:39:30 -080063import com.android.server.LocalServices;
Terry Wangfebbead2019-10-17 17:05:18 -070064import com.android.server.SystemService;
Alexander Dorokhinef660d8f2020-10-29 22:37:00 -070065import com.android.server.appsearch.external.localstorage.AppSearchImpl;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080066import com.android.server.appsearch.external.localstorage.stats.CallStats;
67import com.android.server.appsearch.stats.LoggerInstanceManager;
68import com.android.server.appsearch.stats.PlatformLogger;
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -070069import com.android.server.usage.StorageStatsManagerLocal;
70import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080071
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070072import com.google.android.icing.proto.PersistType;
73
Terry Wang623e3b02021-02-02 20:27:33 -080074import java.io.DataInputStream;
75import java.io.DataOutputStream;
76import java.io.EOFException;
77import java.io.FileInputStream;
78import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080079import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080080import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080081import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080082import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080083import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070084import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070085import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070086import java.util.concurrent.ThreadPoolExecutor;
87import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080088
Cassie Wang0c62d992021-01-15 14:39:30 -080089/** TODO(b/142567528): add comments when implement this class */
Terry Wangfebbead2019-10-17 17:05:18 -070090public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070091 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070092 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070093 private PackageManager mPackageManager;
Cassie Wang0c62d992021-01-15 14:39:30 -080094 private PackageManagerInternal mPackageManagerInternal;
Cassie Wang21c2d6a2021-01-20 23:59:55 -080095 private ImplInstanceManager mImplInstanceManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070096 private UserManager mUserManager;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080097 private LoggerInstanceManager mLoggerInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -070098
Terry Wange04ceab2021-03-29 19:25:12 -070099 // Never call shutdownNow(). It will cancel the futures it's returned. And since
100 // Executor#execute won't return anything, we will hang forever waiting for the execution.
101 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
102 // mutate requests will need to gain write lock and query requests need to gain read lock.
103 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
104 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700105 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700106
Cassie Wang15c86972021-02-09 13:43:25 -0800107 // Cache of unlocked user ids so we don't have to query UserManager service each time. The
108 // "locked" suffix refers to the fact that access to the field should be locked; unrelated to
109 // the unlocked status of user ids.
110 @GuardedBy("mUnlockedUserIdsLocked")
111 private final Set<Integer> mUnlockedUserIdsLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800112
Terry Wangfebbead2019-10-17 17:05:18 -0700113 public AppSearchManagerService(Context context) {
114 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700115 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700116 }
117
118 @Override
119 public void onStart() {
120 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700121 mPackageManager = getContext().getPackageManager();
Cassie Wang0c62d992021-01-15 14:39:30 -0800122 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
Terry Wang12dc6c02021-03-31 19:26:16 -0700123 mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
124 mUserManager = mContext.getSystemService(UserManager.class);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800125 mLoggerInstanceManager = LoggerInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700126 registerReceivers();
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -0700127 LocalManagerRegistry.getManager(StorageStatsManagerLocal.class)
Yang Yu0fcd51a2021-04-23 11:25:44 -0700128 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700129 }
130
131 private void registerReceivers() {
132 mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
133 new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
134 /*scheduler=*/ null);
Terry Wange201dc02021-04-16 01:03:20 -0700135
136 //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
137 // broadcasts
138 IntentFilter packageChangedFilter = new IntentFilter();
139 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED);
140 packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
141 packageChangedFilter.addDataScheme("package");
142 packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
143 mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
144 packageChangedFilter, /*broadcastPermission=*/ null,
145 /*scheduler=*/ null);
Terry Wang12dc6c02021-03-31 19:26:16 -0700146 }
147
148 private class UserActionReceiver extends BroadcastReceiver {
149 @Override
150 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
151 switch (intent.getAction()) {
152 case Intent.ACTION_USER_REMOVED:
Terry Wange201dc02021-04-16 01:03:20 -0700153 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
Terry Wang12dc6c02021-03-31 19:26:16 -0700154 if (userId == USER_NULL) {
Terry Wange201dc02021-04-16 01:03:20 -0700155 Log.e(TAG, "userId is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700156 return;
157 }
158 handleUserRemoved(userId);
159 break;
160 default:
Terry Wange201dc02021-04-16 01:03:20 -0700161 Log.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700162 }
163 }
164 }
165
166 /**
167 * Handles user removed action.
168 *
169 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
170 * "credential encrypted" system directory of each user. That directory will be auto-deleted
171 * when a user is removed.
172 *
173 * @param userId The multi-user userId of the user that need to be removed.
174 *
175 * @see android.os.Environment#getDataSystemCeDirectory
176 */
177 private void handleUserRemoved(@UserIdInt int userId) {
178 try {
179 mImplInstanceManager.removeAppSearchImplForUser(userId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800180 mLoggerInstanceManager.removePlatformLoggerForUser(userId);
Terry Wange201dc02021-04-16 01:03:20 -0700181 Log.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
Terry Wang12dc6c02021-03-31 19:26:16 -0700182 } catch (Throwable t) {
Terry Wange201dc02021-04-16 01:03:20 -0700183 Log.e(TAG, "Unable to remove data for user: " + userId, t);
184 }
185 }
186
187 private class PackageChangedReceiver extends BroadcastReceiver {
188 @Override
189 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
190 switch (intent.getAction()) {
191 case Intent.ACTION_PACKAGE_FULLY_REMOVED:
192 case Intent.ACTION_PACKAGE_DATA_CLEARED:
193 String packageName = intent.getData().getSchemeSpecificPart();
194 if (packageName == null) {
195 Log.e(TAG, "Package name is missing in the intent: " + intent);
196 return;
197 }
198 int uid = intent.getIntExtra(Intent.EXTRA_UID, INVALID_UID);
199 if (uid == INVALID_UID) {
200 Log.e(TAG, "uid is missing in the intent: " + intent);
201 return;
202 }
203 handlePackageRemoved(packageName, uid);
204 break;
205 default:
206 Log.e(TAG, "Received unknown intent: " + intent);
207 }
208 }
209 }
210
211 private void handlePackageRemoved(String packageName, int uid) {
212 int userId = UserHandle.getUserId(uid);
213 try {
214 if (isUserLocked(userId)) {
215 //TODO(b/186151459) clear the uninstalled package data when user is unlocked.
216 return;
217 }
218 if (ImplInstanceManager.getAppSearchDir(userId).exists()) {
219 // Only clear the package's data if AppSearch exists for this user.
220 AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
221 userId);
222 //TODO(b/145759910) clear visibility setting for package.
223 impl.clearPackageData(packageName);
224 }
225 } catch (Throwable t) {
226 Log.e(TAG, "Unable to remove data for package: " + packageName, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700227 }
Terry Wangfebbead2019-10-17 17:05:18 -0700228 }
229
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800230 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700231 public void onUserUnlocking(@NonNull TargetUser user) {
Cassie Wang15c86972021-02-09 13:43:25 -0800232 synchronized (mUnlockedUserIdsLocked) {
233 mUnlockedUserIdsLocked.add(user.getUserIdentifier());
234 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800235 }
236
Terry Wangde9f3382021-04-28 19:45:07 -0700237 @Override
238 public void onUserStopping(@NonNull TargetUser user) {
239 synchronized (mUnlockedUserIdsLocked) {
240 mUnlockedUserIdsLocked.remove(user.getUserIdentifier());
241 try {
242 mImplInstanceManager.closeAndRemoveAppSearchImplForUser(user.getUserIdentifier());
243 } catch (Throwable t) {
244 Log.e(TAG, "Error handling user stopping.", t);
245 }
246 }
247 }
248
Yang Yu0fcd51a2021-04-23 11:25:44 -0700249 private void verifyUserUnlocked(int callingUserId) {
Terry Wange201dc02021-04-16 01:03:20 -0700250 if (isUserLocked(callingUserId)) {
251 throw new IllegalStateException("User " + callingUserId + " is locked or not running.");
252 }
253 }
254
255 private boolean isUserLocked(int callingUserId) {
Yang Yu0fcd51a2021-04-23 11:25:44 -0700256 synchronized (mUnlockedUserIdsLocked) {
257 // First, check the local copy.
258 if (mUnlockedUserIdsLocked.contains(callingUserId)) {
Terry Wange201dc02021-04-16 01:03:20 -0700259 return false;
Yang Yu0fcd51a2021-04-23 11:25:44 -0700260 }
261 // If the local copy says the user is locked, check with UM for the actual state,
262 // since the user might just have been unlocked.
Terry Wange201dc02021-04-16 01:03:20 -0700263 return !mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId));
Yang Yu0fcd51a2021-04-23 11:25:44 -0700264 }
265 }
266
Terry Wangfebbead2019-10-17 17:05:18 -0700267 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800268 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800269 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800270 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700271 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700272 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800273 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhineab789062021-01-11 21:00:00 -0800274 @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800275 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700276 int schemaVersion,
Terry Wangc10610d2021-03-21 13:21:24 -0700277 @UserIdInt int userId,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700278 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800279 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700280 Objects.requireNonNull(packageName);
281 Objects.requireNonNull(databaseName);
282 Objects.requireNonNull(schemaBundles);
283 Objects.requireNonNull(callback);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700284 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800285 int callingUid = Binder.getCallingUid();
286 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700287 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700288 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
289 PlatformLogger logger = null;
290 int operationSuccessCount = 0;
291 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700292 try {
293 verifyUserUnlocked(callingUserId);
294 verifyCallingPackage(callingUid, packageName);
295 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
296 for (int i = 0; i < schemaBundles.size(); i++) {
297 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800298 }
Terry Wange04ceab2021-03-29 19:25:12 -0700299 Map<String, List<PackageIdentifier>> schemasPackageAccessible =
300 new ArrayMap<>(schemasPackageAccessibleBundles.size());
301 for (Map.Entry<String, List<Bundle>> entry :
302 schemasPackageAccessibleBundles.entrySet()) {
303 List<PackageIdentifier> packageIdentifiers =
304 new ArrayList<>(entry.getValue().size());
305 for (int i = 0; i < entry.getValue().size(); i++) {
306 packageIdentifiers.add(
307 new PackageIdentifier(entry.getValue().get(i)));
308 }
309 schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
310 }
311 AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700312 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700313 SetSchemaResponse setSchemaResponse = impl.setSchema(
314 packageName,
315 databaseName,
316 schemas,
317 schemasNotDisplayedBySystem,
318 schemasPackageAccessible,
319 forceOverride,
320 schemaVersion);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700321 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700322 invokeCallbackOnResult(callback,
323 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
324 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700325 ++operationFailureCount;
326 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700327 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700328 } finally {
329 if (logger != null) {
330 int estimatedBinderLatencyMillis =
331 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
332 int totalLatencyMillis =
333 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
334 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
335 databaseName)
336 .setCallType(CallStats.CALL_TYPE_SET_SCHEMA)
337 // TODO(b/173532925) check the existing binder call latency chart
338 // is good enough for us:
339 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
340 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
341 .setNumOperationsSucceeded(operationSuccessCount)
342 .setNumOperationsFailed(operationFailureCount);
343 cBuilder.getGeneralStatsBuilder()
344 .setStatusCode(statusCode)
345 .setTotalLatencyMillis(totalLatencyMillis);
346 logger.logStats(cBuilder.build());
347 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800348 }
Terry Wange04ceab2021-03-29 19:25:12 -0700349 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800350 }
351
352 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800353 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800354 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800355 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -0800356 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -0800357 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700358 Objects.requireNonNull(packageName);
359 Objects.requireNonNull(databaseName);
360 Objects.requireNonNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700361 int callingUid = Binder.getCallingUid();
Terry Wangf2093072020-11-30 04:47:19 -0800362 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700363 EXECUTOR.execute(() -> {
364 try {
365 verifyUserUnlocked(callingUserId);
366 verifyCallingPackage(callingUid, packageName);
367 AppSearchImpl impl =
368 mImplInstanceManager.getAppSearchImpl(callingUserId);
369 GetSchemaResponse response = impl.getSchema(packageName, databaseName);
370 invokeCallbackOnResult(
371 callback,
372 AppSearchResult.newSuccessfulResult(response.getBundle()));
373 } catch (Throwable t) {
374 invokeCallbackOnError(callback, t);
375 }
376 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700377 }
378
379 @Override
380 public void getNamespaces(
381 @NonNull String packageName,
382 @NonNull String databaseName,
383 @UserIdInt int userId,
384 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700385 Objects.requireNonNull(packageName);
386 Objects.requireNonNull(databaseName);
387 Objects.requireNonNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700388 int callingUid = Binder.getCallingUid();
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700389 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700390 EXECUTOR.execute(() -> {
391 try {
392 verifyUserUnlocked(callingUserId);
393 verifyCallingPackage(callingUid, packageName);
394 AppSearchImpl impl =
395 mImplInstanceManager.getAppSearchImpl(callingUserId);
396 List<String> namespaces = impl.getNamespaces(packageName, databaseName);
397 invokeCallbackOnResult(callback,
398 AppSearchResult.newSuccessfulResult(namespaces));
399 } catch (Throwable t) {
400 invokeCallbackOnError(callback, t);
401 }
402 });
Terry Wang83a24932020-12-09 21:00:18 -0800403 }
404
405 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800406 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800407 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700408 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700409 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800410 @UserIdInt int userId,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800411 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800412 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700413 Objects.requireNonNull(packageName);
414 Objects.requireNonNull(databaseName);
415 Objects.requireNonNull(documentBundles);
416 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800417 int callingUid = Binder.getCallingUid();
418 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700419 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800420 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
421 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
422 PlatformLogger logger = null;
423 int operationSuccessCount = 0;
424 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700425 try {
426 verifyUserUnlocked(callingUserId);
427 verifyCallingPackage(callingUid, packageName);
428 AppSearchBatchResult.Builder<String, Void> resultBuilder =
429 new AppSearchBatchResult.Builder<>();
430 AppSearchImpl impl =
431 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800432 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700433 for (int i = 0; i < documentBundles.size(); i++) {
434 GenericDocument document = new GenericDocument(documentBundles.get(i));
435 try {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800436 impl.putDocument(packageName, databaseName, document, logger);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700437 resultBuilder.setSuccess(document.getId(), /*result=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800438 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700439 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700440 resultBuilder.setResult(document.getId(),
Terry Wange04ceab2021-03-29 19:25:12 -0700441 throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800442 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700443 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700444 // Since we can only include one status code in the atom,
445 // for failures, we would just save the one for the last failure
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800446 statusCode = result.getResultCode();
447 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700448 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800449 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700450 // Now that the batch has been written. Persist the newly written data.
451 impl.persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700452 invokeCallbackOnResult(callback, resultBuilder.build());
453 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700454 ++operationFailureCount;
455 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700456 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800457 } finally {
458 if (logger != null) {
459 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
460 databaseName)
461 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
462 // TODO(b/173532925) check the existing binder call latency chart
463 // is good enough for us:
464 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
465 .setEstimatedBinderLatencyMillis(
466 2 * (int) (totalLatencyStartTimeMillis
467 - binderCallStartTimeMillis))
468 .setNumOperationsSucceeded(operationSuccessCount)
469 .setNumOperationsFailed(operationFailureCount);
470 cBuilder.getGeneralStatsBuilder()
471 .setStatusCode(statusCode)
472 .setTotalLatencyMillis(
473 (int) (SystemClock.elapsedRealtime()
474 - totalLatencyStartTimeMillis));
475 logger.logStats(cBuilder.build());
476 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800477 }
Terry Wange04ceab2021-03-29 19:25:12 -0700478 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800479 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800480
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800481 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800482 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800483 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800484 @NonNull String databaseName,
485 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700486 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800487 @NonNull Map<String, List<String>> typePropertyPaths,
Terry Wangf2093072020-11-30 04:47:19 -0800488 @UserIdInt int userId,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700489 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800490 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700491 Objects.requireNonNull(packageName);
492 Objects.requireNonNull(databaseName);
493 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700494 Objects.requireNonNull(ids);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700495 Objects.requireNonNull(callback);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700496 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800497 int callingUid = Binder.getCallingUid();
498 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700499 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700500 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
501 PlatformLogger logger = null;
502 int operationSuccessCount = 0;
503 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700504 try {
505 verifyUserUnlocked(callingUserId);
506 verifyCallingPackage(callingUid, packageName);
507 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
508 new AppSearchBatchResult.Builder<>();
509 AppSearchImpl impl =
510 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700511 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700512 for (int i = 0; i < ids.size(); i++) {
513 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700514 try {
515 GenericDocument document =
516 impl.getDocument(
517 packageName,
518 databaseName,
519 namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700520 id,
Terry Wange04ceab2021-03-29 19:25:12 -0700521 typePropertyPaths);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700522 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700523 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700524 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700525 // Since we can only include one status code in the atom,
526 // for failures, we would just save the one for the last failure
527 AppSearchResult<Bundle> result = throwableToFailedResult(t);
528 resultBuilder.setResult(id, result);
529 statusCode = result.getResultCode();
530 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700531 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800532 }
Terry Wange04ceab2021-03-29 19:25:12 -0700533 invokeCallbackOnResult(callback, resultBuilder.build());
534 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700535 ++operationFailureCount;
536 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700537 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700538 } finally {
539 if (logger != null) {
540 int estimatedBinderLatencyMillis =
541 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
542 int totalLatencyMillis =
543 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
544 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
545 databaseName)
546 .setCallType(CallStats.CALL_TYPE_GET_DOCUMENTS)
547 // TODO(b/173532925) check the existing binder call latency chart
548 // is good enough for us:
549 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
550 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
551 .setNumOperationsSucceeded(operationSuccessCount)
552 .setNumOperationsFailed(operationFailureCount);
553 cBuilder.getGeneralStatsBuilder()
554 .setStatusCode(statusCode)
555 .setTotalLatencyMillis(totalLatencyMillis);
556 logger.logStats(cBuilder.build());
557 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800558 }
Terry Wange04ceab2021-03-29 19:25:12 -0700559 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800560 }
561
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800562 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800563 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800564 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700565 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700566 @NonNull String queryExpression,
567 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800568 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700569 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700570 Objects.requireNonNull(packageName);
571 Objects.requireNonNull(databaseName);
572 Objects.requireNonNull(queryExpression);
573 Objects.requireNonNull(searchSpecBundle);
574 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800575 int callingUid = Binder.getCallingUid();
576 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700577 EXECUTOR.execute(() -> {
578 try {
579 verifyUserUnlocked(callingUserId);
580 verifyCallingPackage(callingUid, packageName);
581 AppSearchImpl impl =
582 mImplInstanceManager.getAppSearchImpl(callingUserId);
583 SearchResultPage searchResultPage =
584 impl.query(
585 packageName,
586 databaseName,
587 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700588 new SearchSpec(searchSpecBundle),
589 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700590 invokeCallbackOnResult(
591 callback,
592 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
593 } catch (Throwable t) {
594 invokeCallbackOnError(callback, t);
595 }
596 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700597 }
598
Terry Wangf2093072020-11-30 04:47:19 -0800599 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800600 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800601 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800602 @NonNull String queryExpression,
603 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800604 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800605 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700606 Objects.requireNonNull(packageName);
607 Objects.requireNonNull(queryExpression);
608 Objects.requireNonNull(searchSpecBundle);
609 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800610 int callingUid = Binder.getCallingUid();
611 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700612 EXECUTOR.execute(() -> {
613 try {
614 verifyUserUnlocked(callingUserId);
615 verifyCallingPackage(callingUid, packageName);
616 AppSearchImpl impl =
617 mImplInstanceManager.getAppSearchImpl(callingUserId);
618 SearchResultPage searchResultPage =
619 impl.globalQuery(
620 queryExpression,
621 new SearchSpec(searchSpecBundle),
622 packageName,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700623 callingUid,
624 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700625 invokeCallbackOnResult(
626 callback,
627 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
628 } catch (Throwable t) {
629 invokeCallbackOnError(callback, t);
630 }
631 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800632 }
633
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700634 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800635 public void getNextPage(
636 long nextPageToken,
637 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700638 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700639 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800640 int callingUid = Binder.getCallingUid();
641 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700642 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
643 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700644 EXECUTOR.execute(() -> {
645 try {
646 verifyUserUnlocked(callingUserId);
647 AppSearchImpl impl =
648 mImplInstanceManager.getAppSearchImpl(callingUserId);
649 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
650 invokeCallbackOnResult(
651 callback,
652 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
653 } catch (Throwable t) {
654 invokeCallbackOnError(callback, t);
655 }
656 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700657 }
658
659 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800660 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
661 int callingUid = Binder.getCallingUid();
662 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700663 EXECUTOR.execute(() -> {
664 try {
665 verifyUserUnlocked(callingUserId);
666 AppSearchImpl impl =
667 mImplInstanceManager.getAppSearchImpl(callingUserId);
668 impl.invalidateNextPageToken(nextPageToken);
669 } catch (Throwable t) {
670 Log.e(TAG, "Unable to invalidate the query page token", t);
671 }
672 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800673 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800674
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700675 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800676 public void writeQueryResultsToFile(
677 @NonNull String packageName,
678 @NonNull String databaseName,
679 @NonNull ParcelFileDescriptor fileDescriptor,
680 @NonNull String queryExpression,
681 @NonNull Bundle searchSpecBundle,
682 @UserIdInt int userId,
683 @NonNull IAppSearchResultCallback callback) {
684 int callingUid = Binder.getCallingUid();
685 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700686 EXECUTOR.execute(() -> {
687 try {
688 verifyCallingPackage(callingUid, packageName);
689 AppSearchImpl impl =
690 mImplInstanceManager.getAppSearchImpl(callingUserId);
691 // we don't need to append the file. The file is always brand new.
692 try (DataOutputStream outputStream = new DataOutputStream(
693 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
694 SearchResultPage searchResultPage = impl.query(
695 packageName,
696 databaseName,
697 queryExpression,
Alexander Dorokhine7cbc4712021-04-27 14:47:39 -0700698 new SearchSpec(searchSpecBundle),
699 /*logger=*/ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700700 while (!searchResultPage.getResults().isEmpty()) {
701 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
702 AppSearchMigrationHelper.writeBundleToOutputStream(
703 outputStream, searchResultPage.getResults().get(i)
704 .getGenericDocument().getBundle());
705 }
706 searchResultPage = impl.getNextPage(
707 searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800708 }
Terry Wang623e3b02021-02-02 20:27:33 -0800709 }
Terry Wange04ceab2021-03-29 19:25:12 -0700710 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
711 } catch (Throwable t) {
712 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800713 }
Terry Wange04ceab2021-03-29 19:25:12 -0700714 });
Terry Wang623e3b02021-02-02 20:27:33 -0800715 }
716
717 @Override
718 public void putDocumentsFromFile(
719 @NonNull String packageName,
720 @NonNull String databaseName,
721 @NonNull ParcelFileDescriptor fileDescriptor,
722 @UserIdInt int userId,
723 @NonNull IAppSearchResultCallback callback) {
724 int callingUid = Binder.getCallingUid();
725 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700726 EXECUTOR.execute(() -> {
727 try {
728 verifyCallingPackage(callingUid, packageName);
729 AppSearchImpl impl =
730 mImplInstanceManager.getAppSearchImpl(callingUserId);
Terry Wang623e3b02021-02-02 20:27:33 -0800731
Terry Wange04ceab2021-03-29 19:25:12 -0700732 GenericDocument document;
733 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
734 try (DataInputStream inputStream = new DataInputStream(
735 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
736 while (true) {
737 try {
738 document = AppSearchMigrationHelper
739 .readDocumentFromInputStream(inputStream);
740 } catch (EOFException e) {
741 // nothing wrong, we just finish the reading.
742 break;
743 }
744 try {
745 impl.putDocument(packageName, databaseName, document,
746 /*logger=*/ null);
747 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700748 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
749 document.getNamespace(),
750 document.getId(),
751 document.getSchemaType(),
752 AppSearchResult.throwableToFailedResult(t))
753 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700754 }
Terry Wang623e3b02021-02-02 20:27:33 -0800755 }
756 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700757 impl.persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700758 invokeCallbackOnResult(callback,
759 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
760 } catch (Throwable t) {
761 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800762 }
Terry Wange04ceab2021-03-29 19:25:12 -0700763 });
Terry Wang623e3b02021-02-02 20:27:33 -0800764 }
765
766 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800767 public void reportUsage(
768 @NonNull String packageName,
769 @NonNull String databaseName,
770 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700771 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800772 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700773 boolean systemUsage,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800774 @UserIdInt int userId,
775 @NonNull IAppSearchResultCallback callback) {
776 Objects.requireNonNull(databaseName);
777 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700778 Objects.requireNonNull(documentId);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800779 Objects.requireNonNull(callback);
780 int callingUid = Binder.getCallingUid();
781 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700782 EXECUTOR.execute(() -> {
783 try {
784 verifyUserUnlocked(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700785
Terry Wange04ceab2021-03-29 19:25:12 -0700786 if (systemUsage) {
787 // TODO(b/183031844): Validate that the call comes from the system
788 }
789
790 AppSearchImpl impl =
791 mImplInstanceManager.getAppSearchImpl(callingUserId);
792 impl.reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700793 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -0700794 usageTimeMillis, systemUsage);
795 invokeCallbackOnResult(
796 callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
797 } catch (Throwable t) {
798 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700799 }
Terry Wange04ceab2021-03-29 19:25:12 -0700800 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800801 }
802
803 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700804 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -0800805 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800806 @NonNull String databaseName,
807 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700808 @NonNull List<String> ids,
Terry Wangf2093072020-11-30 04:47:19 -0800809 @UserIdInt int userId,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700810 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800811 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700812 Objects.requireNonNull(packageName);
813 Objects.requireNonNull(databaseName);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700814 Objects.requireNonNull(ids);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700815 Objects.requireNonNull(callback);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700816 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800817 int callingUid = Binder.getCallingUid();
818 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700819 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700820 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
821 PlatformLogger logger = null;
822 int operationSuccessCount = 0;
823 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700824 try {
825 verifyUserUnlocked(callingUserId);
826 verifyCallingPackage(callingUid, packageName);
827 AppSearchBatchResult.Builder<String, Void> resultBuilder =
828 new AppSearchBatchResult.Builder<>();
829 AppSearchImpl impl =
830 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700831 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700832 for (int i = 0; i < ids.size(); i++) {
833 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700834 try {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700835 impl.remove(packageName, databaseName, namespace, id);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700836 ++operationSuccessCount;
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700837 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700838 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700839 AppSearchResult<Void> result = throwableToFailedResult(t);
840 resultBuilder.setResult(id, result);
841 // Since we can only include one status code in the atom,
842 // for failures, we would just save the one for the last failure
843 statusCode = result.getResultCode();
844 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700845 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700846 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700847 // Now that the batch has been written. Persist the newly written data.
848 impl.persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700849 invokeCallbackOnResult(callback, resultBuilder.build());
850 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700851 ++operationFailureCount;
852 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700853 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700854 } finally {
855 if (logger != null) {
856 int estimatedBinderLatencyMillis =
857 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
858 int totalLatencyMillis =
859 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
860 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
861 databaseName)
862 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_ID)
863 // TODO(b/173532925) check the existing binder call latency chart
864 // is good enough for us:
865 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
866 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
867 .setNumOperationsSucceeded(operationSuccessCount)
868 .setNumOperationsFailed(operationFailureCount);
869 cBuilder.getGeneralStatsBuilder()
870 .setStatusCode(statusCode)
871 .setTotalLatencyMillis(totalLatencyMillis);
872 logger.logStats(cBuilder.build());
873 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700874 }
Terry Wange04ceab2021-03-29 19:25:12 -0700875 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700876 }
877
878 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700879 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800880 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700881 @NonNull String databaseName,
882 @NonNull String queryExpression,
883 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800884 @UserIdInt int userId,
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700885 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700886 @NonNull IAppSearchResultCallback callback) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700887 // TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700888 Objects.requireNonNull(packageName);
889 Objects.requireNonNull(databaseName);
890 Objects.requireNonNull(queryExpression);
891 Objects.requireNonNull(searchSpecBundle);
892 Objects.requireNonNull(callback);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700893 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Terry Wangf2093072020-11-30 04:47:19 -0800894 int callingUid = Binder.getCallingUid();
895 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700896 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700897 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
898 PlatformLogger logger = null;
899 int operationSuccessCount = 0;
900 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700901 try {
902 verifyUserUnlocked(callingUserId);
903 verifyCallingPackage(callingUid, packageName);
904 AppSearchImpl impl =
905 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700906 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700907 impl.removeByQuery(
908 packageName,
909 databaseName,
910 queryExpression,
911 new SearchSpec(searchSpecBundle));
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700912 // Now that the batch has been written. Persist the newly written data.
913 impl.persistToDisk(PersistType.Code.LITE);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700914 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700915 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
916 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700917 ++operationFailureCount;
918 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700919 invokeCallbackOnError(callback, t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700920 } finally {
921 if (logger != null) {
922 int estimatedBinderLatencyMillis =
923 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
924 int totalLatencyMillis =
925 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
926 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
927 databaseName)
928 .setCallType(CallStats.CALL_TYPE_REMOVE_DOCUMENTS_BY_SEARCH)
929 // TODO(b/173532925) check the existing binder call latency chart
930 // is good enough for us:
931 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
932 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
933 .setNumOperationsSucceeded(operationSuccessCount)
934 .setNumOperationsFailed(operationFailureCount);
935 cBuilder.getGeneralStatsBuilder()
936 .setStatusCode(statusCode)
937 .setTotalLatencyMillis(totalLatencyMillis);
938 logger.logStats(cBuilder.build());
939 }
Terry Wange04ceab2021-03-29 19:25:12 -0700940 }
941 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700942 }
943
Terry Wangdbd1dca2020-11-03 17:03:56 -0800944 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -0700945 public void getStorageInfo(
946 @NonNull String packageName,
947 @NonNull String databaseName,
948 @UserIdInt int userId,
949 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700950 Objects.requireNonNull(packageName);
951 Objects.requireNonNull(databaseName);
952 Objects.requireNonNull(callback);
Cassie Wang8f0df492021-03-24 09:23:18 -0700953 int callingUid = Binder.getCallingUid();
954 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700955 EXECUTOR.execute(() -> {
956 try {
957 verifyUserUnlocked(callingUserId);
958 verifyCallingPackage(callingUid, packageName);
959 AppSearchImpl impl =
960 mImplInstanceManager.getAppSearchImpl(callingUserId);
961 StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
962 databaseName);
963 Bundle storageInfoBundle = storageInfo.getBundle();
964 invokeCallbackOnResult(
965 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
966 } catch (Throwable t) {
967 invokeCallbackOnError(callback, t);
968 }
969 });
Cassie Wang8f0df492021-03-24 09:23:18 -0700970 }
971
972 @Override
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700973 public void persistToDisk(@UserIdInt int userId,
974 @ElapsedRealtimeLong long binderCallStartTimeMillis) {
975 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
Cassie Wangb0d60122021-03-30 12:38:46 -0700976 int callingUid = Binder.getCallingUid();
Terry Wang2da17852020-12-16 19:59:08 -0800977 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700978 EXECUTOR.execute(() -> {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700979 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
980 PlatformLogger logger = null;
981 int operationSuccessCount = 0;
982 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700983 try {
984 verifyUserUnlocked(callingUserId);
985 AppSearchImpl impl =
986 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700987 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700988 impl.persistToDisk(PersistType.Code.FULL);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700989 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700990 } catch (Throwable t) {
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700991 ++operationFailureCount;
992 statusCode = throwableToFailedResult(t).getResultCode();
Terry Wange04ceab2021-03-29 19:25:12 -0700993 Log.e(TAG, "Unable to persist the data to disk", t);
Xiaoyu Jinc5a75772021-05-09 20:12:44 -0700994 } finally {
995 if (logger != null) {
996 int estimatedBinderLatencyMillis =
997 2 * (int) (totalLatencyStartTimeMillis - binderCallStartTimeMillis);
998 int totalLatencyMillis =
999 (int) (SystemClock.elapsedRealtime() - totalLatencyStartTimeMillis);
1000 CallStats.Builder cBuilder = new CallStats.Builder(/*packageName=*/ "",
1001 /*databaseName=*/ "")
1002 .setCallType(CallStats.CALL_TYPE_FLUSH)
1003 // TODO(b/173532925) check the existing binder call latency chart
1004 // is good enough for us:
1005 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
1006 .setEstimatedBinderLatencyMillis(estimatedBinderLatencyMillis)
1007 .setNumOperationsSucceeded(operationSuccessCount)
1008 .setNumOperationsFailed(operationFailureCount);
1009 cBuilder.getGeneralStatsBuilder()
1010 .setStatusCode(statusCode)
1011 .setTotalLatencyMillis(totalLatencyMillis);
1012 logger.logStats(cBuilder.build());
1013 }
Terry Wange04ceab2021-03-29 19:25:12 -07001014 }
1015 });
Terry Wang2da17852020-12-16 19:59:08 -08001016 }
1017
1018 @Override
Terry Wangf2093072020-11-30 04:47:19 -08001019 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001020 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -08001021 int callingUid = Binder.getCallingUid();
1022 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -07001023 EXECUTOR.execute(() -> {
1024 try {
1025 verifyUserUnlocked(callingUserId);
1026 mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -08001027 mLoggerInstanceManager.getOrCreatePlatformLogger(getContext(), callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -07001028 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
1029 } catch (Throwable t) {
1030 invokeCallbackOnError(callback, t);
1031 }
1032 });
Terry Wangdbd1dca2020-11-03 17:03:56 -08001033 }
1034
Cassie Wang0c62d992021-01-15 14:39:30 -08001035 private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -07001036 Objects.requireNonNull(callingPackage);
Cassie Wang0c62d992021-01-15 14:39:30 -08001037 if (mPackageManagerInternal.getPackageUid(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001038 callingPackage, /*flags=*/ 0, UserHandle.getUserId(callingUid))
Cassie Wang0c62d992021-01-15 14:39:30 -08001039 != callingUid) {
1040 throw new SecurityException(
1041 "Specified calling package ["
1042 + callingPackage
1043 + "] does not match the calling uid "
1044 + callingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001045 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -07001046 }
1047
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001048 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001049 private void invokeCallbackOnResult(
1050 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001051 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001052 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001053 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001054 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001055 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001056 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001057
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001058 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -08001059 private void invokeCallbackOnResult(
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001060 IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -08001061 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001062 callback.onResult(new AppSearchBatchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001063 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001064 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001065 }
Terry Wangdbd1dca2020-11-03 17:03:56 -08001066 }
1067
1068 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001069 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001070 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001071 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -08001072 */
1073 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001074 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001075 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001076 callback.onResult(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001077 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001078 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001079 }
1080 }
1081
1082 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -08001083 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001084 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001085 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -08001086 */
Cassie Wang0c62d992021-01-15 14:39:30 -08001087 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -07001088 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001089 AppSearchResult<?> result = throwableToFailedResult(throwable);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001090 try {
Alexander Dorokhined5e8eda2021-05-04 13:24:47 -07001091 callback.onSystemError(new AppSearchResultParcel<>(result));
Terry Wangdbd1dca2020-11-03 17:03:56 -08001092 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -08001093 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -08001094 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -08001095 }
Terry Wangfebbead2019-10-17 17:05:18 -07001096 }
Terry Wangf2093072020-11-30 04:47:19 -08001097
Cassie Wang0c62d992021-01-15 14:39:30 -08001098 // TODO(b/173553485) verifying that the caller has permission to access target user's data
1099 // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
1100 // TODO(b/173553485) Implement SystemService.onUserStopping()
Terry Wangf2093072020-11-30 04:47:19 -08001101 private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
1102 int callingPid = Binder.getCallingPid();
Cassie Wang0c62d992021-01-15 14:39:30 -08001103 return ActivityManager.handleIncomingUser(
1104 callingPid,
1105 callingUid,
1106 userId,
1107 /*allowAll=*/ false,
1108 /*requireFull=*/ false,
1109 /*name=*/ null,
1110 /*callerPackage=*/ null);
Terry Wangf2093072020-11-30 04:47:19 -08001111 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001112
1113 // TODO(b/179160886): Cache the previous storage stats.
1114 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
1115 @Override
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001116 public void augmentStatsForPackageForUser(
Yang Yu0fcd51a2021-04-23 11:25:44 -07001117 @NonNull PackageStats stats,
1118 @NonNull String packageName,
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001119 @NonNull UserHandle userHandle,
1120 boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001121 Objects.requireNonNull(stats);
1122 Objects.requireNonNull(packageName);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001123 Objects.requireNonNull(userHandle);
1124 int userId = userHandle.getIdentifier();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001125 try {
1126 verifyUserUnlocked(userId);
1127 AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
1128 userId);
1129 stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
1130 } catch (Throwable t) {
1131 Log.e(
1132 TAG,
1133 "Unable to augment storage stats for userId "
1134 + userId
1135 + " packageName "
1136 + packageName,
1137 t);
1138 }
1139 }
1140
1141 @Override
1142 public void augmentStatsForUid(
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001143 @NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Yang Yu0fcd51a2021-04-23 11:25:44 -07001144 Objects.requireNonNull(stats);
1145 int userId = UserHandle.getUserId(uid);
1146 try {
1147 verifyUserUnlocked(userId);
1148 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
1149 if (packagesForUid == null) {
1150 return;
1151 }
1152 AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
1153 userId);
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001154 for (int i = 0; i < packagesForUid.length; i++) {
1155 stats.dataSize +=
1156 impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
Yang Yu0fcd51a2021-04-23 11:25:44 -07001157 }
1158 } catch (Throwable t) {
1159 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
1160 }
1161 }
Alexander Dorokhinea5d0d322021-05-10 15:59:31 -07001162
1163 @Override
1164 public void augmentStatsForUser(
1165 @NonNull PackageStats stats, @NonNull UserHandle userHandle) {
1166 // TODO(b/179160886): this implementation could incur many jni calls and a lot of
1167 // in-memory processing from getStorageInfoForPackage. Instead, we can just compute the
1168 // size of the icing dir (or use the overall StorageInfo without interpolating it).
1169 Objects.requireNonNull(stats);
1170 Objects.requireNonNull(userHandle);
1171 int userId = userHandle.getIdentifier();
1172 try {
1173 verifyUserUnlocked(userId);
1174 List<PackageInfo> packagesForUser =
1175 mPackageManager.getInstalledPackagesAsUser(/*flags=*/0, userId);
1176 if (packagesForUser == null) {
1177 return;
1178 }
1179 AppSearchImpl impl =
1180 mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId);
1181 for (int i = 0; i < packagesForUser.size(); i++) {
1182 String packageName = packagesForUser.get(i).packageName;
1183 stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
1184 }
1185 } catch (Throwable t) {
1186 Log.e(TAG, "Unable to augment storage stats for user " + userId, t);
1187 }
1188 }
Yang Yu0fcd51a2021-04-23 11:25:44 -07001189 }
Terry Wangfebbead2019-10-17 17:05:18 -07001190}