blob: 35c441e9eb98bfbce8fc158c7e5a8b657a6e4e04 [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;
Cassie Wang0c62d992021-01-15 14:39:30 -080043import android.content.pm.PackageManagerInternal;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080044import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070045import android.os.Bundle;
Terry Wang623e3b02021-02-02 20:27:33 -080046import android.os.ParcelFileDescriptor;
Terry Wangdbd1dca2020-11-03 17:03:56 -080047import android.os.ParcelableException;
48import android.os.RemoteException;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080049import android.os.SystemClock;
Cassie Wang0c62d992021-01-15 14:39:30 -080050import android.os.UserHandle;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070051import android.os.UserManager;
Alexander Dorokhineab789062021-01-11 21:00:00 -080052import android.util.ArrayMap;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080053import android.util.ArraySet;
Terry Wangdbd1dca2020-11-03 17:03:56 -080054import android.util.Log;
Terry Wang12dc6c02021-03-31 19:26:16 -070055import android.util.Slog;
Terry Wangfebbead2019-10-17 17:05:18 -070056
Cassie Wang15c86972021-02-09 13:43:25 -080057import com.android.internal.annotations.GuardedBy;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080058import com.android.internal.util.Preconditions;
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;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080065
Terry Wang623e3b02021-02-02 20:27:33 -080066import java.io.DataInputStream;
67import java.io.DataOutputStream;
68import java.io.EOFException;
69import java.io.FileInputStream;
70import java.io.FileOutputStream;
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080071import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080072import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080073import java.util.Map;
Alexander Dorokhined18f8842021-01-20 15:26:13 -080074import java.util.Objects;
Cassie Wang9ba9ae12021-02-01 16:39:37 -080075import java.util.Set;
Terry Wange04ceab2021-03-29 19:25:12 -070076import java.util.concurrent.Executor;
77import java.util.concurrent.SynchronousQueue;
78import java.util.concurrent.ThreadPoolExecutor;
79import java.util.concurrent.TimeUnit;
Alexander Dorokhine18465842020-01-21 01:08:57 -080080
Cassie Wang0c62d992021-01-15 14:39:30 -080081/** TODO(b/142567528): add comments when implement this class */
Terry Wangfebbead2019-10-17 17:05:18 -070082public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070083 private static final String TAG = "AppSearchManagerService";
Terry Wang12dc6c02021-03-31 19:26:16 -070084 private final Context mContext;
Cassie Wang0c62d992021-01-15 14:39:30 -080085 private PackageManagerInternal mPackageManagerInternal;
Cassie Wang21c2d6a2021-01-20 23:59:55 -080086 private ImplInstanceManager mImplInstanceManager;
Pinyao Tingd5c2ed92021-03-18 14:51:54 -070087 private UserManager mUserManager;
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -080088 private LoggerInstanceManager mLoggerInstanceManager;
Terry Wangfebbead2019-10-17 17:05:18 -070089
Terry Wange04ceab2021-03-29 19:25:12 -070090 // Never call shutdownNow(). It will cancel the futures it's returned. And since
91 // Executor#execute won't return anything, we will hang forever waiting for the execution.
92 // AppSearch multi-thread execution is guarded by Read & Write Lock in AppSearchImpl, all
93 // mutate requests will need to gain write lock and query requests need to gain read lock.
94 private static final Executor EXECUTOR = new ThreadPoolExecutor(/*corePoolSize=*/1,
95 Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
96 new SynchronousQueue<Runnable>());
97
Cassie Wang15c86972021-02-09 13:43:25 -080098 // Cache of unlocked user ids so we don't have to query UserManager service each time. The
99 // "locked" suffix refers to the fact that access to the field should be locked; unrelated to
100 // the unlocked status of user ids.
101 @GuardedBy("mUnlockedUserIdsLocked")
102 private final Set<Integer> mUnlockedUserIdsLocked = new ArraySet<>();
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800103
Terry Wangfebbead2019-10-17 17:05:18 -0700104 public AppSearchManagerService(Context context) {
105 super(context);
Terry Wang12dc6c02021-03-31 19:26:16 -0700106 mContext = context;
Terry Wangfebbead2019-10-17 17:05:18 -0700107 }
108
109 @Override
110 public void onStart() {
111 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
Cassie Wang0c62d992021-01-15 14:39:30 -0800112 mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
Terry Wang12dc6c02021-03-31 19:26:16 -0700113 mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
114 mUserManager = mContext.getSystemService(UserManager.class);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800115 mLoggerInstanceManager = LoggerInstanceManager.getInstance();
Terry Wang12dc6c02021-03-31 19:26:16 -0700116 registerReceivers();
117 }
118
119 private void registerReceivers() {
120 mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
121 new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
122 /*scheduler=*/ null);
123 }
124
125 private class UserActionReceiver extends BroadcastReceiver {
126 @Override
127 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
128 switch (intent.getAction()) {
129 case Intent.ACTION_USER_REMOVED:
130 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
131 if (userId == USER_NULL) {
132 Slog.e(TAG, "userId is missing in the intent: " + intent);
133 return;
134 }
135 handleUserRemoved(userId);
136 break;
137 default:
138 Slog.e(TAG, "Received unknown intent: " + intent);
139 }
140 }
141 }
142
143 /**
144 * Handles user removed action.
145 *
146 * <p>Only need to clear the AppSearchImpl instance. The data of AppSearch is saved in the
147 * "credential encrypted" system directory of each user. That directory will be auto-deleted
148 * when a user is removed.
149 *
150 * @param userId The multi-user userId of the user that need to be removed.
151 *
152 * @see android.os.Environment#getDataSystemCeDirectory
153 */
154 private void handleUserRemoved(@UserIdInt int userId) {
155 try {
156 mImplInstanceManager.removeAppSearchImplForUser(userId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800157 mLoggerInstanceManager.removePlatformLoggerForUser(userId);
Terry Wang12dc6c02021-03-31 19:26:16 -0700158 Slog.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
159 } catch (Throwable t) {
160 Slog.e(TAG, "Unable to remove data for user: " + userId, t);
161 }
Terry Wangfebbead2019-10-17 17:05:18 -0700162 }
163
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800164 @Override
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700165 public void onUserUnlocking(@NonNull TargetUser user) {
Cassie Wang15c86972021-02-09 13:43:25 -0800166 synchronized (mUnlockedUserIdsLocked) {
167 mUnlockedUserIdsLocked.add(user.getUserIdentifier());
168 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800169 }
170
Terry Wangfebbead2019-10-17 17:05:18 -0700171 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800172 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800173 public void setSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800174 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700175 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700176 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine315cca62021-03-04 12:34:41 -0800177 @NonNull List<String> schemasNotDisplayedBySystem,
Alexander Dorokhineab789062021-01-11 21:00:00 -0800178 @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800179 boolean forceOverride,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700180 int schemaVersion,
Terry Wangc10610d2021-03-21 13:21:24 -0700181 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800182 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800183 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700184 Preconditions.checkNotNull(databaseName);
Alexander Dorokhine92ce3532020-10-06 01:39:36 -0700185 Preconditions.checkNotNull(schemaBundles);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800186 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800187 int callingUid = Binder.getCallingUid();
188 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700189 EXECUTOR.execute(() -> {
190 try {
191 verifyUserUnlocked(callingUserId);
192 verifyCallingPackage(callingUid, packageName);
193 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
194 for (int i = 0; i < schemaBundles.size(); i++) {
195 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhineab789062021-01-11 21:00:00 -0800196 }
Terry Wange04ceab2021-03-29 19:25:12 -0700197 Map<String, List<PackageIdentifier>> schemasPackageAccessible =
198 new ArrayMap<>(schemasPackageAccessibleBundles.size());
199 for (Map.Entry<String, List<Bundle>> entry :
200 schemasPackageAccessibleBundles.entrySet()) {
201 List<PackageIdentifier> packageIdentifiers =
202 new ArrayList<>(entry.getValue().size());
203 for (int i = 0; i < entry.getValue().size(); i++) {
204 packageIdentifiers.add(
205 new PackageIdentifier(entry.getValue().get(i)));
206 }
207 schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
208 }
209 AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
210 SetSchemaResponse setSchemaResponse = impl.setSchema(
211 packageName,
212 databaseName,
213 schemas,
214 schemasNotDisplayedBySystem,
215 schemasPackageAccessible,
216 forceOverride,
217 schemaVersion);
218 invokeCallbackOnResult(callback,
219 AppSearchResult.newSuccessfulResult(setSchemaResponse.getBundle()));
220 } catch (Throwable t) {
221 invokeCallbackOnError(callback, t);
Alexander Dorokhineab789062021-01-11 21:00:00 -0800222 }
Terry Wange04ceab2021-03-29 19:25:12 -0700223 });
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800224 }
225
226 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800227 public void getSchema(
Cassie Wang0c62d992021-01-15 14:39:30 -0800228 @NonNull String packageName,
Terry Wang83a24932020-12-09 21:00:18 -0800229 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -0800230 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -0800231 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800232 Preconditions.checkNotNull(packageName);
Terry Wang83a24932020-12-09 21:00:18 -0800233 Preconditions.checkNotNull(databaseName);
234 Preconditions.checkNotNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700235 int callingUid = Binder.getCallingUid();
Terry Wangf2093072020-11-30 04:47:19 -0800236 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700237 EXECUTOR.execute(() -> {
238 try {
239 verifyUserUnlocked(callingUserId);
240 verifyCallingPackage(callingUid, packageName);
241 AppSearchImpl impl =
242 mImplInstanceManager.getAppSearchImpl(callingUserId);
243 GetSchemaResponse response = impl.getSchema(packageName, databaseName);
244 invokeCallbackOnResult(
245 callback,
246 AppSearchResult.newSuccessfulResult(response.getBundle()));
247 } catch (Throwable t) {
248 invokeCallbackOnError(callback, t);
249 }
250 });
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700251 }
252
253 @Override
254 public void getNamespaces(
255 @NonNull String packageName,
256 @NonNull String databaseName,
257 @UserIdInt int userId,
258 @NonNull IAppSearchResultCallback callback) {
259 Preconditions.checkNotNull(packageName);
260 Preconditions.checkNotNull(databaseName);
261 Preconditions.checkNotNull(callback);
Cassie Wangb0d60122021-03-30 12:38:46 -0700262 int callingUid = Binder.getCallingUid();
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700263 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700264 EXECUTOR.execute(() -> {
265 try {
266 verifyUserUnlocked(callingUserId);
267 verifyCallingPackage(callingUid, packageName);
268 AppSearchImpl impl =
269 mImplInstanceManager.getAppSearchImpl(callingUserId);
270 List<String> namespaces = impl.getNamespaces(packageName, databaseName);
271 invokeCallbackOnResult(callback,
272 AppSearchResult.newSuccessfulResult(namespaces));
273 } catch (Throwable t) {
274 invokeCallbackOnError(callback, t);
275 }
276 });
Terry Wang83a24932020-12-09 21:00:18 -0800277 }
278
279 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800280 public void putDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800281 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700282 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700283 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800284 @UserIdInt int userId,
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800285 @ElapsedRealtimeLong long binderCallStartTimeMillis,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800286 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800287 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700288 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700289 Preconditions.checkNotNull(documentBundles);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800290 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800291 int callingUid = Binder.getCallingUid();
292 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700293 EXECUTOR.execute(() -> {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800294 long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
295 @AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
296 PlatformLogger logger = null;
297 int operationSuccessCount = 0;
298 int operationFailureCount = 0;
Terry Wange04ceab2021-03-29 19:25:12 -0700299 try {
300 verifyUserUnlocked(callingUserId);
301 verifyCallingPackage(callingUid, packageName);
302 AppSearchBatchResult.Builder<String, Void> resultBuilder =
303 new AppSearchBatchResult.Builder<>();
304 AppSearchImpl impl =
305 mImplInstanceManager.getAppSearchImpl(callingUserId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800306 logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700307 for (int i = 0; i < documentBundles.size(); i++) {
308 GenericDocument document = new GenericDocument(documentBundles.get(i));
309 try {
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800310 impl.putDocument(packageName, databaseName, document, logger);
Terry Wange04ceab2021-03-29 19:25:12 -0700311 resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800312 ++operationSuccessCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700313 } catch (Throwable t) {
314 resultBuilder.setResult(document.getUri(),
315 throwableToFailedResult(t));
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800316 AppSearchResult<Void> result = throwableToFailedResult(t);
317 resultBuilder.setResult(document.getUri(), result);
318 // for failures, we would just log the one for last failure
319 statusCode = result.getResultCode();
320 ++operationFailureCount;
Terry Wange04ceab2021-03-29 19:25:12 -0700321 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800322 }
Terry Wange04ceab2021-03-29 19:25:12 -0700323 invokeCallbackOnResult(callback, resultBuilder.build());
324 } catch (Throwable t) {
325 invokeCallbackOnError(callback, t);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800326 } finally {
327 if (logger != null) {
328 CallStats.Builder cBuilder = new CallStats.Builder(packageName,
329 databaseName)
330 .setCallType(CallStats.CALL_TYPE_PUT_DOCUMENTS)
331 // TODO(b/173532925) check the existing binder call latency chart
332 // is good enough for us:
333 // http://dashboards/view/_72c98f9a_91d9_41d4_ab9a_bc14f79742b4
334 .setEstimatedBinderLatencyMillis(
335 2 * (int) (totalLatencyStartTimeMillis
336 - binderCallStartTimeMillis))
337 .setNumOperationsSucceeded(operationSuccessCount)
338 .setNumOperationsFailed(operationFailureCount);
339 cBuilder.getGeneralStatsBuilder()
340 .setStatusCode(statusCode)
341 .setTotalLatencyMillis(
342 (int) (SystemClock.elapsedRealtime()
343 - totalLatencyStartTimeMillis));
344 logger.logStats(cBuilder.build());
345 }
Alexander Dorokhine18465842020-01-21 01:08:57 -0800346 }
Terry Wange04ceab2021-03-29 19:25:12 -0700347 });
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800348 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800349
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800350 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800351 public void getDocuments(
Cassie Wang0c62d992021-01-15 14:39:30 -0800352 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800353 @NonNull String databaseName,
354 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800355 @NonNull List<String> uris,
Alexander Dorokhine87cdd152021-01-20 15:41:25 -0800356 @NonNull Map<String, List<String>> typePropertyPaths,
Terry Wangf2093072020-11-30 04:47:19 -0800357 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800358 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800359 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700360 Preconditions.checkNotNull(databaseName);
361 Preconditions.checkNotNull(namespace);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800362 Preconditions.checkNotNull(uris);
363 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800364 int callingUid = Binder.getCallingUid();
365 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700366 EXECUTOR.execute(() -> {
367 try {
368 verifyUserUnlocked(callingUserId);
369 verifyCallingPackage(callingUid, packageName);
370 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
371 new AppSearchBatchResult.Builder<>();
372 AppSearchImpl impl =
373 mImplInstanceManager.getAppSearchImpl(callingUserId);
374 for (int i = 0; i < uris.size(); i++) {
375 String uri = uris.get(i);
376 try {
377 GenericDocument document =
378 impl.getDocument(
379 packageName,
380 databaseName,
381 namespace,
382 uri,
383 typePropertyPaths);
384 resultBuilder.setSuccess(uri, document.getBundle());
385 } catch (Throwable t) {
386 resultBuilder.setResult(uri, throwableToFailedResult(t));
387 }
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800388 }
Terry Wange04ceab2021-03-29 19:25:12 -0700389 invokeCallbackOnResult(callback, resultBuilder.build());
390 } catch (Throwable t) {
391 invokeCallbackOnError(callback, t);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800392 }
Terry Wange04ceab2021-03-29 19:25:12 -0700393 });
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800394 }
395
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800396 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800397 public void query(
Cassie Wang0c62d992021-01-15 14:39:30 -0800398 @NonNull String packageName,
Terry Wang6413aee2020-10-07 03:04:58 -0700399 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700400 @NonNull String queryExpression,
401 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800402 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700403 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800404 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700405 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700406 Preconditions.checkNotNull(queryExpression);
407 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800408 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800409 int callingUid = Binder.getCallingUid();
410 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700411 EXECUTOR.execute(() -> {
412 try {
413 verifyUserUnlocked(callingUserId);
414 verifyCallingPackage(callingUid, packageName);
415 AppSearchImpl impl =
416 mImplInstanceManager.getAppSearchImpl(callingUserId);
417 SearchResultPage searchResultPage =
418 impl.query(
419 packageName,
420 databaseName,
421 queryExpression,
422 new SearchSpec(searchSpecBundle));
423 invokeCallbackOnResult(
424 callback,
425 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
426 } catch (Throwable t) {
427 invokeCallbackOnError(callback, t);
428 }
429 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700430 }
431
Terry Wangf2093072020-11-30 04:47:19 -0800432 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800433 public void globalQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800434 @NonNull String packageName,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800435 @NonNull String queryExpression,
436 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800437 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800438 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800439 Preconditions.checkNotNull(packageName);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800440 Preconditions.checkNotNull(queryExpression);
441 Preconditions.checkNotNull(searchSpecBundle);
442 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800443 int callingUid = Binder.getCallingUid();
444 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700445 EXECUTOR.execute(() -> {
446 try {
447 verifyUserUnlocked(callingUserId);
448 verifyCallingPackage(callingUid, packageName);
449 AppSearchImpl impl =
450 mImplInstanceManager.getAppSearchImpl(callingUserId);
451 SearchResultPage searchResultPage =
452 impl.globalQuery(
453 queryExpression,
454 new SearchSpec(searchSpecBundle),
455 packageName,
456 callingUid);
457 invokeCallbackOnResult(
458 callback,
459 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
460 } catch (Throwable t) {
461 invokeCallbackOnError(callback, t);
462 }
463 });
Terry Wangbfbfcac2020-11-06 15:46:44 -0800464 }
465
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700466 @Override
Cassie Wang0c62d992021-01-15 14:39:30 -0800467 public void getNextPage(
468 long nextPageToken,
469 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700470 @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800471 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800472 int callingUid = Binder.getCallingUid();
473 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700474 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
475 // opened it
Terry Wange04ceab2021-03-29 19:25:12 -0700476 EXECUTOR.execute(() -> {
477 try {
478 verifyUserUnlocked(callingUserId);
479 AppSearchImpl impl =
480 mImplInstanceManager.getAppSearchImpl(callingUserId);
481 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
482 invokeCallbackOnResult(
483 callback,
484 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
485 } catch (Throwable t) {
486 invokeCallbackOnError(callback, t);
487 }
488 });
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700489 }
490
491 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800492 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
493 int callingUid = Binder.getCallingUid();
494 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700495 EXECUTOR.execute(() -> {
496 try {
497 verifyUserUnlocked(callingUserId);
498 AppSearchImpl impl =
499 mImplInstanceManager.getAppSearchImpl(callingUserId);
500 impl.invalidateNextPageToken(nextPageToken);
501 } catch (Throwable t) {
502 Log.e(TAG, "Unable to invalidate the query page token", t);
503 }
504 });
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800505 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800506
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700507 @Override
Terry Wang623e3b02021-02-02 20:27:33 -0800508 public void writeQueryResultsToFile(
509 @NonNull String packageName,
510 @NonNull String databaseName,
511 @NonNull ParcelFileDescriptor fileDescriptor,
512 @NonNull String queryExpression,
513 @NonNull Bundle searchSpecBundle,
514 @UserIdInt int userId,
515 @NonNull IAppSearchResultCallback callback) {
516 int callingUid = Binder.getCallingUid();
517 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700518 EXECUTOR.execute(() -> {
519 try {
520 verifyCallingPackage(callingUid, packageName);
521 AppSearchImpl impl =
522 mImplInstanceManager.getAppSearchImpl(callingUserId);
523 // we don't need to append the file. The file is always brand new.
524 try (DataOutputStream outputStream = new DataOutputStream(
525 new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
526 SearchResultPage searchResultPage = impl.query(
527 packageName,
528 databaseName,
529 queryExpression,
530 new SearchSpec(searchSpecBundle));
531 while (!searchResultPage.getResults().isEmpty()) {
532 for (int i = 0; i < searchResultPage.getResults().size(); i++) {
533 AppSearchMigrationHelper.writeBundleToOutputStream(
534 outputStream, searchResultPage.getResults().get(i)
535 .getGenericDocument().getBundle());
536 }
537 searchResultPage = impl.getNextPage(
538 searchResultPage.getNextPageToken());
Terry Wang623e3b02021-02-02 20:27:33 -0800539 }
Terry Wang623e3b02021-02-02 20:27:33 -0800540 }
Terry Wange04ceab2021-03-29 19:25:12 -0700541 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
542 } catch (Throwable t) {
543 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800544 }
Terry Wange04ceab2021-03-29 19:25:12 -0700545 });
Terry Wang623e3b02021-02-02 20:27:33 -0800546 }
547
548 @Override
549 public void putDocumentsFromFile(
550 @NonNull String packageName,
551 @NonNull String databaseName,
552 @NonNull ParcelFileDescriptor fileDescriptor,
553 @UserIdInt int userId,
554 @NonNull IAppSearchResultCallback callback) {
555 int callingUid = Binder.getCallingUid();
556 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700557 EXECUTOR.execute(() -> {
558 try {
559 verifyCallingPackage(callingUid, packageName);
560 AppSearchImpl impl =
561 mImplInstanceManager.getAppSearchImpl(callingUserId);
Terry Wang623e3b02021-02-02 20:27:33 -0800562
Terry Wange04ceab2021-03-29 19:25:12 -0700563 GenericDocument document;
564 ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
565 try (DataInputStream inputStream = new DataInputStream(
566 new FileInputStream(fileDescriptor.getFileDescriptor()))) {
567 while (true) {
568 try {
569 document = AppSearchMigrationHelper
570 .readDocumentFromInputStream(inputStream);
571 } catch (EOFException e) {
572 // nothing wrong, we just finish the reading.
573 break;
574 }
575 try {
576 impl.putDocument(packageName, databaseName, document,
577 /*logger=*/ null);
578 } catch (Throwable t) {
579 migrationFailureBundles.add(
580 new SetSchemaResponse.MigrationFailure.Builder()
581 .setNamespace(document.getNamespace())
582 .setSchemaType(document.getSchemaType())
583 .setUri(document.getUri())
584 .setAppSearchResult(AppSearchResult
585 .throwableToFailedResult(t))
586 .build().getBundle());
587 }
Terry Wang623e3b02021-02-02 20:27:33 -0800588 }
589 }
Terry Wange04ceab2021-03-29 19:25:12 -0700590 impl.persistToDisk();
591 invokeCallbackOnResult(callback,
592 AppSearchResult.newSuccessfulResult(migrationFailureBundles));
593 } catch (Throwable t) {
594 invokeCallbackOnError(callback, t);
Terry Wang623e3b02021-02-02 20:27:33 -0800595 }
Terry Wange04ceab2021-03-29 19:25:12 -0700596 });
Terry Wang623e3b02021-02-02 20:27:33 -0800597 }
598
599 @Override
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800600 public void reportUsage(
601 @NonNull String packageName,
602 @NonNull String databaseName,
603 @NonNull String namespace,
604 @NonNull String uri,
605 long usageTimeMillis,
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700606 boolean systemUsage,
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800607 @UserIdInt int userId,
608 @NonNull IAppSearchResultCallback callback) {
609 Objects.requireNonNull(databaseName);
610 Objects.requireNonNull(namespace);
611 Objects.requireNonNull(uri);
612 Objects.requireNonNull(callback);
613 int callingUid = Binder.getCallingUid();
614 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700615 EXECUTOR.execute(() -> {
616 try {
617 verifyUserUnlocked(callingUserId);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700618
Terry Wange04ceab2021-03-29 19:25:12 -0700619 if (systemUsage) {
620 // TODO(b/183031844): Validate that the call comes from the system
621 }
622
623 AppSearchImpl impl =
624 mImplInstanceManager.getAppSearchImpl(callingUserId);
625 impl.reportUsage(
626 packageName, databaseName, namespace, uri,
627 usageTimeMillis, systemUsage);
628 invokeCallbackOnResult(
629 callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
630 } catch (Throwable t) {
631 invokeCallbackOnError(callback, t);
Alexander Dorokhine9795b512021-03-23 22:06:59 -0700632 }
Terry Wange04ceab2021-03-29 19:25:12 -0700633 });
Alexander Dorokhined18f8842021-01-20 15:26:13 -0800634 }
635
636 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800637 public void removeByUri(
Cassie Wang0c62d992021-01-15 14:39:30 -0800638 @NonNull String packageName,
Terry Wangf2093072020-11-30 04:47:19 -0800639 @NonNull String databaseName,
640 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800641 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800642 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800643 @NonNull IAppSearchBatchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800644 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700645 Preconditions.checkNotNull(databaseName);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700646 Preconditions.checkNotNull(uris);
647 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800648 int callingUid = Binder.getCallingUid();
649 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700650 EXECUTOR.execute(() -> {
651 try {
652 verifyUserUnlocked(callingUserId);
653 verifyCallingPackage(callingUid, packageName);
654 AppSearchBatchResult.Builder<String, Void> resultBuilder =
655 new AppSearchBatchResult.Builder<>();
656 AppSearchImpl impl =
657 mImplInstanceManager.getAppSearchImpl(callingUserId);
658 for (int i = 0; i < uris.size(); i++) {
659 String uri = uris.get(i);
660 try {
661 impl.remove(packageName, databaseName, namespace, uri);
662 resultBuilder.setSuccess(uri, /*result= */ null);
663 } catch (Throwable t) {
664 resultBuilder.setResult(uri, throwableToFailedResult(t));
665 }
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700666 }
Terry Wange04ceab2021-03-29 19:25:12 -0700667 invokeCallbackOnResult(callback, resultBuilder.build());
668 } catch (Throwable t) {
669 invokeCallbackOnError(callback, t);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700670 }
Terry Wange04ceab2021-03-29 19:25:12 -0700671 });
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700672 }
673
674 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700675 public void removeByQuery(
Cassie Wang0c62d992021-01-15 14:39:30 -0800676 @NonNull String packageName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700677 @NonNull String databaseName,
678 @NonNull String queryExpression,
679 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800680 @UserIdInt int userId,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700681 @NonNull IAppSearchResultCallback callback) {
Cassie Wang0c62d992021-01-15 14:39:30 -0800682 Preconditions.checkNotNull(packageName);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700683 Preconditions.checkNotNull(databaseName);
684 Preconditions.checkNotNull(queryExpression);
685 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800686 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800687 int callingUid = Binder.getCallingUid();
688 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700689 EXECUTOR.execute(() -> {
690 try {
691 verifyUserUnlocked(callingUserId);
692 verifyCallingPackage(callingUid, packageName);
693 AppSearchImpl impl =
694 mImplInstanceManager.getAppSearchImpl(callingUserId);
695 impl.removeByQuery(
696 packageName,
697 databaseName,
698 queryExpression,
699 new SearchSpec(searchSpecBundle));
700 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
701 } catch (Throwable t) {
702 invokeCallbackOnError(callback, t);
703 }
704 });
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700705 }
706
Terry Wangdbd1dca2020-11-03 17:03:56 -0800707 @Override
Cassie Wang8f0df492021-03-24 09:23:18 -0700708 public void getStorageInfo(
709 @NonNull String packageName,
710 @NonNull String databaseName,
711 @UserIdInt int userId,
712 @NonNull IAppSearchResultCallback callback) {
713 Preconditions.checkNotNull(packageName);
714 Preconditions.checkNotNull(databaseName);
715 Preconditions.checkNotNull(callback);
716 int callingUid = Binder.getCallingUid();
717 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700718 EXECUTOR.execute(() -> {
719 try {
720 verifyUserUnlocked(callingUserId);
721 verifyCallingPackage(callingUid, packageName);
722 AppSearchImpl impl =
723 mImplInstanceManager.getAppSearchImpl(callingUserId);
724 StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
725 databaseName);
726 Bundle storageInfoBundle = storageInfo.getBundle();
727 invokeCallbackOnResult(
728 callback, AppSearchResult.newSuccessfulResult(storageInfoBundle));
729 } catch (Throwable t) {
730 invokeCallbackOnError(callback, t);
731 }
732 });
Cassie Wang8f0df492021-03-24 09:23:18 -0700733 }
734
735 @Override
Terry Wang2da17852020-12-16 19:59:08 -0800736 public void persistToDisk(@UserIdInt int userId) {
Cassie Wangb0d60122021-03-30 12:38:46 -0700737 int callingUid = Binder.getCallingUid();
Terry Wang2da17852020-12-16 19:59:08 -0800738 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700739 EXECUTOR.execute(() -> {
740 try {
741 verifyUserUnlocked(callingUserId);
742 AppSearchImpl impl =
743 mImplInstanceManager.getAppSearchImpl(callingUserId);
744 impl.persistToDisk();
745 } catch (Throwable t) {
746 Log.e(TAG, "Unable to persist the data to disk", t);
747 }
748 });
Terry Wang2da17852020-12-16 19:59:08 -0800749 }
750
751 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800752 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800753 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800754 int callingUid = Binder.getCallingUid();
755 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wange04ceab2021-03-29 19:25:12 -0700756 EXECUTOR.execute(() -> {
757 try {
758 verifyUserUnlocked(callingUserId);
759 mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId);
Xiaoyu Jinf8cc2012021-03-12 11:00:54 -0800760 mLoggerInstanceManager.getOrCreatePlatformLogger(getContext(), callingUserId);
Terry Wange04ceab2021-03-29 19:25:12 -0700761 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
762 } catch (Throwable t) {
763 invokeCallbackOnError(callback, t);
764 }
765 });
Terry Wangdbd1dca2020-11-03 17:03:56 -0800766 }
767
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800768 private void verifyUserUnlocked(int callingUserId) {
Cassie Wang15c86972021-02-09 13:43:25 -0800769 synchronized (mUnlockedUserIdsLocked) {
Pinyao Tingd5c2ed92021-03-18 14:51:54 -0700770 // First, check the local copy.
771 if (mUnlockedUserIdsLocked.contains(callingUserId)) {
772 return;
773 }
774 // If the local copy says the user is locked, check with UM for the actual state,
775 // since the user might just have been unlocked.
776 if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId))) {
Cassie Wang15c86972021-02-09 13:43:25 -0800777 throw new IllegalStateException(
778 "User " + callingUserId + " is locked or not running.");
779 }
Cassie Wang9ba9ae12021-02-01 16:39:37 -0800780 }
781 }
782
Cassie Wang0c62d992021-01-15 14:39:30 -0800783 private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) {
784 Preconditions.checkNotNull(callingPackage);
785 if (mPackageManagerInternal.getPackageUid(
786 callingPackage, /*flags=*/ 0, UserHandle.getUserId(callingUid))
787 != callingUid) {
788 throw new SecurityException(
789 "Specified calling package ["
790 + callingPackage
791 + "] does not match the calling uid "
792 + callingUid);
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700793 }
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700794 }
795
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800796 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -0800797 private void invokeCallbackOnResult(
798 IAppSearchResultCallback callback, AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800799 try {
800 callback.onResult(result);
801 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800802 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800803 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800804 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800805
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800806 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Cassie Wang0c62d992021-01-15 14:39:30 -0800807 private void invokeCallbackOnResult(
808 IAppSearchBatchResultCallback callback, AppSearchBatchResult<?, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800809 try {
810 callback.onResult(result);
811 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800812 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800813 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800814 }
815
816 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800817 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800818 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800819 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -0800820 */
821 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
822 try {
823 callback.onResult(throwableToFailedResult(throwable));
824 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800825 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800826 }
827 }
828
829 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800830 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800831 *
832 * <p>The throwable is converted to {@link ParcelableException}.
833 */
Cassie Wang0c62d992021-01-15 14:39:30 -0800834 private void invokeCallbackOnError(
835 IAppSearchBatchResultCallback callback, Throwable throwable) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800836 try {
Terry Wang9d8f4272021-02-04 21:01:10 -0800837 //TODO(b/175067650) verify ParcelableException could propagate throwable correctly.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800838 callback.onSystemError(new ParcelableException(throwable));
839 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800840 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800841 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800842 }
Terry Wangfebbead2019-10-17 17:05:18 -0700843 }
Terry Wangf2093072020-11-30 04:47:19 -0800844
Cassie Wang0c62d992021-01-15 14:39:30 -0800845 // TODO(b/173553485) verifying that the caller has permission to access target user's data
846 // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
847 // TODO(b/173553485) Implement SystemService.onUserStopping()
Terry Wangf2093072020-11-30 04:47:19 -0800848 private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
849 int callingPid = Binder.getCallingPid();
Cassie Wang0c62d992021-01-15 14:39:30 -0800850 return ActivityManager.handleIncomingUser(
851 callingPid,
852 callingUid,
853 userId,
854 /*allowAll=*/ false,
855 /*requireFull=*/ false,
856 /*name=*/ null,
857 /*callerPackage=*/ null);
Terry Wangf2093072020-11-30 04:47:19 -0800858 }
Terry Wangfebbead2019-10-17 17:05:18 -0700859}