blob: 87c41e53dc63ae62710a00e22c0914fb5ab8d8bd [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;
19
sidchhabraa7c8f8a2020-01-16 18:38:17 -080020import android.annotation.NonNull;
Terry Wangf2093072020-11-30 04:47:19 -080021import android.annotation.UserIdInt;
22import android.app.ActivityManager;
Alexander Dorokhine18465842020-01-21 01:08:57 -080023import android.app.appsearch.AppSearchBatchResult;
Alexander Dorokhine969f4462020-03-05 15:54:19 -080024import android.app.appsearch.AppSearchResult;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070025import android.app.appsearch.AppSearchSchema;
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -070026import android.app.appsearch.GenericDocument;
Terry Wangdbd1dca2020-11-03 17:03:56 -080027import android.app.appsearch.IAppSearchBatchResultCallback;
Terry Wangfebbead2019-10-17 17:05:18 -070028import android.app.appsearch.IAppSearchManager;
Terry Wangdbd1dca2020-11-03 17:03:56 -080029import android.app.appsearch.IAppSearchResultCallback;
Terry Wang26b9e5c2020-10-23 02:05:01 -070030import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070031import android.app.appsearch.SearchSpec;
Terry Wangfebbead2019-10-17 17:05:18 -070032import android.content.Context;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080033import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070034import android.os.Bundle;
Terry Wangdbd1dca2020-11-03 17:03:56 -080035import android.os.ParcelableException;
36import android.os.RemoteException;
Terry Wangdbd1dca2020-11-03 17:03:56 -080037import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070038
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080039import com.android.internal.util.Preconditions;
Terry Wangfebbead2019-10-17 17:05:18 -070040import com.android.server.SystemService;
Alexander Dorokhinef660d8f2020-10-29 22:37:00 -070041import com.android.server.appsearch.external.localstorage.AppSearchImpl;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080042
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080043import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080044import java.util.List;
45
Terry Wangfebbead2019-10-17 17:05:18 -070046/**
47 * TODO(b/142567528): add comments when implement this class
48 */
49public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070050 private static final String TAG = "AppSearchManagerService";
Terry Wangfebbead2019-10-17 17:05:18 -070051
52 public AppSearchManagerService(Context context) {
53 super(context);
54 }
55
56 @Override
57 public void onStart() {
58 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
59 }
60
61 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080062 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -080063 public void setSchema(
Terry Wang6413aee2020-10-07 03:04:58 -070064 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070065 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080066 @NonNull List<String> schemasNotPlatformSurfaceable,
Alexander Dorokhine969f4462020-03-05 15:54:19 -080067 boolean forceOverride,
Terry Wangf2093072020-11-30 04:47:19 -080068 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -080069 @NonNull IAppSearchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -070070 Preconditions.checkNotNull(databaseName);
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070071 Preconditions.checkNotNull(schemaBundles);
Terry Wangbfbfcac2020-11-06 15:46:44 -080072 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -080073 int callingUid = Binder.getCallingUid();
74 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -060075 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080076 try {
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080077 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070078 for (int i = 0; i < schemaBundles.size(); i++) {
Terry Wang26b9e5c2020-10-23 02:05:01 -070079 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070080 }
Terry Wang0d393872020-12-11 22:17:09 +000081 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -080082 String packageName = convertUidToPackageName(callingUid);
83 impl.setSchema(packageName, databaseName, schemas, schemasNotPlatformSurfaceable,
84 forceOverride);
Terry Wangdbd1dca2020-11-03 17:03:56 -080085 invokeCallbackOnResult(callback,
86 AppSearchResult.newSuccessfulResult(/*result=*/ null));
Alexander Dorokhine179c8b82020-01-11 00:17:48 -080087 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -080088 invokeCallbackOnError(callback, t);
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080089 } finally {
90 Binder.restoreCallingIdentity(callingIdentity);
Alexander Dorokhine179c8b82020-01-11 00:17:48 -080091 }
92 }
93
94 @Override
Terry Wang83a24932020-12-09 21:00:18 -080095 public void getSchema(
96 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -080097 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -080098 @NonNull IAppSearchResultCallback callback) {
99 Preconditions.checkNotNull(databaseName);
100 Preconditions.checkNotNull(callback);
101 int callingUid = Binder.getCallingUidOrThrow();
Terry Wangf2093072020-11-30 04:47:19 -0800102 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wang83a24932020-12-09 21:00:18 -0800103 final long callingIdentity = Binder.clearCallingIdentity();
104 try {
105 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800106 String packageName = convertUidToPackageName(callingUid);
107 List<AppSearchSchema> schemas = impl.getSchema(packageName, databaseName);
Terry Wang83a24932020-12-09 21:00:18 -0800108 List<Bundle> schemaBundles = new ArrayList<>(schemas.size());
109 for (int i = 0; i < schemas.size(); i++) {
110 schemaBundles.add(schemas.get(i).getBundle());
111 }
112 invokeCallbackOnResult(callback,
113 AppSearchResult.newSuccessfulResult(schemaBundles));
114 } catch (Throwable t) {
115 invokeCallbackOnError(callback, t);
116 } finally {
117 Binder.restoreCallingIdentity(callingIdentity);
118 }
119 }
120
121 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800122 public void putDocuments(
Terry Wang6413aee2020-10-07 03:04:58 -0700123 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700124 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800125 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800126 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700127 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700128 Preconditions.checkNotNull(documentBundles);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800129 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800130 int callingUid = Binder.getCallingUid();
131 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600132 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800133 try {
Alexander Dorokhine18465842020-01-21 01:08:57 -0800134 AppSearchBatchResult.Builder<String, Void> resultBuilder =
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800135 new AppSearchBatchResult.Builder<>();
Terry Wang0d393872020-12-11 22:17:09 +0000136 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800137 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700138 for (int i = 0; i < documentBundles.size(); i++) {
139 GenericDocument document = new GenericDocument(documentBundles.get(i));
Alexander Dorokhine18465842020-01-21 01:08:57 -0800140 try {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800141 // TODO(b/173451571): reduce burden of binder thread by enqueue request onto
142 // a separate thread.
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800143 impl.putDocument(packageName, databaseName, document);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700144 resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
Alexander Dorokhine18465842020-01-21 01:08:57 -0800145 } catch (Throwable t) {
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800146 resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
Alexander Dorokhine18465842020-01-21 01:08:57 -0800147 }
148 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800149 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800150 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800151 invokeCallbackOnError(callback, t);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800152 } finally {
153 Binder.restoreCallingIdentity(callingIdentity);
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800154 }
155 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800156
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800157 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800158 public void getDocuments(
159 @NonNull String databaseName,
160 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800161 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800162 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800163 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700164 Preconditions.checkNotNull(databaseName);
165 Preconditions.checkNotNull(namespace);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800166 Preconditions.checkNotNull(uris);
167 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800168 int callingUid = Binder.getCallingUid();
169 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600170 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800171 try {
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700172 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800173 new AppSearchBatchResult.Builder<>();
Terry Wang0d393872020-12-11 22:17:09 +0000174 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800175 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800176 for (int i = 0; i < uris.size(); i++) {
177 String uri = uris.get(i);
178 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800179 GenericDocument document = impl.getDocument(packageName, databaseName,
180 namespace, uri);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700181 resultBuilder.setSuccess(uri, document.getBundle());
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800182 } catch (Throwable t) {
183 resultBuilder.setResult(uri, throwableToFailedResult(t));
184 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800185 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800186 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800187 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800188 invokeCallbackOnError(callback, t);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800189 } finally {
190 Binder.restoreCallingIdentity(callingIdentity);
191 }
192 }
193
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800194 // TODO(sidchhabra): Do this in a threadpool.
195 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800196 public void query(
Terry Wang6413aee2020-10-07 03:04:58 -0700197 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700198 @NonNull String queryExpression,
199 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800200 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700201 @NonNull IAppSearchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700202 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700203 Preconditions.checkNotNull(queryExpression);
204 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800205 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800206 int callingUid = Binder.getCallingUid();
207 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600208 final long callingIdentity = Binder.clearCallingIdentity();
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800209 try {
Terry Wang0d393872020-12-11 22:17:09 +0000210 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800211 String packageName = convertUidToPackageName(callingUid);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700212 SearchResultPage searchResultPage = impl.query(
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800213 packageName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700214 databaseName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700215 queryExpression,
216 new SearchSpec(searchSpecBundle));
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700217 invokeCallbackOnResult(callback,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700218 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800219 } catch (Throwable t) {
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700220 invokeCallbackOnError(callback, t);
221 } finally {
222 Binder.restoreCallingIdentity(callingIdentity);
223 }
224 }
225
Terry Wangf2093072020-11-30 04:47:19 -0800226 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800227 public void globalQuery(
228 @NonNull String queryExpression,
229 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800230 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800231 @NonNull IAppSearchResultCallback callback) {
232 Preconditions.checkNotNull(queryExpression);
233 Preconditions.checkNotNull(searchSpecBundle);
234 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800235 int callingUid = Binder.getCallingUid();
236 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800237 final long callingIdentity = Binder.clearCallingIdentity();
238 try {
Terry Wang0d393872020-12-11 22:17:09 +0000239 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800240 SearchResultPage searchResultPage = impl.globalQuery(
241 queryExpression,
242 new SearchSpec(searchSpecBundle));
243 invokeCallbackOnResult(callback,
244 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
245 } catch (Throwable t) {
246 invokeCallbackOnError(callback, t);
247 } finally {
248 Binder.restoreCallingIdentity(callingIdentity);
249 }
250 }
251
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700252 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800253 public void getNextPage(long nextPageToken, @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700254 @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800255 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800256 int callingUid = Binder.getCallingUid();
257 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700258 final long callingIdentity = Binder.clearCallingIdentity();
259 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
260 // opened it
261 try {
Terry Wang0d393872020-12-11 22:17:09 +0000262 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700263 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
264 invokeCallbackOnResult(callback,
265 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
266 } catch (Throwable t) {
267 invokeCallbackOnError(callback, t);
268 } finally {
269 Binder.restoreCallingIdentity(callingIdentity);
270 }
271 }
272
273 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800274 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
275 int callingUid = Binder.getCallingUid();
276 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700277 final long callingIdentity = Binder.clearCallingIdentity();
278 try {
Terry Wang0d393872020-12-11 22:17:09 +0000279 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700280 impl.invalidateNextPageToken(nextPageToken);
281 } catch (Throwable t) {
Terry Wang2da17852020-12-16 19:59:08 -0800282 Log.e(TAG, "Unable to invalidate the query page token", t);
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800283 } finally {
284 Binder.restoreCallingIdentity(callingIdentity);
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800285 }
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800286 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800287
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700288 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800289 public void removeByUri(
290 @NonNull String databaseName,
291 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800292 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800293 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800294 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700295 Preconditions.checkNotNull(databaseName);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700296 Preconditions.checkNotNull(uris);
297 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800298 int callingUid = Binder.getCallingUid();
299 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600300 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700301 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800302 AppSearchBatchResult.Builder<String, Void> resultBuilder =
303 new AppSearchBatchResult.Builder<>();
Terry Wang0d393872020-12-11 22:17:09 +0000304 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800305 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700306 for (int i = 0; i < uris.size(); i++) {
307 String uri = uris.get(i);
308 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800309 impl.remove(packageName, databaseName, namespace, uri);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700310 resultBuilder.setSuccess(uri, /*result= */null);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700311 } catch (Throwable t) {
312 resultBuilder.setResult(uri, throwableToFailedResult(t));
313 }
314 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800315 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700316 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800317 invokeCallbackOnError(callback, t);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700318 } finally {
319 Binder.restoreCallingIdentity(callingIdentity);
320 }
321 }
322
323 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700324 public void removeByQuery(
325 @NonNull String databaseName,
326 @NonNull String queryExpression,
327 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800328 @UserIdInt int userId,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700329 @NonNull IAppSearchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700330 Preconditions.checkNotNull(databaseName);
331 Preconditions.checkNotNull(queryExpression);
332 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800333 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800334 int callingUid = Binder.getCallingUid();
335 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600336 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700337 try {
Terry Wang0d393872020-12-11 22:17:09 +0000338 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800339 String packageName = convertUidToPackageName(callingUid);
340 impl.removeByQuery(packageName, databaseName, queryExpression,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700341 new SearchSpec(searchSpecBundle));
342 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700343 } catch (Throwable t) {
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700344 invokeCallbackOnError(callback, t);
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700345 } finally {
346 Binder.restoreCallingIdentity(callingIdentity);
347 }
348 }
349
Terry Wangdbd1dca2020-11-03 17:03:56 -0800350 @Override
Terry Wang2da17852020-12-16 19:59:08 -0800351 public void persistToDisk(@UserIdInt int userId) {
352 int callingUid = Binder.getCallingUidOrThrow();
353 int callingUserId = handleIncomingUser(userId, callingUid);
354 final long callingIdentity = Binder.clearCallingIdentity();
355 try {
356 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
357 impl.persistToDisk();
358 } catch (Throwable t) {
359 Log.e(TAG, "Unable to persist the data to disk", t);
360 } finally {
361 Binder.restoreCallingIdentity(callingIdentity);
362 }
363 }
364
365 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800366 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800367 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800368 int callingUid = Binder.getCallingUid();
369 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800370 final long callingIdentity = Binder.clearCallingIdentity();
371 try {
Terry Wang0d393872020-12-11 22:17:09 +0000372 ImplInstanceManager.getInstance(getContext(), callingUserId);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800373 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
374 } catch (Throwable t) {
375 invokeCallbackOnError(callback, t);
376 } finally {
377 Binder.restoreCallingIdentity(callingIdentity);
378 }
379 }
380
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700381 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800382 * Returns a package name for the given uid.
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700383 *
384 * <p>The current implementation returns the package name of the app with this uid in a
385 * format like {@code com.example.package} or {@code com.example.sharedname:5678}.
386 */
387 @NonNull
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800388 private String convertUidToPackageName(int callingUid) {
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700389 // For regular apps, this call will return the package name. If callingUid is an
390 // android:sharedUserId, this value may be another type of name and have a :uid suffix.
391 String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
392 if (callingUidName == null) {
393 // Not sure how this is possible --- maybe app was uninstalled?
394 throw new IllegalStateException(
395 "Failed to look up package name for uid " + callingUid);
396 }
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800397 return callingUidName;
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700398 }
399
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800400 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Terry Wangdbd1dca2020-11-03 17:03:56 -0800401 private void invokeCallbackOnResult(IAppSearchResultCallback callback,
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800402 AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800403 try {
404 callback.onResult(result);
405 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800406 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800407 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800408 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800409
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800410 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Terry Wangdbd1dca2020-11-03 17:03:56 -0800411 private void invokeCallbackOnResult(IAppSearchBatchResultCallback callback,
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800412 AppSearchBatchResult<?, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800413 try {
414 callback.onResult(result);
415 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800416 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800417 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800418 }
419
420 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800421 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800422 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800423 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -0800424 */
425 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
426 try {
427 callback.onResult(throwableToFailedResult(throwable));
428 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800429 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800430 }
431 }
432
433 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800434 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800435 *
436 * <p>The throwable is converted to {@link ParcelableException}.
437 */
438 private void invokeCallbackOnError(IAppSearchBatchResultCallback callback,
439 Throwable throwable) {
440 try {
441 callback.onSystemError(new ParcelableException(throwable));
442 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800443 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800444 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800445 }
Terry Wangfebbead2019-10-17 17:05:18 -0700446 }
Terry Wangf2093072020-11-30 04:47:19 -0800447
448 //TODO(b/173553485) verifying that the caller has permission to access target user's data
449 //TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
450 //TODO(b/173553485) Implement SystemService.onUserStopping()
451 private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
452 int callingPid = Binder.getCallingPid();
453 return ActivityManager.handleIncomingUser(callingPid, callingUid, userId,
454 /*allowAll=*/ false, /*requireFull=*/ false,
455 /*name=*/ null, /*callerPackage=*/ null);
456 }
Terry Wangfebbead2019-10-17 17:05:18 -0700457}