blob: 7ca77d41cc89322343500688a657a1dc2fa603c6 [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 Wang12dc6c02021-03-31 19:26:16 -070019import static android.os.UserHandle.USER_NULL;
Terry Wangdbd1dca2020-11-03 17:03:56 -080020
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080021import android.annotation.ElapsedRealtimeLong;
sidchhabraa7c8f8a2020-01-16 18:38:17 -080022import android.annotation.NonNull;
Terry Wangf2093072020-11-30 04:47:19 -080023import android.annotation.UserIdInt;
24import android.app.ActivityManager;
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 Wangdbd1dca2020-11-03 17:03:56 -080031import android.app.appsearch.IAppSearchBatchResultCallback;
Terry Wangfebbead2019-10-17 17:05:18 -070032import android.app.appsearch.IAppSearchManager;
Terry Wangdbd1dca2020-11-03 17:03:56 -080033import android.app.appsearch.IAppSearchResultCallback;
Alexander Dorokhineab789062021-01-11 21:00:00 -080034import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070035import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070036import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080037import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070038import android.app.appsearch.StorageInfo;
Terry Wang12dc6c02021-03-31 19:26:16 -070039import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070040import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070041import android.content.Intent;
42import android.content.IntentFilter;
Yang Yu0fcd51a2021-04-23 11:25:44 -070043import android.content.pm.PackageManager;
Cassie Wang0c62d992021-01-15 14:39:30 -080044import android.content.pm.PackageManagerInternal;
Yang Yu0fcd51a2021-04-23 11:25:44 -070045import android.content.pm.PackageStats;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080046import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070047import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080048import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080049import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080050import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080051import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070052import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080053import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080054import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080055import android.util.Log;
Martijn Coenen9fdaf0d2021-04-15 07:18:26 +000056import android.util.Slog;
Terry Wangfebbead2019-10-17 17:05:18 -070057
Cassie Wang15c86972021-02-09 13:43:25 -080058import com.android.internal.annotations.GuardedBy;
Cassie Wang0c62d992021-01-15 14:39:30 -080059import com.android.server.LocalServices;
Terry Wangfebbead2019-10-17 17:05:18 -070060import com.android.server.SystemService;
Alexander Dorokhinef660d8f2020-10-29 22:37:00 -070061import com.android.server.appsearch.external.localstorage.AppSearchImpl;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080062import com.android.server.appsearch.external.localstorage.stats.CallStats;
63import com.android.server.appsearch.stats.LoggerInstanceManager;
64import com.android.server.appsearch.stats.PlatformLogger;
Yang Yu0fcd51a2021-04-23 11:25:44 -070065import com.android.server.usage.StorageStatsManagerInternal;
66import com.android.server.usage.StorageStatsManagerInternal.StorageStatsAugmenter;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080067
Alexander Dorokhinec77f4442021-04-14 09:26:06 -070068import com.google.android.icing.proto.PersistType;
69
Terry Wang623e3b02021-02-02 20:27:33 -080070import java.io.DataInputStream;
71import java.io.DataOutputStream;
72import java.io.EOFException;
73import java.io.FileInputStream;
74import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080075import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080076import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080077import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080078import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080079import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070080import java.util.concurrent.Executor;
Terry Wangd2186e52021-04-14 13:19:45 -070081import java.util.concurrent.LinkedBlockingQueue;
Terry Wange04ceab2021-03-29 19:25:12 -070082import java.util.concurrent.ThreadPoolExecutor;
83import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080084
Cassie Wang0c62d992021-01-15 14:39:30 -080085/** TODO(b/142567528): add comments when implement this class */
Terry Wangfebbead2019-10-17 17:05:18 -070086public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070087 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070088 private final Context mContext;
Yang Yu0fcd51a2021-04-23 11:25:44 -070089 private PackageManager mPackageManager;
Cassie Wang0c62d992021-01-15 14:39:30 -080090 private PackageManagerInternal mPackageManagerInternal;
Cassie Wang21c2d6a2021-01-20 23:59:55 -080091 private ImplInstanceManager mImplInstanceManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070092 private UserManager mUserManager;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080093 private LoggerInstanceManager mLoggerInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -070094
Terry Wange04ceab2021-03-29 19:25:12 -070095 // Never call shutdownNow(). It will cancel the futures it's returned. And since
96 // Executor#execute won't return anything, we will hang forever waiting for the execution.
97 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
98 // mutate requests will need to gain write lock and query requests need to gain read lock.
99 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
100 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
Terry Wangd2186e52021-04-14 13:19:45 -0700101 new LinkedBlockingQueue<>());
Terry Wange04ceab2021-03-29 19:25:12 -0700102
Cassie Wang15c86972021-02-09 13:43:25 -0800103 // Cache of unlocked user ids so we don't have to query UserManager service each time. The
104 // "locked" suffix refers to the fact that access to the field should be locked; unrelated to
105 // the unlocked status of user ids.
106 @GuardedBy("mUnlockedUserIdsLocked")
107 private final Set<Integer> mUnlockedUserIdsLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800108
Terry Wangfebbead2019-10-17 17:05:18 -0700109 public AppSearchManagerService(Context context) {
110 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700111 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700112 }
113
114 @Override
115 public void onStart() {
116 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Yang Yu0fcd51a2021-04-23 11:25:44 -0700117 mPackageManager = getContext().getPackageManager();
Cassie Wang0c62d992021-01-15 14:39:30 -0800118 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
Terry Wang12dc6c02021-03-31 19:26:16 -0700119 mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
120 mUserManager = mContext.getSystemService(UserManager.class);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800121 mLoggerInstanceManager = LoggerInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700122 registerReceivers();
Yang Yu0fcd51a2021-04-23 11:25:44 -0700123 LocalServices.getService(StorageStatsManagerInternal.class)
124 .registerStorageStatsAugmenter(new AppSearchStorageStatsAugmenter(), TAG);
Terry Wang12dc6c02021-03-31 19:26:16 -0700125 }
126
127 private void registerReceivers() {
128 mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
129 new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
130 /*scheduler=*/ null);
131 }
132
133 private class UserActionReceiver extends BroadcastReceiver {
134 @Override
135 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
136 switch (intent.getAction()) {
137 case Intent.ACTION_USER_REMOVED:
Martijn Coenen9fdaf0d2021-04-15 07:18:26 +0000138 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
Terry Wang12dc6c02021-03-31 19:26:16 -0700139 if (userId == USER_NULL) {
Martijn Coenen9fdaf0d2021-04-15 07:18:26 +0000140 Slog.e(TAG, "userId is missing in the intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700141 return;
142 }
143 handleUserRemoved(userId);
144 break;
145 default:
Martijn Coenen9fdaf0d2021-04-15 07:18:26 +0000146 Slog.e(TAG, "Received unknown intent: " + intent);
Terry Wang12dc6c02021-03-31 19:26:16 -0700147 }
148 }
149 }
150
151 /**
152 * Handles user removed action.
153 *
154 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
155 * "credential encrypted" system directory of each user. That directory will be auto-deleted
156 * when a user is removed.
157 *
158 * @param userId The multi-user userId of the user that need to be removed.
159 *
160 * @see android.os.Environment#getDataSystemCeDirectory
161 */
162 private void handleUserRemoved(@UserIdInt int userId) {
163 try {
164 mImplInstanceManager.removeAppSearchImplForUser(userId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800165 mLoggerInstanceManager.removePlatformLoggerForUser(userId);
Martijn Coenen9fdaf0d2021-04-15 07:18:26 +0000166 Slog.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
Terry Wang12dc6c02021-03-31 19:26:16 -0700167 } catch (Throwable t) {
Martijn Coenen9fdaf0d2021-04-15 07:18:26 +0000168 Slog.e(TAG, "Unable to remove data for user: " + userId, t);
Terry Wang12dc6c02021-03-31 19:26:16 -0700169 }
Terry Wangfebbead2019-10-17 17:05:18 -0700170 }
171
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800172 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700173 public void onUserUnlocking(@NonNull TargetUser user) {
Cassie Wang15c86972021-02-09 13:43:25 -0800174 synchronized (mUnlockedUserIdsLocked) {
175 mUnlockedUserIdsLocked.add(user.getUserIdentifier());
176 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800177 }
178
Yang Yu0fcd51a2021-04-23 11:25:44 -0700179 private void verifyUserUnlocked(int callingUserId) {
180 synchronized (mUnlockedUserIdsLocked) {
181 // First, check the local copy.
182 if (mUnlockedUserIdsLocked.contains(callingUserId)) {
183 return;
184 }
185 // If the local copy says the user is locked, check with UM for the actual state,
186 // since the user might just have been unlocked.
187 if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId))) {
188 throw new IllegalStateException(
189 "User " + callingUserId + " is locked or not running.");
190 }
191 }
192 }
193
Terry Wangfebbead2019-10-17 17:05:18 -0700194 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800195 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800196 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800197 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700198 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700199 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800200 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhineab789062021-01-11 21:00:00 -0800201 @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800202 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700203 int schemaVersion,
Terry Wangc10610d2021-03-21 13:21:24 -0700204 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800205 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700206 Objects.requireNonNull(packageName);
207 Objects.requireNonNull(databaseName);
208 Objects.requireNonNull(schemaBundles);
209 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800210 int callingUid = Binder.getCallingUid();
211 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700212 EXECUTOR.execute(() -> {
213 try {
214 verifyUserUnlocked(callingUserId);
215 verifyCallingPackage(callingUid, packageName);
216 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
217 for (int i = 0; i < schemaBundles.size(); i++) {
218 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800219 }
Terry Wange04ceab2021-03-29 19:25:12 -0700220 Map<String, List<PackageIdentifier>> schemasPackageAccessible =
221 new ArrayMap<>(schemasPackageAccessibleBundles.size());
222 for (Map.Entry<String, List<Bundle>> entry :
223 schemasPackageAccessibleBundles.entrySet()) {
224 List<PackageIdentifier> packageIdentifiers =
225 new ArrayList<>(entry.getValue().size());
226 for (int i = 0; i < entry.getValue().size(); i++) {
227 packageIdentifiers.add(
228 new PackageIdentifier(entry.getValue().get(i)));
229 }
230 schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
231 }
232 AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
233 SetSchemaResponse setSchemaResponse = impl.setSchema(
234 packageName,
235 databaseName,
236 schemas,
237 schemasNotDisplayedBySystem,
238 schemasPackageAccessible,
239 forceOverride,
240 schemaVersion);
241 invokeCallbackOnResult(callback,
242 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
243 } catch (Throwable t) {
244 invokeCallbackOnError(callback, t);
Alexander Dorokhineab789062021-01-11 21:00:00 -0800245 }
Terry Wange04ceab2021-03-29 19:25:12 -0700246 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800247 }
248
249 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800250 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800251 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800252 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -0800253 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -0800254 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700255 Objects.requireNonNull(packageName);
256 Objects.requireNonNull(databaseName);
257 Objects.requireNonNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700258 int callingUid = Binder.getCallingUid();
Terry Wangf2093072020-11-30 04:47:19 -0800259 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700260 EXECUTOR.execute(() -> {
261 try {
262 verifyUserUnlocked(callingUserId);
263 verifyCallingPackage(callingUid, packageName);
264 AppSearchImpl impl =
265 mImplInstanceManager.getAppSearchImpl(callingUserId);
266 GetSchemaResponse response = impl.getSchema(packageName, databaseName);
267 invokeCallbackOnResult(
268 callback,
269 AppSearchResult.newSuccessfulResult(response.getBundle()));
270 } catch (Throwable t) {
271 invokeCallbackOnError(callback, t);
272 }
273 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700274 }
275
276 @Override
277 public void getNamespaces(
278 @NonNull String packageName,
279 @NonNull String databaseName,
280 @UserIdInt int userId,
281 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700282 Objects.requireNonNull(packageName);
283 Objects.requireNonNull(databaseName);
284 Objects.requireNonNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700285 int callingUid = Binder.getCallingUid();
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700286 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700287 EXECUTOR.execute(() -> {
288 try {
289 verifyUserUnlocked(callingUserId);
290 verifyCallingPackage(callingUid, packageName);
291 AppSearchImpl impl =
292 mImplInstanceManager.getAppSearchImpl(callingUserId);
293 List<String> namespaces = impl.getNamespaces(packageName, databaseName);
294 invokeCallbackOnResult(callback,
295 AppSearchResult.newSuccessfulResult(namespaces));
296 } catch (Throwable t) {
297 invokeCallbackOnError(callback, t);
298 }
299 });
Terry Wang83a24932020-12-09 21:00:18 -0800300 }
301
302 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800303 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800304 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700305 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700306 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800307 @UserIdInt int userId,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800308 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800309 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700310 Objects.requireNonNull(packageName);
311 Objects.requireNonNull(databaseName);
312 Objects.requireNonNull(documentBundles);
313 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800314 int callingUid = Binder.getCallingUid();
315 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700316 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800317 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
318 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
319 PlatformLogger logger = null;
320 int operationSuccessCount = 0;
321 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700322 try {
323 verifyUserUnlocked(callingUserId);
324 verifyCallingPackage(callingUid, packageName);
325 AppSearchBatchResult.Builder<String, Void> resultBuilder =
326 new AppSearchBatchResult.Builder<>();
327 AppSearchImpl impl =
328 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800329 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700330 for (int i = 0; i < documentBundles.size(); i++) {
331 GenericDocument document = new GenericDocument(documentBundles.get(i));
332 try {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800333 impl.putDocument(packageName, databaseName, document, logger);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700334 resultBuilder.setSuccess(document.getId(), /*result=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800335 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700336 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700337 resultBuilder.setResult(document.getId(),
Terry Wange04ceab2021-03-29 19:25:12 -0700338 throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800339 AppSearchResult<Void> result = throwableToFailedResult(t);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700340 resultBuilder.setResult(document.getId(), result);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800341 // for failures, we would just log the one for last failure
342 statusCode = result.getResultCode();
343 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700344 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800345 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700346 // Now that the batch has been written. Persist the newly written data.
347 impl.persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700348 invokeCallbackOnResult(callback, resultBuilder.build());
349 } catch (Throwable t) {
350 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800351 } finally {
352 if (logger != null) {
353 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
354 databaseName)
355 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
356 // TODO(b/173532925) check the existing binder call latency chart
357 // is good enough for us:
358 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
359 .setEstimatedBinderLatencyMillis(
360 2 * (int) (totalLatencyStartTimeMillis
361 - binderCallStartTimeMillis))
362 .setNumOperationsSucceeded(operationSuccessCount)
363 .setNumOperationsFailed(operationFailureCount);
364 cBuilder.getGeneralStatsBuilder()
365 .setStatusCode(statusCode)
366 .setTotalLatencyMillis(
367 (int) (SystemClock.elapsedRealtime()
368 - totalLatencyStartTimeMillis));
369 logger.logStats(cBuilder.build());
370 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800371 }
Terry Wange04ceab2021-03-29 19:25:12 -0700372 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800373 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800374
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800375 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800376 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800377 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800378 @NonNull String databaseName,
379 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700380 @NonNull List<String> ids,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800381 @NonNull Map<String, List<String>> typePropertyPaths,
Terry Wangf2093072020-11-30 04:47:19 -0800382 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800383 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700384 Objects.requireNonNull(packageName);
385 Objects.requireNonNull(databaseName);
386 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700387 Objects.requireNonNull(ids);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700388 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800389 int callingUid = Binder.getCallingUid();
390 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700391 EXECUTOR.execute(() -> {
392 try {
393 verifyUserUnlocked(callingUserId);
394 verifyCallingPackage(callingUid, packageName);
395 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
396 new AppSearchBatchResult.Builder<>();
397 AppSearchImpl impl =
398 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700399 for (int i = 0; i < ids.size(); i++) {
400 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700401 try {
402 GenericDocument document =
403 impl.getDocument(
404 packageName,
405 databaseName,
406 namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700407 id,
Terry Wange04ceab2021-03-29 19:25:12 -0700408 typePropertyPaths);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700409 resultBuilder.setSuccess(id, document.getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700410 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700411 resultBuilder.setResult(id, throwableToFailedResult(t));
Terry Wange04ceab2021-03-29 19:25:12 -0700412 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800413 }
Terry Wange04ceab2021-03-29 19:25:12 -0700414 invokeCallbackOnResult(callback, resultBuilder.build());
415 } catch (Throwable t) {
416 invokeCallbackOnError(callback, t);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800417 }
Terry Wange04ceab2021-03-29 19:25:12 -0700418 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800419 }
420
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800421 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800422 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800423 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700424 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700425 @NonNull String queryExpression,
426 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800427 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700428 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700429 Objects.requireNonNull(packageName);
430 Objects.requireNonNull(databaseName);
431 Objects.requireNonNull(queryExpression);
432 Objects.requireNonNull(searchSpecBundle);
433 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800434 int callingUid = Binder.getCallingUid();
435 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700436 EXECUTOR.execute(() -> {
437 try {
438 verifyUserUnlocked(callingUserId);
439 verifyCallingPackage(callingUid, packageName);
440 AppSearchImpl impl =
441 mImplInstanceManager.getAppSearchImpl(callingUserId);
442 SearchResultPage searchResultPage =
443 impl.query(
444 packageName,
445 databaseName,
446 queryExpression,
447 new SearchSpec(searchSpecBundle));
448 invokeCallbackOnResult(
449 callback,
450 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
451 } catch (Throwable t) {
452 invokeCallbackOnError(callback, t);
453 }
454 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700455 }
456
Terry Wangf2093072020-11-30 04:47:19 -0800457 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800458 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800459 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800460 @NonNull String queryExpression,
461 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800462 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800463 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700464 Objects.requireNonNull(packageName);
465 Objects.requireNonNull(queryExpression);
466 Objects.requireNonNull(searchSpecBundle);
467 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800468 int callingUid = Binder.getCallingUid();
469 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700470 EXECUTOR.execute(() -> {
471 try {
472 verifyUserUnlocked(callingUserId);
473 verifyCallingPackage(callingUid, packageName);
474 AppSearchImpl impl =
475 mImplInstanceManager.getAppSearchImpl(callingUserId);
476 SearchResultPage searchResultPage =
477 impl.globalQuery(
478 queryExpression,
479 new SearchSpec(searchSpecBundle),
480 packageName,
481 callingUid);
482 invokeCallbackOnResult(
483 callback,
484 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
485 } catch (Throwable t) {
486 invokeCallbackOnError(callback, t);
487 }
488 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800489 }
490
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700491 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800492 public void getNextPage(
493 long nextPageToken,
494 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700495 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700496 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800497 int callingUid = Binder.getCallingUid();
498 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700499 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
500 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700501 EXECUTOR.execute(() -> {
502 try {
503 verifyUserUnlocked(callingUserId);
504 AppSearchImpl impl =
505 mImplInstanceManager.getAppSearchImpl(callingUserId);
506 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
507 invokeCallbackOnResult(
508 callback,
509 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
510 } catch (Throwable t) {
511 invokeCallbackOnError(callback, t);
512 }
513 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700514 }
515
516 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800517 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
518 int callingUid = Binder.getCallingUid();
519 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700520 EXECUTOR.execute(() -> {
521 try {
522 verifyUserUnlocked(callingUserId);
523 AppSearchImpl impl =
524 mImplInstanceManager.getAppSearchImpl(callingUserId);
525 impl.invalidateNextPageToken(nextPageToken);
526 } catch (Throwable t) {
527 Log.e(TAG, "Unable to invalidate the query page token", t);
528 }
529 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800530 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800531
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700532 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800533 public void writeQueryResultsToFile(
534 @NonNull String packageName,
535 @NonNull String databaseName,
536 @NonNull ParcelFileDescriptor fileDescriptor,
537 @NonNull String queryExpression,
538 @NonNull Bundle searchSpecBundle,
539 @UserIdInt int userId,
540 @NonNull IAppSearchResultCallback callback) {
541 int callingUid = Binder.getCallingUid();
542 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700543 EXECUTOR.execute(() -> {
544 try {
545 verifyCallingPackage(callingUid, packageName);
546 AppSearchImpl impl =
547 mImplInstanceManager.getAppSearchImpl(callingUserId);
548 // we don't need to append the file. The file is always brand new.
549 try (DataOutputStream outputStream = new DataOutputStream(
550 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
551 SearchResultPage searchResultPage = impl.query(
552 packageName,
553 databaseName,
554 queryExpression,
555 new SearchSpec(searchSpecBundle));
556 while (!searchResultPage.getResults().isEmpty()) {
557 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
558 AppSearchMigrationHelper.writeBundleToOutputStream(
559 outputStream, searchResultPage.getResults().get(i)
560 .getGenericDocument().getBundle());
561 }
562 searchResultPage = impl.getNextPage(
563 searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800564 }
Terry Wang623e3b02021-02-02 20:27:33 -0800565 }
Terry Wange04ceab2021-03-29 19:25:12 -0700566 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
567 } catch (Throwable t) {
568 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800569 }
Terry Wange04ceab2021-03-29 19:25:12 -0700570 });
Terry Wang623e3b02021-02-02 20:27:33 -0800571 }
572
573 @Override
574 public void putDocumentsFromFile(
575 @NonNull String packageName,
576 @NonNull String databaseName,
577 @NonNull ParcelFileDescriptor fileDescriptor,
578 @UserIdInt int userId,
579 @NonNull IAppSearchResultCallback callback) {
580 int callingUid = Binder.getCallingUid();
581 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700582 EXECUTOR.execute(() -> {
583 try {
584 verifyCallingPackage(callingUid, packageName);
585 AppSearchImpl impl =
586 mImplInstanceManager.getAppSearchImpl(callingUserId);
Terry Wang623e3b02021-02-02 20:27:33 -0800587
Terry Wange04ceab2021-03-29 19:25:12 -0700588 GenericDocument document;
589 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
590 try (DataInputStream inputStream = new DataInputStream(
591 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
592 while (true) {
593 try {
594 document = AppSearchMigrationHelper
595 .readDocumentFromInputStream(inputStream);
596 } catch (EOFException e) {
597 // nothing wrong, we just finish the reading.
598 break;
599 }
600 try {
601 impl.putDocument(packageName, databaseName, document,
602 /*logger=*/ null);
603 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700604 migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
605 document.getNamespace(),
606 document.getId(),
607 document.getSchemaType(),
608 AppSearchResult.throwableToFailedResult(t))
609 .getBundle());
Terry Wange04ceab2021-03-29 19:25:12 -0700610 }
Terry Wang623e3b02021-02-02 20:27:33 -0800611 }
612 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700613 impl.persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700614 invokeCallbackOnResult(callback,
615 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
616 } catch (Throwable t) {
617 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800618 }
Terry Wange04ceab2021-03-29 19:25:12 -0700619 });
Terry Wang623e3b02021-02-02 20:27:33 -0800620 }
621
622 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800623 public void reportUsage(
624 @NonNull String packageName,
625 @NonNull String databaseName,
626 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700627 @NonNull String documentId,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800628 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700629 boolean systemUsage,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800630 @UserIdInt int userId,
631 @NonNull IAppSearchResultCallback callback) {
632 Objects.requireNonNull(databaseName);
633 Objects.requireNonNull(namespace);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700634 Objects.requireNonNull(documentId);
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800635 Objects.requireNonNull(callback);
636 int callingUid = Binder.getCallingUid();
637 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700638 EXECUTOR.execute(() -> {
639 try {
640 verifyUserUnlocked(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700641
Terry Wange04ceab2021-03-29 19:25:12 -0700642 if (systemUsage) {
643 // TODO(b/183031844): Validate that the call comes from the system
644 }
645
646 AppSearchImpl impl =
647 mImplInstanceManager.getAppSearchImpl(callingUserId);
648 impl.reportUsage(
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700649 packageName, databaseName, namespace, documentId,
Terry Wange04ceab2021-03-29 19:25:12 -0700650 usageTimeMillis, systemUsage);
651 invokeCallbackOnResult(
652 callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
653 } catch (Throwable t) {
654 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700655 }
Terry Wange04ceab2021-03-29 19:25:12 -0700656 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800657 }
658
659 @Override
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700660 public void removeByDocumentId(
Cassie Wang0c62d992021-01-15 14:39:30 -0800661 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800662 @NonNull String databaseName,
663 @NonNull String namespace,
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700664 @NonNull List<String> ids,
Terry Wangf2093072020-11-30 04:47:19 -0800665 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800666 @NonNull IAppSearchBatchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700667 Objects.requireNonNull(packageName);
668 Objects.requireNonNull(databaseName);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700669 Objects.requireNonNull(ids);
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700670 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800671 int callingUid = Binder.getCallingUid();
672 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700673 EXECUTOR.execute(() -> {
674 try {
675 verifyUserUnlocked(callingUserId);
676 verifyCallingPackage(callingUid, packageName);
677 AppSearchBatchResult.Builder<String, Void> resultBuilder =
678 new AppSearchBatchResult.Builder<>();
679 AppSearchImpl impl =
680 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700681 for (int i = 0; i < ids.size(); i++) {
682 String id = ids.get(i);
Terry Wange04ceab2021-03-29 19:25:12 -0700683 try {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700684 impl.remove(packageName, databaseName, namespace, id);
685 resultBuilder.setSuccess(id, /*result= */ null);
Terry Wange04ceab2021-03-29 19:25:12 -0700686 } catch (Throwable t) {
Alexander Dorokhine17f79372021-04-21 11:23:09 -0700687 resultBuilder.setResult(id, throwableToFailedResult(t));
Terry Wange04ceab2021-03-29 19:25:12 -0700688 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700689 }
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700690 // Now that the batch has been written. Persist the newly written data.
691 impl.persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700692 invokeCallbackOnResult(callback, resultBuilder.build());
693 } catch (Throwable t) {
694 invokeCallbackOnError(callback, t);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700695 }
Terry Wange04ceab2021-03-29 19:25:12 -0700696 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700697 }
698
699 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700700 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800701 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700702 @NonNull String databaseName,
703 @NonNull String queryExpression,
704 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800705 @UserIdInt int userId,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700706 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700707 Objects.requireNonNull(packageName);
708 Objects.requireNonNull(databaseName);
709 Objects.requireNonNull(queryExpression);
710 Objects.requireNonNull(searchSpecBundle);
711 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800712 int callingUid = Binder.getCallingUid();
713 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700714 EXECUTOR.execute(() -> {
715 try {
716 verifyUserUnlocked(callingUserId);
717 verifyCallingPackage(callingUid, packageName);
718 AppSearchImpl impl =
719 mImplInstanceManager.getAppSearchImpl(callingUserId);
720 impl.removeByQuery(
721 packageName,
722 databaseName,
723 queryExpression,
724 new SearchSpec(searchSpecBundle));
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700725 // Now that the batch has been written. Persist the newly written data.
726 impl.persistToDisk(PersistType.Code.LITE);
Terry Wange04ceab2021-03-29 19:25:12 -0700727 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
728 } catch (Throwable t) {
729 invokeCallbackOnError(callback, t);
730 }
731 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700732 }
733
Terry Wangdbd1dca2020-11-03 17:03:56 -0800734 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -0700735 public void getStorageInfo(
736 @NonNull String packageName,
737 @NonNull String databaseName,
738 @UserIdInt int userId,
739 @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700740 Objects.requireNonNull(packageName);
741 Objects.requireNonNull(databaseName);
742 Objects.requireNonNull(callback);
Cassie Wang8f0df492021-03-24 09:23:18 -0700743 int callingUid = Binder.getCallingUid();
744 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700745 EXECUTOR.execute(() -> {
746 try {
747 verifyUserUnlocked(callingUserId);
748 verifyCallingPackage(callingUid, packageName);
749 AppSearchImpl impl =
750 mImplInstanceManager.getAppSearchImpl(callingUserId);
751 StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
752 databaseName);
753 Bundle storageInfoBundle = storageInfo.getBundle();
754 invokeCallbackOnResult(
755 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
756 } catch (Throwable t) {
757 invokeCallbackOnError(callback, t);
758 }
759 });
Cassie Wang8f0df492021-03-24 09:23:18 -0700760 }
761
762 @Override
Terry Wang2da17852020-12-16 19:59:08 -0800763 public void persistToDisk(@UserIdInt int userId) {
Cassie Wangb0d60122021-03-30 12:38:46 -0700764 int callingUid = Binder.getCallingUid();
Terry Wang2da17852020-12-16 19:59:08 -0800765 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700766 EXECUTOR.execute(() -> {
767 try {
768 verifyUserUnlocked(callingUserId);
769 AppSearchImpl impl =
770 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhinec77f4442021-04-14 09:26:06 -0700771 impl.persistToDisk(PersistType.Code.FULL);
Terry Wange04ceab2021-03-29 19:25:12 -0700772 } catch (Throwable t) {
773 Log.e(TAG, "Unable to persist the data to disk", t);
774 }
775 });
Terry Wang2da17852020-12-16 19:59:08 -0800776 }
777
778 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800779 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700780 Objects.requireNonNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800781 int callingUid = Binder.getCallingUid();
782 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700783 EXECUTOR.execute(() -> {
784 try {
785 verifyUserUnlocked(callingUserId);
786 mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800787 mLoggerInstanceManager.getOrCreatePlatformLogger(getContext(), callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700788 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
789 } catch (Throwable t) {
790 invokeCallbackOnError(callback, t);
791 }
792 });
Terry Wangdbd1dca2020-11-03 17:03:56 -0800793 }
794
Cassie Wang0c62d992021-01-15 14:39:30 -0800795 private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) {
Alexander Dorokhine5258ad22021-04-15 10:59:55 -0700796 Objects.requireNonNull(callingPackage);
Cassie Wang0c62d992021-01-15 14:39:30 -0800797 if (mPackageManagerInternal.getPackageUid(
Yang Yu0fcd51a2021-04-23 11:25:44 -0700798 callingPackage, /*flags=*/ 0, UserHandle.getUserId(callingUid))
Cassie Wang0c62d992021-01-15 14:39:30 -0800799 != callingUid) {
800 throw new SecurityException(
801 "Specified calling package ["
802 + callingPackage
803 + "] does not match the calling uid "
804 + callingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700805 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700806 }
807
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800808 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -0800809 private void invokeCallbackOnResult(
810 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800811 try {
812 callback.onResult(result);
813 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800814 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800815 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800816 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800817
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800818 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -0800819 private void invokeCallbackOnResult(
820 IAppSearchBatchResultCallback callback, AppSearchBatchResult<?, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800821 try {
822 callback.onResult(result);
823 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800824 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800825 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800826 }
827
828 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800829 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800830 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800831 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -0800832 */
833 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
834 try {
835 callback.onResult(throwableToFailedResult(throwable));
836 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800837 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800838 }
839 }
840
841 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800842 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800843 *
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -0700844 * <p>The throwable is converted to {@link AppSearchResult}.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800845 */
Cassie Wang0c62d992021-01-15 14:39:30 -0800846 private void invokeCallbackOnError(
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -0700847 @NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800848 try {
Alexander Dorokhineb5d34b12021-04-15 00:32:15 -0700849 callback.onSystemError(throwableToFailedResult(throwable));
Terry Wangdbd1dca2020-11-03 17:03:56 -0800850 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800851 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800852 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800853 }
Terry Wangfebbead2019-10-17 17:05:18 -0700854 }
Terry Wangf2093072020-11-30 04:47:19 -0800855
Cassie Wang0c62d992021-01-15 14:39:30 -0800856 // TODO(b/173553485) verifying that the caller has permission to access target user's data
857 // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
858 // TODO(b/173553485) Implement SystemService.onUserStopping()
Terry Wangf2093072020-11-30 04:47:19 -0800859 private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
860 int callingPid = Binder.getCallingPid();
Cassie Wang0c62d992021-01-15 14:39:30 -0800861 return ActivityManager.handleIncomingUser(
862 callingPid,
863 callingUid,
864 userId,
865 /*allowAll=*/ false,
866 /*requireFull=*/ false,
867 /*name=*/ null,
868 /*callerPackage=*/ null);
Terry Wangf2093072020-11-30 04:47:19 -0800869 }
Yang Yu0fcd51a2021-04-23 11:25:44 -0700870
871 // TODO(b/179160886): Cache the previous storage stats.
872 private class AppSearchStorageStatsAugmenter implements StorageStatsAugmenter {
873 @Override
874 public void augmentStatsForPackage(
875 @NonNull PackageStats stats,
876 @NonNull String packageName,
877 @UserIdInt int userId,
878 boolean callerHasStatsPermission) {
879 Objects.requireNonNull(stats);
880 Objects.requireNonNull(packageName);
881 try {
882 verifyUserUnlocked(userId);
883 AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
884 userId);
885 stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
886 } catch (Throwable t) {
887 Log.e(
888 TAG,
889 "Unable to augment storage stats for userId "
890 + userId
891 + " packageName "
892 + packageName,
893 t);
894 }
895 }
896
897 @Override
898 public void augmentStatsForUid(
899 @NonNull PackageStats stats, int uid, boolean callerHasStatsPermission) {
900 Objects.requireNonNull(stats);
901 int userId = UserHandle.getUserId(uid);
902 try {
903 verifyUserUnlocked(userId);
904 String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
905 if (packagesForUid == null) {
906 return;
907 }
908 AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
909 userId);
910 for (String packageName : packagesForUid) {
911 stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
912 }
913 } catch (Throwable t) {
914 Log.e(TAG, "Unable to augment storage stats for uid " + uid, t);
915 }
916 }
917 }
Terry Wangfebbead2019-10-17 17:05:18 -0700918}