blob: 1f1e9a1a28a804ea4c0292521754ea480e11d289 [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;
Alexander Dorokhineab789062021-01-11 21:00:00 -080030import android.app.appsearch.PackageIdentifier;
Terry Wang26b9e5c2020-10-23 02:05:01 -070031import android.app.appsearch.SearchResultPage;
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -070032import android.app.appsearch.SearchSpec;
Terry Wangfebbead2019-10-17 17:05:18 -070033import android.content.Context;
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080034import android.os.Binder;
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070035import android.os.Bundle;
Terry Wangdbd1dca2020-11-03 17:03:56 -080036import android.os.ParcelableException;
37import android.os.RemoteException;
Alexander Dorokhineab789062021-01-11 21:00:00 -080038import android.util.ArrayMap;
Terry Wangdbd1dca2020-11-03 17:03:56 -080039import android.util.Log;
Terry Wangfebbead2019-10-17 17:05:18 -070040
Alexander Dorokhine270d4f12020-01-15 17:24:35 -080041import com.android.internal.util.Preconditions;
Terry Wangfebbead2019-10-17 17:05:18 -070042import com.android.server.SystemService;
Alexander Dorokhinef660d8f2020-10-29 22:37:00 -070043import com.android.server.appsearch.external.localstorage.AppSearchImpl;
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080044
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080045import java.util.ArrayList;
Alexander Dorokhine18465842020-01-21 01:08:57 -080046import java.util.List;
Alexander Dorokhineab789062021-01-11 21:00:00 -080047import java.util.Map;
Alexander Dorokhine18465842020-01-21 01:08:57 -080048
Terry Wangfebbead2019-10-17 17:05:18 -070049/**
50 * TODO(b/142567528): add comments when implement this class
51 */
52public class AppSearchManagerService extends SystemService {
Alexander Dorokhineebd37742020-09-22 15:02:26 -070053 private static final String TAG = "AppSearchManagerService";
Terry Wangfebbead2019-10-17 17:05:18 -070054
55 public AppSearchManagerService(Context context) {
56 super(context);
57 }
58
59 @Override
60 public void onStart() {
61 publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
62 }
63
64 private class Stub extends IAppSearchManager.Stub {
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080065 @Override
Alexander Dorokhine969f4462020-03-05 15:54:19 -080066 public void setSchema(
Terry Wang6413aee2020-10-07 03:04:58 -070067 @NonNull String databaseName,
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070068 @NonNull List<Bundle> schemaBundles,
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080069 @NonNull List<String> schemasNotPlatformSurfaceable,
Alexander Dorokhineab789062021-01-11 21:00:00 -080070 @NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
Alexander Dorokhine969f4462020-03-05 15:54:19 -080071 boolean forceOverride,
Terry Wangf2093072020-11-30 04:47:19 -080072 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -080073 @NonNull IAppSearchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -070074 Preconditions.checkNotNull(databaseName);
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070075 Preconditions.checkNotNull(schemaBundles);
Terry Wangbfbfcac2020-11-06 15:46:44 -080076 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -080077 int callingUid = Binder.getCallingUid();
78 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -060079 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -080080 try {
Alexander Dorokhine6a99f942020-12-04 02:57:22 -080081 List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070082 for (int i = 0; i < schemaBundles.size(); i++) {
Terry Wang26b9e5c2020-10-23 02:05:01 -070083 schemas.add(new AppSearchSchema(schemaBundles.get(i)));
Alexander Dorokhine92ce3532020-10-06 01:39:36 -070084 }
Alexander Dorokhineab789062021-01-11 21:00:00 -080085 Map<String, List<PackageIdentifier>> schemasPackageAccessible =
86 new ArrayMap<>(schemasPackageAccessibleBundles.size());
87 for (Map.Entry<String, List<Bundle>> entry :
88 schemasPackageAccessibleBundles.entrySet()) {
89 List<PackageIdentifier> packageIdentifiers =
90 new ArrayList<>(entry.getValue().size());
91 for (int i = 0; i < packageIdentifiers.size(); i++) {
92 packageIdentifiers.add(new PackageIdentifier(entry.getValue().get(i)));
93 }
94 schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
95 }
Terry Wang0d393872020-12-11 22:17:09 +000096 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -080097 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhineab789062021-01-11 21:00:00 -080098 impl.setSchema(
99 packageName,
100 databaseName,
101 schemas,
102 schemasNotPlatformSurfaceable,
103 schemasPackageAccessible,
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800104 forceOverride);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800105 invokeCallbackOnResult(callback,
106 AppSearchResult.newSuccessfulResult(/*result=*/ null));
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800107 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800108 invokeCallbackOnError(callback, t);
Alexander Dorokhine270d4f12020-01-15 17:24:35 -0800109 } finally {
110 Binder.restoreCallingIdentity(callingIdentity);
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800111 }
112 }
113
114 @Override
Terry Wang83a24932020-12-09 21:00:18 -0800115 public void getSchema(
116 @NonNull String databaseName,
Terry Wangf2093072020-11-30 04:47:19 -0800117 @UserIdInt int userId,
Terry Wang83a24932020-12-09 21:00:18 -0800118 @NonNull IAppSearchResultCallback callback) {
119 Preconditions.checkNotNull(databaseName);
120 Preconditions.checkNotNull(callback);
121 int callingUid = Binder.getCallingUidOrThrow();
Terry Wangf2093072020-11-30 04:47:19 -0800122 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wang83a24932020-12-09 21:00:18 -0800123 final long callingIdentity = Binder.clearCallingIdentity();
124 try {
125 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800126 String packageName = convertUidToPackageName(callingUid);
127 List<AppSearchSchema> schemas = impl.getSchema(packageName, databaseName);
Terry Wang83a24932020-12-09 21:00:18 -0800128 List<Bundle> schemaBundles = new ArrayList<>(schemas.size());
129 for (int i = 0; i < schemas.size(); i++) {
130 schemaBundles.add(schemas.get(i).getBundle());
131 }
132 invokeCallbackOnResult(callback,
133 AppSearchResult.newSuccessfulResult(schemaBundles));
134 } catch (Throwable t) {
135 invokeCallbackOnError(callback, t);
136 } finally {
137 Binder.restoreCallingIdentity(callingIdentity);
138 }
139 }
140
141 @Override
Alexander Dorokhine18465842020-01-21 01:08:57 -0800142 public void putDocuments(
Terry Wang6413aee2020-10-07 03:04:58 -0700143 @NonNull String databaseName,
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700144 @NonNull List<Bundle> documentBundles,
Terry Wangf2093072020-11-30 04:47:19 -0800145 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800146 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700147 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700148 Preconditions.checkNotNull(documentBundles);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800149 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800150 int callingUid = Binder.getCallingUid();
151 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600152 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhine179c8b82020-01-11 00:17:48 -0800153 try {
Alexander Dorokhine18465842020-01-21 01:08:57 -0800154 AppSearchBatchResult.Builder<String, Void> resultBuilder =
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800155 new AppSearchBatchResult.Builder<>();
Terry Wang0d393872020-12-11 22:17:09 +0000156 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800157 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700158 for (int i = 0; i < documentBundles.size(); i++) {
159 GenericDocument document = new GenericDocument(documentBundles.get(i));
Alexander Dorokhine18465842020-01-21 01:08:57 -0800160 try {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800161 // TODO(b/173451571): reduce burden of binder thread by enqueue request onto
162 // a separate thread.
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800163 impl.putDocument(packageName, databaseName, document);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700164 resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
Alexander Dorokhine18465842020-01-21 01:08:57 -0800165 } catch (Throwable t) {
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800166 resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
Alexander Dorokhine18465842020-01-21 01:08:57 -0800167 }
168 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800169 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800170 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800171 invokeCallbackOnError(callback, t);
Alexander Dorokhinecc223452020-01-19 03:00:28 -0800172 } finally {
173 Binder.restoreCallingIdentity(callingIdentity);
Alexander Dorokhinefd07eba2020-01-13 20:22:20 -0800174 }
175 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800176
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800177 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800178 public void getDocuments(
179 @NonNull String databaseName,
180 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800181 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800182 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800183 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700184 Preconditions.checkNotNull(databaseName);
185 Preconditions.checkNotNull(namespace);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800186 Preconditions.checkNotNull(uris);
187 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800188 int callingUid = Binder.getCallingUid();
189 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600190 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800191 try {
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700192 AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800193 new AppSearchBatchResult.Builder<>();
Terry Wang0d393872020-12-11 22:17:09 +0000194 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800195 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800196 for (int i = 0; i < uris.size(); i++) {
197 String uri = uris.get(i);
198 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800199 GenericDocument document = impl.getDocument(packageName, databaseName,
200 namespace, uri);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700201 resultBuilder.setSuccess(uri, document.getBundle());
Alexander Dorokhinea95f44f2020-03-06 13:53:14 -0800202 } catch (Throwable t) {
203 resultBuilder.setResult(uri, throwableToFailedResult(t));
204 }
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800205 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800206 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800207 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800208 invokeCallbackOnError(callback, t);
Alexander Dorokhine69a8d9f2020-03-06 10:43:16 -0800209 } finally {
210 Binder.restoreCallingIdentity(callingIdentity);
211 }
212 }
213
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800214 // TODO(sidchhabra): Do this in a threadpool.
215 @Override
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800216 public void query(
Terry Wang6413aee2020-10-07 03:04:58 -0700217 @NonNull String databaseName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700218 @NonNull String queryExpression,
219 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800220 @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700221 @NonNull IAppSearchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700222 Preconditions.checkNotNull(databaseName);
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700223 Preconditions.checkNotNull(queryExpression);
224 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800225 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800226 int callingUid = Binder.getCallingUid();
227 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600228 final long callingIdentity = Binder.clearCallingIdentity();
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800229 try {
Terry Wang0d393872020-12-11 22:17:09 +0000230 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800231 String packageName = convertUidToPackageName(callingUid);
Terry Wang26b9e5c2020-10-23 02:05:01 -0700232 SearchResultPage searchResultPage = impl.query(
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800233 packageName,
Alexander Dorokhinec9fc9602020-10-06 01:39:50 -0700234 databaseName,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700235 queryExpression,
236 new SearchSpec(searchSpecBundle));
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700237 invokeCallbackOnResult(callback,
Terry Wang26b9e5c2020-10-23 02:05:01 -0700238 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800239 } catch (Throwable t) {
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700240 invokeCallbackOnError(callback, t);
241 } finally {
242 Binder.restoreCallingIdentity(callingIdentity);
243 }
244 }
245
Terry Wangf2093072020-11-30 04:47:19 -0800246 @Override
Terry Wangbfbfcac2020-11-06 15:46:44 -0800247 public void globalQuery(
248 @NonNull String queryExpression,
249 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800250 @UserIdInt int userId,
Terry Wangbfbfcac2020-11-06 15:46:44 -0800251 @NonNull IAppSearchResultCallback callback) {
252 Preconditions.checkNotNull(queryExpression);
253 Preconditions.checkNotNull(searchSpecBundle);
254 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800255 int callingUid = Binder.getCallingUid();
256 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800257 final long callingIdentity = Binder.clearCallingIdentity();
258 try {
Terry Wang0d393872020-12-11 22:17:09 +0000259 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800260 SearchResultPage searchResultPage = impl.globalQuery(
261 queryExpression,
262 new SearchSpec(searchSpecBundle));
263 invokeCallbackOnResult(callback,
264 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
265 } catch (Throwable t) {
266 invokeCallbackOnError(callback, t);
267 } finally {
268 Binder.restoreCallingIdentity(callingIdentity);
269 }
270 }
271
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700272 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800273 public void getNextPage(long nextPageToken, @UserIdInt int userId,
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700274 @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800275 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800276 int callingUid = Binder.getCallingUid();
277 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700278 final long callingIdentity = Binder.clearCallingIdentity();
279 // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
280 // opened it
281 try {
Terry Wang0d393872020-12-11 22:17:09 +0000282 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700283 SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
284 invokeCallbackOnResult(callback,
285 AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
286 } catch (Throwable t) {
287 invokeCallbackOnError(callback, t);
288 } finally {
289 Binder.restoreCallingIdentity(callingIdentity);
290 }
291 }
292
293 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800294 public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
295 int callingUid = Binder.getCallingUid();
296 int callingUserId = handleIncomingUser(userId, callingUid);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700297 final long callingIdentity = Binder.clearCallingIdentity();
298 try {
Terry Wang0d393872020-12-11 22:17:09 +0000299 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhined48f2362020-10-20 17:40:49 -0700300 impl.invalidateNextPageToken(nextPageToken);
301 } catch (Throwable t) {
Terry Wang2da17852020-12-16 19:59:08 -0800302 Log.e(TAG, "Unable to invalidate the query page token", t);
Alexander Dorokhinee708e182020-03-06 15:30:34 -0800303 } finally {
304 Binder.restoreCallingIdentity(callingIdentity);
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800305 }
sidchhabraa7c8f8a2020-01-16 18:38:17 -0800306 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800307
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700308 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800309 public void removeByUri(
310 @NonNull String databaseName,
311 @NonNull String namespace,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800312 @NonNull List<String> uris,
Terry Wangf2093072020-11-30 04:47:19 -0800313 @UserIdInt int userId,
Terry Wangdbd1dca2020-11-03 17:03:56 -0800314 @NonNull IAppSearchBatchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700315 Preconditions.checkNotNull(databaseName);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700316 Preconditions.checkNotNull(uris);
317 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800318 int callingUid = Binder.getCallingUid();
319 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600320 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700321 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800322 AppSearchBatchResult.Builder<String, Void> resultBuilder =
323 new AppSearchBatchResult.Builder<>();
Terry Wang0d393872020-12-11 22:17:09 +0000324 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800325 String packageName = convertUidToPackageName(callingUid);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700326 for (int i = 0; i < uris.size(); i++) {
327 String uri = uris.get(i);
328 try {
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800329 impl.remove(packageName, databaseName, namespace, uri);
Alexander Dorokhinec66d67c2020-10-08 13:44:04 -0700330 resultBuilder.setSuccess(uri, /*result= */null);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700331 } catch (Throwable t) {
332 resultBuilder.setResult(uri, throwableToFailedResult(t));
333 }
334 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800335 invokeCallbackOnResult(callback, resultBuilder.build());
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700336 } catch (Throwable t) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800337 invokeCallbackOnError(callback, t);
Alexander Dorokhineff82fba2020-03-09 16:35:24 -0700338 } finally {
339 Binder.restoreCallingIdentity(callingIdentity);
340 }
341 }
342
343 @Override
Terry Wang26b9e5c2020-10-23 02:05:01 -0700344 public void removeByQuery(
345 @NonNull String databaseName,
346 @NonNull String queryExpression,
347 @NonNull Bundle searchSpecBundle,
Terry Wangf2093072020-11-30 04:47:19 -0800348 @UserIdInt int userId,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700349 @NonNull IAppSearchResultCallback callback) {
Terry Wang26b9e5c2020-10-23 02:05:01 -0700350 Preconditions.checkNotNull(databaseName);
351 Preconditions.checkNotNull(queryExpression);
352 Preconditions.checkNotNull(searchSpecBundle);
Terry Wangbfbfcac2020-11-06 15:46:44 -0800353 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800354 int callingUid = Binder.getCallingUid();
355 int callingUserId = handleIncomingUser(userId, callingUid);
Jeff Sharkeyea5328c2020-10-06 11:18:09 -0600356 final long callingIdentity = Binder.clearCallingIdentity();
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700357 try {
Terry Wang0d393872020-12-11 22:17:09 +0000358 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800359 String packageName = convertUidToPackageName(callingUid);
360 impl.removeByQuery(packageName, databaseName, queryExpression,
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700361 new SearchSpec(searchSpecBundle));
362 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700363 } catch (Throwable t) {
Alexander Dorokhine178366b2020-10-20 17:40:49 -0700364 invokeCallbackOnError(callback, t);
Alexander Dorokhinef6c66ae2020-03-09 14:47:25 -0700365 } finally {
366 Binder.restoreCallingIdentity(callingIdentity);
367 }
368 }
369
Terry Wangdbd1dca2020-11-03 17:03:56 -0800370 @Override
Terry Wang2da17852020-12-16 19:59:08 -0800371 public void persistToDisk(@UserIdInt int userId) {
372 int callingUid = Binder.getCallingUidOrThrow();
373 int callingUserId = handleIncomingUser(userId, callingUid);
374 final long callingIdentity = Binder.clearCallingIdentity();
375 try {
376 AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
377 impl.persistToDisk();
378 } catch (Throwable t) {
379 Log.e(TAG, "Unable to persist the data to disk", t);
380 } finally {
381 Binder.restoreCallingIdentity(callingIdentity);
382 }
383 }
384
385 @Override
Terry Wangf2093072020-11-30 04:47:19 -0800386 public void initialize(@UserIdInt int userId, @NonNull IAppSearchResultCallback callback) {
Terry Wangbfbfcac2020-11-06 15:46:44 -0800387 Preconditions.checkNotNull(callback);
Terry Wangf2093072020-11-30 04:47:19 -0800388 int callingUid = Binder.getCallingUid();
389 int callingUserId = handleIncomingUser(userId, callingUid);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800390 final long callingIdentity = Binder.clearCallingIdentity();
391 try {
Terry Wang0d393872020-12-11 22:17:09 +0000392 ImplInstanceManager.getInstance(getContext(), callingUserId);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800393 invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
394 } catch (Throwable t) {
395 invokeCallbackOnError(callback, t);
396 } finally {
397 Binder.restoreCallingIdentity(callingIdentity);
398 }
399 }
400
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700401 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800402 * Returns a package name for the given uid.
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700403 *
404 * <p>The current implementation returns the package name of the app with this uid in a
405 * format like {@code com.example.package} or {@code com.example.sharedname:5678}.
406 */
407 @NonNull
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800408 private String convertUidToPackageName(int callingUid) {
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700409 // For regular apps, this call will return the package name. If callingUid is an
410 // android:sharedUserId, this value may be another type of name and have a :uid suffix.
411 String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
412 if (callingUidName == null) {
413 // Not sure how this is possible --- maybe app was uninstalled?
414 throw new IllegalStateException(
415 "Failed to look up package name for uid " + callingUid);
416 }
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800417 return callingUidName;
Alexander Dorokhineebd37742020-09-22 15:02:26 -0700418 }
419
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800420 /** Invokes the {@link IAppSearchResultCallback} with the result. */
Terry Wangdbd1dca2020-11-03 17:03:56 -0800421 private void invokeCallbackOnResult(IAppSearchResultCallback callback,
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800422 AppSearchResult<?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800423 try {
424 callback.onResult(result);
425 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800426 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800427 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800428 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800429
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800430 /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
Terry Wangdbd1dca2020-11-03 17:03:56 -0800431 private void invokeCallbackOnResult(IAppSearchBatchResultCallback callback,
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800432 AppSearchBatchResult<?, ?> result) {
Terry Wangdbd1dca2020-11-03 17:03:56 -0800433 try {
434 callback.onResult(result);
435 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800436 Log.e(TAG, "Unable to send result to the callback", e);
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800437 }
Terry Wangdbd1dca2020-11-03 17:03:56 -0800438 }
439
440 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800441 * Invokes the {@link IAppSearchResultCallback} with an throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800442 *
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800443 * <p>The throwable is convert to a {@link AppSearchResult};
Terry Wangdbd1dca2020-11-03 17:03:56 -0800444 */
445 private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
446 try {
447 callback.onResult(throwableToFailedResult(throwable));
448 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800449 Log.e(TAG, "Unable to send result to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800450 }
451 }
452
453 /**
Alexander Dorokhine8c5ba912020-12-14 22:58:12 -0800454 * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
Terry Wangdbd1dca2020-11-03 17:03:56 -0800455 *
456 * <p>The throwable is converted to {@link ParcelableException}.
457 */
458 private void invokeCallbackOnError(IAppSearchBatchResultCallback callback,
459 Throwable throwable) {
460 try {
461 callback.onSystemError(new ParcelableException(throwable));
462 } catch (RemoteException e) {
Terry Wang2da17852020-12-16 19:59:08 -0800463 Log.e(TAG, "Unable to send error to the callback", e);
Terry Wangdbd1dca2020-11-03 17:03:56 -0800464 }
Alexander Dorokhine969f4462020-03-05 15:54:19 -0800465 }
Terry Wangfebbead2019-10-17 17:05:18 -0700466 }
Terry Wangf2093072020-11-30 04:47:19 -0800467
468 //TODO(b/173553485) verifying that the caller has permission to access target user's data
469 //TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
470 //TODO(b/173553485) Implement SystemService.onUserStopping()
471 private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
472 int callingPid = Binder.getCallingPid();
473 return ActivityManager.handleIncomingUser(callingPid, callingUid, userId,
474 /*allowAll=*/ false, /*requireFull=*/ false,
475 /*name=*/ null, /*callerPackage=*/ null);
476 }
Terry Wangfebbead2019-10-17 17:05:18 -0700477}