blob: 704ee6446e54bc483bd7e953ef1ce8180eb04810 [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
sidchhabraa7c8f8a2020-01-16 18:38:17 -080021import android.annotation.NonNull;
Terry Wangf2093072020-11-30 04:47:19 -080022import android.annotation.UserIdInt;
23import android.app.ActivityManager;
Alexander Dorokhine18465842020-01-21 01:08:57 -080024import android.app.appsearch.AppSearchBatchResult;
Terry Wang623e3b02021-02-02 20:27:33 -080025import android.app.appsearch.AppSearchMigrationHelper;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080026import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070027import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070028import android.app.appsearch.GenericDocument;
Alexander Dorokhine9795b512021-03-23 22:06:59 -070029import android.app.appsearch.GetSchemaResponse;
Terry Wangdbd1dca2020-11-03 17:03:56 -080030import android.app.appsearch.IAppSearchBatchResultCallback;
Terry Wangfebbead2019-10-17 17:05:18 -070031import android.app.appsearch.IAppSearchManager;
Terry Wangdbd1dca2020-11-03 17:03:56 -080032import android.app.appsearch.IAppSearchResultCallback;
Alexander Dorokhineab789062021-01-11 21:00:00 -080033import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070034import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070035import android.app.appsearch.SearchSpec;
Terry Wang623e3b02021-02-02 20:27:33 -080036import android.app.appsearch.SetSchemaResponse;
Cassie Wang8f0df492021-03-24 09:23:18 -070037import android.app.appsearch.StorageInfo;
Terry Wang12dc6c02021-03-31 19:26:16 -070038import android.content.BroadcastReceiver;
Terry Wangfebbead2019-10-17 17:05:18 -070039import android.content.Context;
Terry Wang12dc6c02021-03-31 19:26:16 -070040import android.content.Intent;
41import android.content.IntentFilter;
Cassie Wang0c62d992021-01-15 14:39:30 -080042import android.content.pm.PackageManagerInternal;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080043import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070044import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080045import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080046import android.os.ParcelableException;
47import android.os.RemoteException;
Cassie Wang0c62d992021-01-15 14:39:30 -080048import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070049import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080050import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080051import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080052import android.util.Log;
Terry Wang12dc6c02021-03-31 19:26:16 -070053import android.util.Slog;
Terry Wangfebbead2019-10-17 17:05:18 -070054
Cassie Wang15c86972021-02-09 13:43:25 -080055import com.android.internal.annotations.GuardedBy;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080056import com.android.internal.util.Preconditions;
Cassie Wang0c62d992021-01-15 14:39:30 -080057import com.android.server.LocalServices;
Terry Wangfebbead2019-10-17 17:05:18 -070058import com.android.server.SystemService;
Alexander Dorokhinef660d8f2020-10-29 22:37:00 -070059import com.android.server.appsearch.external.localstorage.AppSearchImpl;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080060
Terry Wang623e3b02021-02-02 20:27:33 -080061import java.io.DataInputStream;
62import java.io.DataOutputStream;
63import java.io.EOFException;
64import java.io.FileInputStream;
65import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080066import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080067import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080068import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080069import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080070import java.util.Set;
Alexander Dorokhine18465842020-01-21 01:08:57 -080071
Cassie Wang0c62d992021-01-15 14:39:30 -080072/** TODO(b/142567528): add comments when implement this class */
Terry Wangfebbead2019-10-17 17:05:18 -070073public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070074 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070075 private final Context mContext;
Cassie Wang0c62d992021-01-15 14:39:30 -080076 private PackageManagerInternal mPackageManagerInternal;
Cassie Wang21c2d6a2021-01-20 23:59:55 -080077 private ImplInstanceManager mImplInstanceManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070078 private UserManager mUserManager;
Terry Wangfebbead2019-10-17 17:05:18 -070079
Cassie Wang15c86972021-02-09 13:43:25 -080080 // Cache of unlocked user ids so we don't have to query UserManager service each time. The
81 // "locked" suffix refers to the fact that access to the field should be locked; unrelated to
82 // the unlocked status of user ids.
83 @GuardedBy("mUnlockedUserIdsLocked")
84 private final Set<Integer> mUnlockedUserIdsLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -080085
Terry Wangfebbead2019-10-17 17:05:18 -070086 public AppSearchManagerService(Context context) {
87 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -070088 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -070089 }
90
91 @Override
92 public void onStart() {
93 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Cassie Wang0c62d992021-01-15 14:39:30 -080094 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
Terry Wang12dc6c02021-03-31 19:26:16 -070095 mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
96 mUserManager = mContext.getSystemService(UserManager.class);
97 registerReceivers();
98 }
99
100 private void registerReceivers() {
101 mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
102 new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
103 /*scheduler=*/ null);
104 }
105
106 private class UserActionReceiver extends BroadcastReceiver {
107 @Override
108 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
109 switch (intent.getAction()) {
110 case Intent.ACTION_USER_REMOVED:
111 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
112 if (userId == USER_NULL) {
113 Slog.e(TAG, "userId is missing in the intent: " + intent);
114 return;
115 }
116 handleUserRemoved(userId);
117 break;
118 default:
119 Slog.e(TAG, "Received unknown intent: " + intent);
120 }
121 }
122 }
123
124 /**
125 * Handles user removed action.
126 *
127 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
128 * "credential encrypted" system directory of each user. That directory will be auto-deleted
129 * when a user is removed.
130 *
131 * @param userId The multi-user userId of the user that need to be removed.
132 *
133 * @see android.os.Environment#getDataSystemCeDirectory
134 */
135 private void handleUserRemoved(@UserIdInt int userId) {
136 try {
137 mImplInstanceManager.removeAppSearchImplForUser(userId);
138 Slog.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
139 } catch (Throwable t) {
140 Slog.e(TAG, "Unable to remove data for user: " + userId, t);
141 }
Terry Wangfebbead2019-10-17 17:05:18 -0700142 }
143
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800144 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700145 public void onUserUnlocking(@NonNull TargetUser user) {
Cassie Wang15c86972021-02-09 13:43:25 -0800146 synchronized (mUnlockedUserIdsLocked) {
147 mUnlockedUserIdsLocked.add(user.getUserIdentifier());
148 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800149 }
150
Terry Wangfebbead2019-10-17 17:05:18 -0700151 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800152 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800153 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800154 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700155 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700156 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800157 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhineab789062021-01-11 21:00:00 -0800158 @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800159 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700160 int schemaVersion,
Terry Wangc10610d2021-03-21 13:21:24 -0700161 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800162 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800163 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700164 Preconditions.checkNotNull(databaseName);
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700165 Preconditions.checkNotNull(schemaBundles);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800166 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800167 int callingUid = Binder.getCallingUid();
168 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600169 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800170 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800171 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800172 verifyCallingPackage(callingUid, packageName);
Alexander Dorokhine6a99f942020-12-04 02:57:22 -0800173 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700174 for (int i = 0; i < schemaBundles.size(); i++) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700175 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700176 }
Alexander Dorokhineab789062021-01-11 21:00:00 -0800177 Map<String, List<PackageIdentifier>> schemasPackageAccessible =
178 new ArrayMap<>(schemasPackageAccessibleBundles.size());
179 for (Map.Entry<String, List<Bundle>> entry :
180 schemasPackageAccessibleBundles.entrySet()) {
181 List<PackageIdentifier> packageIdentifiers =
182 new ArrayList<>(entry.getValue().size());
Cassie Wange8569db2021-02-05 00:05:25 -0800183 for (int i = 0; i < entry.getValue().size(); i++) {
Alexander Dorokhineab789062021-01-11 21:00:00 -0800184 packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
185 }
186 schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
187 }
Terry Wang9d8f4272021-02-04 21:01:10 -0800188 AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
Terry Wang623e3b02021-02-02 20:27:33 -0800189 SetSchemaResponse setSchemaResponse = impl.setSchema(
Alexander Dorokhineab789062021-01-11 21:00:00 -0800190 packageName,
191 databaseName,
192 schemas,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800193 schemasNotDisplayedBySystem,
Alexander Dorokhineab789062021-01-11 21:00:00 -0800194 schemasPackageAccessible,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700195 forceOverride,
196 schemaVersion);
Terry Wang623e3b02021-02-02 20:27:33 -0800197 invokeCallbackOnResult(callback,
198 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800199 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800200 invokeCallbackOnError(callback, t);
Alexander Dorokhine270d4f12020-01-15 17:24:35 -0800201 } finally {
202 Binder.restoreCallingIdentity(callingIdentity);
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800203 }
204 }
205
206 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800207 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800208 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800209 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -0800210 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -0800211 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800212 Preconditions.checkNotNull(packageName);
Terry Wang83a24932020-12-09 21:00:18 -0800213 Preconditions.checkNotNull(databaseName);
214 Preconditions.checkNotNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700215 int callingUid = Binder.getCallingUid();
Terry Wangf2093072020-11-30 04:47:19 -0800216 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wang83a24932020-12-09 21:00:18 -0800217 final long callingIdentity = Binder.clearCallingIdentity();
218 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800219 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800220 verifyCallingPackage(callingUid, packageName);
Cassie Wang308304c2021-01-21 11:13:49 -0800221 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800222 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700223 GetSchemaResponse response = impl.getSchema(packageName, databaseName);
Cassie Wang0c62d992021-01-15 14:39:30 -0800224 invokeCallbackOnResult(
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700225 callback, AppSearchResult.newSuccessfulResult(response.getBundle()));
226 } catch (Throwable t) {
227 invokeCallbackOnError(callback, t);
228 } finally {
229 Binder.restoreCallingIdentity(callingIdentity);
230 }
231 }
232
233 @Override
234 public void getNamespaces(
235 @NonNull String packageName,
236 @NonNull String databaseName,
237 @UserIdInt int userId,
238 @NonNull IAppSearchResultCallback callback) {
239 Preconditions.checkNotNull(packageName);
240 Preconditions.checkNotNull(databaseName);
241 Preconditions.checkNotNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700242 int callingUid = Binder.getCallingUid();
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700243 int callingUserId = handleIncomingUser(userId, callingUid);
244 final long callingIdentity = Binder.clearCallingIdentity();
245 try {
246 verifyUserUnlocked(callingUserId);
247 verifyCallingPackage(callingUid, packageName);
248 AppSearchImpl impl =
249 mImplInstanceManager.getAppSearchImpl(callingUserId);
250 List<String> namespaces = impl.getNamespaces(packageName, databaseName);
251 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(namespaces));
Terry Wang83a24932020-12-09 21:00:18 -0800252 } catch (Throwable t) {
253 invokeCallbackOnError(callback, t);
254 } finally {
255 Binder.restoreCallingIdentity(callingIdentity);
256 }
257 }
258
259 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800260 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800261 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700262 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700263 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800264 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800265 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800266 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700267 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700268 Preconditions.checkNotNull(documentBundles);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800269 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800270 int callingUid = Binder.getCallingUid();
271 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600272 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800273 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800274 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800275 verifyCallingPackage(callingUid, packageName);
Alexander Dorokhine18465842020-01-21 01:08:57 -0800276 AppSearchBatchResult.Builder<String, Void> resultBuilder =
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800277 new AppSearchBatchResult.Builder<>();
Cassie Wang308304c2021-01-21 11:13:49 -0800278 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800279 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700280 for (int i = 0; i < documentBundles.size(); i++) {
281 GenericDocument document = new GenericDocument(documentBundles.get(i));
Alexander Dorokhine18465842020-01-21 01:08:57 -0800282 try {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800283 // TODO(b/173451571): reduce burden of binder thread by enqueue request onto
284 // a separate thread.
Alexander Dorokhine3488b9a2021-03-16 23:57:49 -0700285 impl.putDocument(packageName, databaseName, document, /*logger=*/ null);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700286 resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
Alexander Dorokhine18465842020-01-21 01:08:57 -0800287 } catch (Throwable t) {
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800288 resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
Alexander Dorokhine18465842020-01-21 01:08:57 -0800289 }
290 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800291 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800292 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800293 invokeCallbackOnError(callback, t);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800294 } finally {
295 Binder.restoreCallingIdentity(callingIdentity);
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800296 }
297 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800298
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800299 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800300 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800301 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800302 @NonNull String databaseName,
303 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800304 @NonNull List<String> uris,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800305 @NonNull Map<String, List<String>> typePropertyPaths,
Terry Wangf2093072020-11-30 04:47:19 -0800306 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800307 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800308 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700309 Preconditions.checkNotNull(databaseName);
310 Preconditions.checkNotNull(namespace);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800311 Preconditions.checkNotNull(uris);
312 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800313 int callingUid = Binder.getCallingUid();
314 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600315 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800316 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800317 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800318 verifyCallingPackage(callingUid, packageName);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700319 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800320 new AppSearchBatchResult.Builder<>();
Cassie Wang308304c2021-01-21 11:13:49 -0800321 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800322 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800323 for (int i = 0; i < uris.size(); i++) {
324 String uri = uris.get(i);
325 try {
Cassie Wang308304c2021-01-21 11:13:49 -0800326 GenericDocument document =
327 impl.getDocument(
328 packageName,
329 databaseName,
330 namespace,
331 uri,
332 typePropertyPaths);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700333 resultBuilder.setSuccess(uri, document.getBundle());
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800334 } catch (Throwable t) {
335 resultBuilder.setResult(uri, throwableToFailedResult(t));
336 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800337 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800338 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800339 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800340 invokeCallbackOnError(callback, t);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800341 } finally {
342 Binder.restoreCallingIdentity(callingIdentity);
343 }
344 }
345
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800346 // TODO(sidchhabra): Do this in a threadpool.
347 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800348 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800349 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700350 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700351 @NonNull String queryExpression,
352 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800353 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700354 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800355 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700356 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700357 Preconditions.checkNotNull(queryExpression);
358 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800359 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800360 int callingUid = Binder.getCallingUid();
361 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600362 final long callingIdentity = Binder.clearCallingIdentity();
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800363 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800364 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800365 verifyCallingPackage(callingUid, packageName);
Cassie Wang308304c2021-01-21 11:13:49 -0800366 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800367 mImplInstanceManager.getAppSearchImpl(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800368 SearchResultPage searchResultPage =
369 impl.query(
370 packageName,
371 databaseName,
372 queryExpression,
373 new SearchSpec(searchSpecBundle));
374 invokeCallbackOnResult(
375 callback,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700376 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800377 } catch (Throwable t) {
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700378 invokeCallbackOnError(callback, t);
379 } finally {
380 Binder.restoreCallingIdentity(callingIdentity);
381 }
382 }
383
Terry Wangf2093072020-11-30 04:47:19 -0800384 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800385 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800386 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800387 @NonNull String queryExpression,
388 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800389 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800390 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800391 Preconditions.checkNotNull(packageName);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800392 Preconditions.checkNotNull(queryExpression);
393 Preconditions.checkNotNull(searchSpecBundle);
394 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800395 int callingUid = Binder.getCallingUid();
396 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800397 final long callingIdentity = Binder.clearCallingIdentity();
398 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800399 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800400 verifyCallingPackage(callingUid, packageName);
Cassie Wang308304c2021-01-21 11:13:49 -0800401 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800402 mImplInstanceManager.getAppSearchImpl(callingUserId);
Cassie Wang308304c2021-01-21 11:13:49 -0800403 SearchResultPage searchResultPage =
404 impl.globalQuery(
405 queryExpression,
406 new SearchSpec(searchSpecBundle),
407 packageName,
408 callingUid);
Cassie Wang0c62d992021-01-15 14:39:30 -0800409 invokeCallbackOnResult(
410 callback,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800411 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
412 } catch (Throwable t) {
413 invokeCallbackOnError(callback, t);
414 } finally {
415 Binder.restoreCallingIdentity(callingIdentity);
416 }
417 }
418
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700419 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800420 public void getNextPage(
421 long nextPageToken,
422 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700423 @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800424 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800425 int callingUid = Binder.getCallingUid();
426 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700427 final long callingIdentity = Binder.clearCallingIdentity();
428 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
429 // opened it
430 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800431 verifyUserUnlocked(callingUserId);
Cassie Wang308304c2021-01-21 11:13:49 -0800432 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800433 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700434 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
Cassie Wang0c62d992021-01-15 14:39:30 -0800435 invokeCallbackOnResult(
436 callback,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700437 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
438 } catch (Throwable t) {
439 invokeCallbackOnError(callback, t);
440 } finally {
441 Binder.restoreCallingIdentity(callingIdentity);
442 }
443 }
444
445 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800446 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
447 int callingUid = Binder.getCallingUid();
448 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700449 final long callingIdentity = Binder.clearCallingIdentity();
450 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800451 verifyUserUnlocked(callingUserId);
Cassie Wang308304c2021-01-21 11:13:49 -0800452 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800453 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700454 impl.invalidateNextPageToken(nextPageToken);
455 } catch (Throwable t) {
Terry Wang2da17852020-12-16 19:59:08 -0800456 Log.e(TAG, "Unable to invalidate the query page token", t);
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800457 } finally {
458 Binder.restoreCallingIdentity(callingIdentity);
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800459 }
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800460 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800461
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700462 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800463 public void writeQueryResultsToFile(
464 @NonNull String packageName,
465 @NonNull String databaseName,
466 @NonNull ParcelFileDescriptor fileDescriptor,
467 @NonNull String queryExpression,
468 @NonNull Bundle searchSpecBundle,
469 @UserIdInt int userId,
470 @NonNull IAppSearchResultCallback callback) {
471 int callingUid = Binder.getCallingUid();
472 int callingUserId = handleIncomingUser(userId, callingUid);
473 final long callingIdentity = Binder.clearCallingIdentity();
474 try {
475 verifyCallingPackage(callingUid, packageName);
476 AppSearchImpl impl =
477 mImplInstanceManager.getAppSearchImpl(callingUserId);
478 // we don't need to append the file. The file is always brand new.
479 try (DataOutputStream outputStream = new DataOutputStream(
480 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
481 SearchResultPage searchResultPage = impl.query(
482 packageName,
483 databaseName,
484 queryExpression,
485 new SearchSpec(searchSpecBundle));
486 while (!searchResultPage.getResults().isEmpty()) {
487 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
488 AppSearchMigrationHelper.writeBundleToOutputStream(
489 outputStream, searchResultPage.getResults().get(i)
490 .getGenericDocument().getBundle());
491 }
492 searchResultPage = impl.getNextPage(searchResultPage.getNextPageToken());
493 }
494 }
495 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
496 } catch (Throwable t) {
497 invokeCallbackOnError(callback, t);
498 } finally {
499 Binder.restoreCallingIdentity(callingIdentity);
500 }
501 }
502
503 @Override
504 public void putDocumentsFromFile(
505 @NonNull String packageName,
506 @NonNull String databaseName,
507 @NonNull ParcelFileDescriptor fileDescriptor,
508 @UserIdInt int userId,
509 @NonNull IAppSearchResultCallback callback) {
510 int callingUid = Binder.getCallingUid();
511 int callingUserId = handleIncomingUser(userId, callingUid);
512 final long callingIdentity = Binder.clearCallingIdentity();
513 try {
514 verifyCallingPackage(callingUid, packageName);
515 AppSearchImpl impl =
516 mImplInstanceManager.getAppSearchImpl(callingUserId);
517
518 GenericDocument document;
519 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
520 try (DataInputStream inputStream = new DataInputStream(
521 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
522 while (true) {
523 try {
524 document = AppSearchMigrationHelper
525 .readDocumentFromInputStream(inputStream);
526 } catch (EOFException e) {
527 // nothing wrong, we just finish the reading.
528 break;
529 }
530 try {
531 impl.putDocument(packageName, databaseName, document, /*logger=*/ null);
532 } catch (Throwable t) {
533 migrationFailureBundles.add(
534 new SetSchemaResponse.MigrationFailure.Builder()
535 .setNamespace(document.getNamespace())
536 .setSchemaType(document.getSchemaType())
537 .setUri(document.getUri())
538 .setAppSearchResult(
539 AppSearchResult.throwableToFailedResult(t))
540 .build().getBundle());
541 }
542 }
543 }
544 impl.persistToDisk();
545 invokeCallbackOnResult(callback,
546 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
547 } catch (Throwable t) {
548 invokeCallbackOnError(callback, t);
549 } finally {
550 Binder.restoreCallingIdentity(callingIdentity);
551 }
552 }
553
554 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800555 public void reportUsage(
556 @NonNull String packageName,
557 @NonNull String databaseName,
558 @NonNull String namespace,
559 @NonNull String uri,
560 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700561 boolean systemUsage,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800562 @UserIdInt int userId,
563 @NonNull IAppSearchResultCallback callback) {
564 Objects.requireNonNull(databaseName);
565 Objects.requireNonNull(namespace);
566 Objects.requireNonNull(uri);
567 Objects.requireNonNull(callback);
568 int callingUid = Binder.getCallingUid();
569 int callingUserId = handleIncomingUser(userId, callingUid);
570 final long callingIdentity = Binder.clearCallingIdentity();
571 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800572 verifyUserUnlocked(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700573
574 if (systemUsage) {
575 // TODO(b/183031844): Validate that the call comes from the system
576 }
577
Cassie Wang308304c2021-01-21 11:13:49 -0800578 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800579 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700580 impl.reportUsage(
581 packageName, databaseName, namespace, uri,
582 usageTimeMillis, systemUsage);
Cassie Wang308304c2021-01-21 11:13:49 -0800583 invokeCallbackOnResult(
584 callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800585 } catch (Throwable t) {
586 invokeCallbackOnError(callback, t);
587 } finally {
588 Binder.restoreCallingIdentity(callingIdentity);
589 }
590 }
591
592 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800593 public void removeByUri(
Cassie Wang0c62d992021-01-15 14:39:30 -0800594 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800595 @NonNull String databaseName,
596 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800597 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800598 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800599 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800600 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700601 Preconditions.checkNotNull(databaseName);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700602 Preconditions.checkNotNull(uris);
603 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800604 int callingUid = Binder.getCallingUid();
605 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600606 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700607 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800608 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800609 verifyCallingPackage(callingUid, packageName);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800610 AppSearchBatchResult.Builder<String, Void> resultBuilder =
611 new AppSearchBatchResult.Builder<>();
Cassie Wang308304c2021-01-21 11:13:49 -0800612 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800613 mImplInstanceManager.getAppSearchImpl(callingUserId);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700614 for (int i = 0; i < uris.size(); i++) {
615 String uri = uris.get(i);
616 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800617 impl.remove(packageName, databaseName, namespace, uri);
Cassie Wang0c62d992021-01-15 14:39:30 -0800618 resultBuilder.setSuccess(uri, /*result= */ null);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700619 } catch (Throwable t) {
620 resultBuilder.setResult(uri, throwableToFailedResult(t));
621 }
622 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800623 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700624 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800625 invokeCallbackOnError(callback, t);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700626 } finally {
627 Binder.restoreCallingIdentity(callingIdentity);
628 }
629 }
630
631 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700632 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800633 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700634 @NonNull String databaseName,
635 @NonNull String queryExpression,
636 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800637 @UserIdInt int userId,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700638 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800639 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700640 Preconditions.checkNotNull(databaseName);
641 Preconditions.checkNotNull(queryExpression);
642 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800643 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800644 int callingUid = Binder.getCallingUid();
645 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600646 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700647 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800648 verifyUserUnlocked(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800649 verifyCallingPackage(callingUid, packageName);
Cassie Wang308304c2021-01-21 11:13:49 -0800650 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800651 mImplInstanceManager.getAppSearchImpl(callingUserId);
Cassie Wang0c62d992021-01-15 14:39:30 -0800652 impl.removeByQuery(
653 packageName,
654 databaseName,
655 queryExpression,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700656 new SearchSpec(searchSpecBundle));
657 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700658 } catch (Throwable t) {
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700659 invokeCallbackOnError(callback, t);
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700660 } finally {
661 Binder.restoreCallingIdentity(callingIdentity);
662 }
663 }
664
Terry Wangdbd1dca2020-11-03 17:03:56 -0800665 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -0700666 public void getStorageInfo(
667 @NonNull String packageName,
668 @NonNull String databaseName,
669 @UserIdInt int userId,
670 @NonNull IAppSearchResultCallback callback) {
671 Preconditions.checkNotNull(packageName);
672 Preconditions.checkNotNull(databaseName);
673 Preconditions.checkNotNull(callback);
674 int callingUid = Binder.getCallingUid();
675 int callingUserId = handleIncomingUser(userId, callingUid);
676 final long callingIdentity = Binder.clearCallingIdentity();
677 try {
678 verifyUserUnlocked(callingUserId);
679 verifyCallingPackage(callingUid, packageName);
680 AppSearchImpl impl =
681 mImplInstanceManager.getAppSearchImpl(callingUserId);
682 StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName, databaseName);
683 Bundle storageInfoBundle = storageInfo.getBundle();
684 invokeCallbackOnResult(
685 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
686 } catch (Throwable t) {
687 invokeCallbackOnError(callback, t);
688 } finally {
689 Binder.restoreCallingIdentity(callingIdentity);
690 }
691 }
692
693 @Override
Terry Wang2da17852020-12-16 19:59:08 -0800694 public void persistToDisk(@UserIdInt int userId) {
Cassie Wangb0d60122021-03-30 12:38:46 -0700695 int callingUid = Binder.getCallingUid();
Terry Wang2da17852020-12-16 19:59:08 -0800696 int callingUserId = handleIncomingUser(userId, callingUid);
697 final long callingIdentity = Binder.clearCallingIdentity();
698 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800699 verifyUserUnlocked(callingUserId);
Cassie Wang308304c2021-01-21 11:13:49 -0800700 AppSearchImpl impl =
Terry Wang9d8f4272021-02-04 21:01:10 -0800701 mImplInstanceManager.getAppSearchImpl(callingUserId);
Terry Wang2da17852020-12-16 19:59:08 -0800702 impl.persistToDisk();
703 } catch (Throwable t) {
704 Log.e(TAG, "Unable to persist the data to disk", t);
705 } finally {
706 Binder.restoreCallingIdentity(callingIdentity);
707 }
708 }
709
710 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800711 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800712 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800713 int callingUid = Binder.getCallingUid();
714 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800715 final long callingIdentity = Binder.clearCallingIdentity();
716 try {
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800717 verifyUserUnlocked(callingUserId);
Terry Wang12dc6c02021-03-31 19:26:16 -0700718 mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800719 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
720 } catch (Throwable t) {
721 invokeCallbackOnError(callback, t);
722 } finally {
723 Binder.restoreCallingIdentity(callingIdentity);
724 }
725 }
726
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800727 private void verifyUserUnlocked(int callingUserId) {
Cassie Wang15c86972021-02-09 13:43:25 -0800728 synchronized (mUnlockedUserIdsLocked) {
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700729 // First, check the local copy.
730 if (mUnlockedUserIdsLocked.contains(callingUserId)) {
731 return;
732 }
733 // If the local copy says the user is locked, check with UM for the actual state,
734 // since the user might just have been unlocked.
735 if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId))) {
Cassie Wang15c86972021-02-09 13:43:25 -0800736 throw new IllegalStateException(
737 "User " + callingUserId + " is locked or not running.");
738 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800739 }
740 }
741
Cassie Wang0c62d992021-01-15 14:39:30 -0800742 private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) {
743 Preconditions.checkNotNull(callingPackage);
744 if (mPackageManagerInternal.getPackageUid(
745 callingPackage, /*flags=*/ 0, UserHandle.getUserId(callingUid))
746 != callingUid) {
747 throw new SecurityException(
748 "Specified calling package ["
749 + callingPackage
750 + "] does not match the calling uid "
751 + callingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700752 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700753 }
754
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800755 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -0800756 private void invokeCallbackOnResult(
757 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800758 try {
759 callback.onResult(result);
760 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800761 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800762 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800763 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800764
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800765 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -0800766 private void invokeCallbackOnResult(
767 IAppSearchBatchResultCallback callback, AppSearchBatchResult<?, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800768 try {
769 callback.onResult(result);
770 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800771 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800772 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800773 }
774
775 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800776 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800777 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800778 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -0800779 */
780 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
781 try {
782 callback.onResult(throwableToFailedResult(throwable));
783 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800784 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800785 }
786 }
787
788 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800789 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800790 *
791 * <p>The throwable is converted to {@link ParcelableException}.
792 */
Cassie Wang0c62d992021-01-15 14:39:30 -0800793 private void invokeCallbackOnError(
794 IAppSearchBatchResultCallback callback, Throwable throwable) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800795 try {
Terry Wang9d8f4272021-02-04 21:01:10 -0800796 //TODO(b/175067650) verify ParcelableException could propagate throwable correctly.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800797 callback.onSystemError(new ParcelableException(throwable));
798 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800799 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800800 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800801 }
Terry Wangfebbead2019-10-17 17:05:18 -0700802 }
Terry Wangf2093072020-11-30 04:47:19 -0800803
Cassie Wang0c62d992021-01-15 14:39:30 -0800804 // TODO(b/173553485) verifying that the caller has permission to access target user's data
805 // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
806 // TODO(b/173553485) Implement SystemService.onUserStopping()
Terry Wangf2093072020-11-30 04:47:19 -0800807 private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
808 int callingPid = Binder.getCallingPid();
Cassie Wang0c62d992021-01-15 14:39:30 -0800809 return ActivityManager.handleIncomingUser(
810 callingPid,
811 callingUid,
812 userId,
813 /*allowAll=*/ false,
814 /*requireFull=*/ false,
815 /*name=*/ null,
816 /*callerPackage=*/ null);
Terry Wangf2093072020-11-30 04:47:19 -0800817 }
Terry Wangfebbead2019-10-17 17:05:18 -0700818}