blob: b46e85d1d4800e5cf51c36d96222ff1e99e36a7b [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;
Terry Wange04ceab2021-03-29 19:25:12 -070071import java.util.concurrent.Executor;
72import java.util.concurrent.SynchronousQueue;
73import java.util.concurrent.ThreadPoolExecutor;
74import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080075
Cassie Wang0c62d992021-01-15 14:39:30 -080076/** TODO(b/142567528): add comments when implement this class */
Terry Wangfebbead2019-10-17 17:05:18 -070077public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070078 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070079 private final Context mContext;
Cassie Wang0c62d992021-01-15 14:39:30 -080080 private PackageManagerInternal mPackageManagerInternal;
Cassie Wang21c2d6a2021-01-20 23:59:55 -080081 private ImplInstanceManager mImplInstanceManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070082 private UserManager mUserManager;
Terry Wangfebbead2019-10-17 17:05:18 -070083
Terry Wange04ceab2021-03-29 19:25:12 -070084 // Never call shutdownNow(). It will cancel the futures it's returned. And since
85 // Executor#execute won't return anything, we will hang forever waiting for the execution.
86 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
87 // mutate requests will need to gain write lock and query requests need to gain read lock.
88 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
89 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
90 new SynchronousQueue<Runnable>());
91
Cassie Wang15c86972021-02-09 13:43:25 -080092 // Cache of unlocked user ids so we don't have to query UserManager service each time. The
93 // "locked" suffix refers to the fact that access to the field should be locked; unrelated to
94 // the unlocked status of user ids.
95 @GuardedBy("mUnlockedUserIdsLocked")
96 private final Set<Integer> mUnlockedUserIdsLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -080097
Terry Wangfebbead2019-10-17 17:05:18 -070098 public AppSearchManagerService(Context context) {
99 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700100 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700101 }
102
103 @Override
104 public void onStart() {
105 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Cassie Wang0c62d992021-01-15 14:39:30 -0800106 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
Terry Wang12dc6c02021-03-31 19:26:16 -0700107 mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
108 mUserManager = mContext.getSystemService(UserManager.class);
109 registerReceivers();
110 }
111
112 private void registerReceivers() {
113 mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
114 new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
115 /*scheduler=*/ null);
116 }
117
118 private class UserActionReceiver extends BroadcastReceiver {
119 @Override
120 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
121 switch (intent.getAction()) {
122 case Intent.ACTION_USER_REMOVED:
123 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
124 if (userId == USER_NULL) {
125 Slog.e(TAG, "userId is missing in the intent: " + intent);
126 return;
127 }
128 handleUserRemoved(userId);
129 break;
130 default:
131 Slog.e(TAG, "Received unknown intent: " + intent);
132 }
133 }
134 }
135
136 /**
137 * Handles user removed action.
138 *
139 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
140 * "credential encrypted" system directory of each user. That directory will be auto-deleted
141 * when a user is removed.
142 *
143 * @param userId The multi-user userId of the user that need to be removed.
144 *
145 * @see android.os.Environment#getDataSystemCeDirectory
146 */
147 private void handleUserRemoved(@UserIdInt int userId) {
148 try {
149 mImplInstanceManager.removeAppSearchImplForUser(userId);
150 Slog.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
151 } catch (Throwable t) {
152 Slog.e(TAG, "Unable to remove data for user: " + userId, t);
153 }
Terry Wangfebbead2019-10-17 17:05:18 -0700154 }
155
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800156 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700157 public void onUserUnlocking(@NonNull TargetUser user) {
Cassie Wang15c86972021-02-09 13:43:25 -0800158 synchronized (mUnlockedUserIdsLocked) {
159 mUnlockedUserIdsLocked.add(user.getUserIdentifier());
160 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800161 }
162
Terry Wangfebbead2019-10-17 17:05:18 -0700163 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800164 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800165 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800166 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700167 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700168 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800169 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhineab789062021-01-11 21:00:00 -0800170 @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800171 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700172 int schemaVersion,
Terry Wangc10610d2021-03-21 13:21:24 -0700173 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800174 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800175 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700176 Preconditions.checkNotNull(databaseName);
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700177 Preconditions.checkNotNull(schemaBundles);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800178 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800179 int callingUid = Binder.getCallingUid();
180 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700181 EXECUTOR.execute(() -> {
182 try {
183 verifyUserUnlocked(callingUserId);
184 verifyCallingPackage(callingUid, packageName);
185 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
186 for (int i = 0; i < schemaBundles.size(); i++) {
187 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800188 }
Terry Wange04ceab2021-03-29 19:25:12 -0700189 Map<String, List<PackageIdentifier>> schemasPackageAccessible =
190 new ArrayMap<>(schemasPackageAccessibleBundles.size());
191 for (Map.Entry<String, List<Bundle>> entry :
192 schemasPackageAccessibleBundles.entrySet()) {
193 List<PackageIdentifier> packageIdentifiers =
194 new ArrayList<>(entry.getValue().size());
195 for (int i = 0; i < entry.getValue().size(); i++) {
196 packageIdentifiers.add(
197 new PackageIdentifier(entry.getValue().get(i)));
198 }
199 schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
200 }
201 AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
202 SetSchemaResponse setSchemaResponse = impl.setSchema(
203 packageName,
204 databaseName,
205 schemas,
206 schemasNotDisplayedBySystem,
207 schemasPackageAccessible,
208 forceOverride,
209 schemaVersion);
210 invokeCallbackOnResult(callback,
211 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
212 } catch (Throwable t) {
213 invokeCallbackOnError(callback, t);
Alexander Dorokhineab789062021-01-11 21:00:00 -0800214 }
Terry Wange04ceab2021-03-29 19:25:12 -0700215 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800216 }
217
218 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800219 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800220 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800221 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -0800222 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -0800223 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800224 Preconditions.checkNotNull(packageName);
Terry Wang83a24932020-12-09 21:00:18 -0800225 Preconditions.checkNotNull(databaseName);
226 Preconditions.checkNotNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700227 int callingUid = Binder.getCallingUid();
Terry Wangf2093072020-11-30 04:47:19 -0800228 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700229 EXECUTOR.execute(() -> {
230 try {
231 verifyUserUnlocked(callingUserId);
232 verifyCallingPackage(callingUid, packageName);
233 AppSearchImpl impl =
234 mImplInstanceManager.getAppSearchImpl(callingUserId);
235 GetSchemaResponse response = impl.getSchema(packageName, databaseName);
236 invokeCallbackOnResult(
237 callback,
238 AppSearchResult.newSuccessfulResult(response.getBundle()));
239 } catch (Throwable t) {
240 invokeCallbackOnError(callback, t);
241 }
242 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700243 }
244
245 @Override
246 public void getNamespaces(
247 @NonNull String packageName,
248 @NonNull String databaseName,
249 @UserIdInt int userId,
250 @NonNull IAppSearchResultCallback callback) {
251 Preconditions.checkNotNull(packageName);
252 Preconditions.checkNotNull(databaseName);
253 Preconditions.checkNotNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700254 int callingUid = Binder.getCallingUid();
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700255 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700256 EXECUTOR.execute(() -> {
257 try {
258 verifyUserUnlocked(callingUserId);
259 verifyCallingPackage(callingUid, packageName);
260 AppSearchImpl impl =
261 mImplInstanceManager.getAppSearchImpl(callingUserId);
262 List<String> namespaces = impl.getNamespaces(packageName, databaseName);
263 invokeCallbackOnResult(callback,
264 AppSearchResult.newSuccessfulResult(namespaces));
265 } catch (Throwable t) {
266 invokeCallbackOnError(callback, t);
267 }
268 });
Terry Wang83a24932020-12-09 21:00:18 -0800269 }
270
271 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800272 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800273 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700274 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700275 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800276 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800277 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800278 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700279 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700280 Preconditions.checkNotNull(documentBundles);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800281 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800282 int callingUid = Binder.getCallingUid();
283 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700284 EXECUTOR.execute(() -> {
285 try {
286 verifyUserUnlocked(callingUserId);
287 verifyCallingPackage(callingUid, packageName);
288 AppSearchBatchResult.Builder<String, Void> resultBuilder =
289 new AppSearchBatchResult.Builder<>();
290 AppSearchImpl impl =
291 mImplInstanceManager.getAppSearchImpl(callingUserId);
292 for (int i = 0; i < documentBundles.size(); i++) {
293 GenericDocument document = new GenericDocument(documentBundles.get(i));
294 try {
295 impl.putDocument(packageName, databaseName, document,
296 /*logger=*/ null);
297 resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
298 } catch (Throwable t) {
299 resultBuilder.setResult(document.getUri(),
300 throwableToFailedResult(t));
301 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800302 }
Terry Wange04ceab2021-03-29 19:25:12 -0700303 invokeCallbackOnResult(callback, resultBuilder.build());
304 } catch (Throwable t) {
305 invokeCallbackOnError(callback, t);
Alexander Dorokhine18465842020-01-21 01:08:57 -0800306 }
Terry Wange04ceab2021-03-29 19:25:12 -0700307 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800308 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800309
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800310 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800311 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800312 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800313 @NonNull String databaseName,
314 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800315 @NonNull List<String> uris,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800316 @NonNull Map<String, List<String>> typePropertyPaths,
Terry Wangf2093072020-11-30 04:47:19 -0800317 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800318 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800319 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700320 Preconditions.checkNotNull(databaseName);
321 Preconditions.checkNotNull(namespace);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800322 Preconditions.checkNotNull(uris);
323 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800324 int callingUid = Binder.getCallingUid();
325 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700326 EXECUTOR.execute(() -> {
327 try {
328 verifyUserUnlocked(callingUserId);
329 verifyCallingPackage(callingUid, packageName);
330 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
331 new AppSearchBatchResult.Builder<>();
332 AppSearchImpl impl =
333 mImplInstanceManager.getAppSearchImpl(callingUserId);
334 for (int i = 0; i < uris.size(); i++) {
335 String uri = uris.get(i);
336 try {
337 GenericDocument document =
338 impl.getDocument(
339 packageName,
340 databaseName,
341 namespace,
342 uri,
343 typePropertyPaths);
344 resultBuilder.setSuccess(uri, document.getBundle());
345 } catch (Throwable t) {
346 resultBuilder.setResult(uri, throwableToFailedResult(t));
347 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800348 }
Terry Wange04ceab2021-03-29 19:25:12 -0700349 invokeCallbackOnResult(callback, resultBuilder.build());
350 } catch (Throwable t) {
351 invokeCallbackOnError(callback, t);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800352 }
Terry Wange04ceab2021-03-29 19:25:12 -0700353 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800354 }
355
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800356 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800357 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800358 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700359 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700360 @NonNull String queryExpression,
361 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800362 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700363 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800364 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700365 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700366 Preconditions.checkNotNull(queryExpression);
367 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800368 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800369 int callingUid = Binder.getCallingUid();
370 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700371 EXECUTOR.execute(() -> {
372 try {
373 verifyUserUnlocked(callingUserId);
374 verifyCallingPackage(callingUid, packageName);
375 AppSearchImpl impl =
376 mImplInstanceManager.getAppSearchImpl(callingUserId);
377 SearchResultPage searchResultPage =
378 impl.query(
379 packageName,
380 databaseName,
381 queryExpression,
382 new SearchSpec(searchSpecBundle));
383 invokeCallbackOnResult(
384 callback,
385 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
386 } catch (Throwable t) {
387 invokeCallbackOnError(callback, t);
388 }
389 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700390 }
391
Terry Wangf2093072020-11-30 04:47:19 -0800392 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800393 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800394 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800395 @NonNull String queryExpression,
396 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800397 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800398 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800399 Preconditions.checkNotNull(packageName);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800400 Preconditions.checkNotNull(queryExpression);
401 Preconditions.checkNotNull(searchSpecBundle);
402 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800403 int callingUid = Binder.getCallingUid();
404 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700405 EXECUTOR.execute(() -> {
406 try {
407 verifyUserUnlocked(callingUserId);
408 verifyCallingPackage(callingUid, packageName);
409 AppSearchImpl impl =
410 mImplInstanceManager.getAppSearchImpl(callingUserId);
411 SearchResultPage searchResultPage =
412 impl.globalQuery(
413 queryExpression,
414 new SearchSpec(searchSpecBundle),
415 packageName,
416 callingUid);
417 invokeCallbackOnResult(
418 callback,
419 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
420 } catch (Throwable t) {
421 invokeCallbackOnError(callback, t);
422 }
423 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800424 }
425
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700426 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800427 public void getNextPage(
428 long nextPageToken,
429 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700430 @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800431 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800432 int callingUid = Binder.getCallingUid();
433 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700434 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
435 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700436 EXECUTOR.execute(() -> {
437 try {
438 verifyUserUnlocked(callingUserId);
439 AppSearchImpl impl =
440 mImplInstanceManager.getAppSearchImpl(callingUserId);
441 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
442 invokeCallbackOnResult(
443 callback,
444 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
445 } catch (Throwable t) {
446 invokeCallbackOnError(callback, t);
447 }
448 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700449 }
450
451 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800452 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
453 int callingUid = Binder.getCallingUid();
454 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700455 EXECUTOR.execute(() -> {
456 try {
457 verifyUserUnlocked(callingUserId);
458 AppSearchImpl impl =
459 mImplInstanceManager.getAppSearchImpl(callingUserId);
460 impl.invalidateNextPageToken(nextPageToken);
461 } catch (Throwable t) {
462 Log.e(TAG, "Unable to invalidate the query page token", t);
463 }
464 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800465 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800466
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700467 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800468 public void writeQueryResultsToFile(
469 @NonNull String packageName,
470 @NonNull String databaseName,
471 @NonNull ParcelFileDescriptor fileDescriptor,
472 @NonNull String queryExpression,
473 @NonNull Bundle searchSpecBundle,
474 @UserIdInt int userId,
475 @NonNull IAppSearchResultCallback callback) {
476 int callingUid = Binder.getCallingUid();
477 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700478 EXECUTOR.execute(() -> {
479 try {
480 verifyCallingPackage(callingUid, packageName);
481 AppSearchImpl impl =
482 mImplInstanceManager.getAppSearchImpl(callingUserId);
483 // we don't need to append the file. The file is always brand new.
484 try (DataOutputStream outputStream = new DataOutputStream(
485 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
486 SearchResultPage searchResultPage = impl.query(
487 packageName,
488 databaseName,
489 queryExpression,
490 new SearchSpec(searchSpecBundle));
491 while (!searchResultPage.getResults().isEmpty()) {
492 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
493 AppSearchMigrationHelper.writeBundleToOutputStream(
494 outputStream, searchResultPage.getResults().get(i)
495 .getGenericDocument().getBundle());
496 }
497 searchResultPage = impl.getNextPage(
498 searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800499 }
Terry Wang623e3b02021-02-02 20:27:33 -0800500 }
Terry Wange04ceab2021-03-29 19:25:12 -0700501 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
502 } catch (Throwable t) {
503 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800504 }
Terry Wange04ceab2021-03-29 19:25:12 -0700505 });
Terry Wang623e3b02021-02-02 20:27:33 -0800506 }
507
508 @Override
509 public void putDocumentsFromFile(
510 @NonNull String packageName,
511 @NonNull String databaseName,
512 @NonNull ParcelFileDescriptor fileDescriptor,
513 @UserIdInt int userId,
514 @NonNull IAppSearchResultCallback callback) {
515 int callingUid = Binder.getCallingUid();
516 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700517 EXECUTOR.execute(() -> {
518 try {
519 verifyCallingPackage(callingUid, packageName);
520 AppSearchImpl impl =
521 mImplInstanceManager.getAppSearchImpl(callingUserId);
Terry Wang623e3b02021-02-02 20:27:33 -0800522
Terry Wange04ceab2021-03-29 19:25:12 -0700523 GenericDocument document;
524 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
525 try (DataInputStream inputStream = new DataInputStream(
526 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
527 while (true) {
528 try {
529 document = AppSearchMigrationHelper
530 .readDocumentFromInputStream(inputStream);
531 } catch (EOFException e) {
532 // nothing wrong, we just finish the reading.
533 break;
534 }
535 try {
536 impl.putDocument(packageName, databaseName, document,
537 /*logger=*/ null);
538 } catch (Throwable t) {
539 migrationFailureBundles.add(
540 new SetSchemaResponse.MigrationFailure.Builder()
541 .setNamespace(document.getNamespace())
542 .setSchemaType(document.getSchemaType())
543 .setUri(document.getUri())
544 .setAppSearchResult(AppSearchResult
545 .throwableToFailedResult(t))
546 .build().getBundle());
547 }
Terry Wang623e3b02021-02-02 20:27:33 -0800548 }
549 }
Terry Wange04ceab2021-03-29 19:25:12 -0700550 impl.persistToDisk();
551 invokeCallbackOnResult(callback,
552 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
553 } catch (Throwable t) {
554 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800555 }
Terry Wange04ceab2021-03-29 19:25:12 -0700556 });
Terry Wang623e3b02021-02-02 20:27:33 -0800557 }
558
559 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800560 public void reportUsage(
561 @NonNull String packageName,
562 @NonNull String databaseName,
563 @NonNull String namespace,
564 @NonNull String uri,
565 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700566 boolean systemUsage,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800567 @UserIdInt int userId,
568 @NonNull IAppSearchResultCallback callback) {
569 Objects.requireNonNull(databaseName);
570 Objects.requireNonNull(namespace);
571 Objects.requireNonNull(uri);
572 Objects.requireNonNull(callback);
573 int callingUid = Binder.getCallingUid();
574 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700575 EXECUTOR.execute(() -> {
576 try {
577 verifyUserUnlocked(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700578
Terry Wange04ceab2021-03-29 19:25:12 -0700579 if (systemUsage) {
580 // TODO(b/183031844): Validate that the call comes from the system
581 }
582
583 AppSearchImpl impl =
584 mImplInstanceManager.getAppSearchImpl(callingUserId);
585 impl.reportUsage(
586 packageName, databaseName, namespace, uri,
587 usageTimeMillis, systemUsage);
588 invokeCallbackOnResult(
589 callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
590 } catch (Throwable t) {
591 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700592 }
Terry Wange04ceab2021-03-29 19:25:12 -0700593 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800594 }
595
596 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800597 public void removeByUri(
Cassie Wang0c62d992021-01-15 14:39:30 -0800598 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800599 @NonNull String databaseName,
600 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800601 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800602 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800603 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800604 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700605 Preconditions.checkNotNull(databaseName);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700606 Preconditions.checkNotNull(uris);
607 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800608 int callingUid = Binder.getCallingUid();
609 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700610 EXECUTOR.execute(() -> {
611 try {
612 verifyUserUnlocked(callingUserId);
613 verifyCallingPackage(callingUid, packageName);
614 AppSearchBatchResult.Builder<String, Void> resultBuilder =
615 new AppSearchBatchResult.Builder<>();
616 AppSearchImpl impl =
617 mImplInstanceManager.getAppSearchImpl(callingUserId);
618 for (int i = 0; i < uris.size(); i++) {
619 String uri = uris.get(i);
620 try {
621 impl.remove(packageName, databaseName, namespace, uri);
622 resultBuilder.setSuccess(uri, /*result= */ null);
623 } catch (Throwable t) {
624 resultBuilder.setResult(uri, throwableToFailedResult(t));
625 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700626 }
Terry Wange04ceab2021-03-29 19:25:12 -0700627 invokeCallbackOnResult(callback, resultBuilder.build());
628 } catch (Throwable t) {
629 invokeCallbackOnError(callback, t);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700630 }
Terry Wange04ceab2021-03-29 19:25:12 -0700631 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700632 }
633
634 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700635 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800636 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700637 @NonNull String databaseName,
638 @NonNull String queryExpression,
639 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800640 @UserIdInt int userId,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700641 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800642 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700643 Preconditions.checkNotNull(databaseName);
644 Preconditions.checkNotNull(queryExpression);
645 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800646 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800647 int callingUid = Binder.getCallingUid();
648 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700649 EXECUTOR.execute(() -> {
650 try {
651 verifyUserUnlocked(callingUserId);
652 verifyCallingPackage(callingUid, packageName);
653 AppSearchImpl impl =
654 mImplInstanceManager.getAppSearchImpl(callingUserId);
655 impl.removeByQuery(
656 packageName,
657 databaseName,
658 queryExpression,
659 new SearchSpec(searchSpecBundle));
660 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
661 } catch (Throwable t) {
662 invokeCallbackOnError(callback, t);
663 }
664 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700665 }
666
Terry Wangdbd1dca2020-11-03 17:03:56 -0800667 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -0700668 public void getStorageInfo(
669 @NonNull String packageName,
670 @NonNull String databaseName,
671 @UserIdInt int userId,
672 @NonNull IAppSearchResultCallback callback) {
673 Preconditions.checkNotNull(packageName);
674 Preconditions.checkNotNull(databaseName);
675 Preconditions.checkNotNull(callback);
676 int callingUid = Binder.getCallingUid();
677 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700678 EXECUTOR.execute(() -> {
679 try {
680 verifyUserUnlocked(callingUserId);
681 verifyCallingPackage(callingUid, packageName);
682 AppSearchImpl impl =
683 mImplInstanceManager.getAppSearchImpl(callingUserId);
684 StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
685 databaseName);
686 Bundle storageInfoBundle = storageInfo.getBundle();
687 invokeCallbackOnResult(
688 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
689 } catch (Throwable t) {
690 invokeCallbackOnError(callback, t);
691 }
692 });
Cassie Wang8f0df492021-03-24 09:23:18 -0700693 }
694
695 @Override
Terry Wang2da17852020-12-16 19:59:08 -0800696 public void persistToDisk(@UserIdInt int userId) {
Cassie Wangb0d60122021-03-30 12:38:46 -0700697 int callingUid = Binder.getCallingUid();
Terry Wang2da17852020-12-16 19:59:08 -0800698 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700699 EXECUTOR.execute(() -> {
700 try {
701 verifyUserUnlocked(callingUserId);
702 AppSearchImpl impl =
703 mImplInstanceManager.getAppSearchImpl(callingUserId);
704 impl.persistToDisk();
705 } catch (Throwable t) {
706 Log.e(TAG, "Unable to persist the data to disk", t);
707 }
708 });
Terry Wang2da17852020-12-16 19:59:08 -0800709 }
710
711 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800712 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800713 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800714 int callingUid = Binder.getCallingUid();
715 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700716 EXECUTOR.execute(() -> {
717 try {
718 verifyUserUnlocked(callingUserId);
719 mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
720 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
721 } catch (Throwable t) {
722 invokeCallbackOnError(callback, t);
723 }
724 });
Terry Wangdbd1dca2020-11-03 17:03:56 -0800725 }
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}