blob: 0cd030e0f6998f084e599bb83c735345f19ca049 [file] [log] [blame]
Todd Kennedy1fb34042017-03-01 13:56:58 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
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 */
16
17package android.app;
18
Todd Kennedy63ff4642019-03-25 11:20:01 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
Todd Kennedy1fb34042017-03-01 13:56:58 -080021import android.annotation.SystemApi;
Todd Kennedy1fb34042017-03-01 13:56:58 -080022import android.content.Context;
23import android.content.Intent;
Winson81fef842019-08-28 12:19:08 -070024import android.content.pm.InstantAppRequestInfo;
Todd Kennedy1fb34042017-03-01 13:56:58 -080025import android.content.pm.InstantAppResolveInfo;
Todd Kennedy02a6b732017-04-05 14:24:58 -070026import android.os.Build;
Todd Kennedy1fb34042017-03-01 13:56:58 -080027import android.os.Bundle;
28import android.os.Handler;
29import android.os.IBinder;
30import android.os.IRemoteCallback;
31import android.os.Looper;
32import android.os.Message;
33import android.os.RemoteException;
Hai Zhangbfa4f902018-08-21 11:33:33 -070034import android.os.UserHandle;
Todd Kennedy02a6b732017-04-05 14:24:58 -070035import android.util.Log;
36import android.util.Slog;
Todd Kennedy1fb34042017-03-01 13:56:58 -080037
Winson191069d2019-12-20 15:35:29 -080038import com.android.internal.annotations.VisibleForTesting;
Todd Kennedyd3c51062017-03-17 16:03:29 -070039import com.android.internal.os.SomeArgs;
40
Todd Kennedy02a6b732017-04-05 14:24:58 -070041import java.util.Arrays;
Patrick Baumann577d4022018-01-31 16:55:10 +000042import java.util.Collections;
Todd Kennedy1fb34042017-03-01 13:56:58 -080043import java.util.List;
44
45/**
46 * Base class for implementing the resolver service.
47 * @hide
48 */
49@SystemApi
50public abstract class InstantAppResolverService extends Service {
Patrick Baumann43c97a02018-01-31 20:09:03 +000051 private static final boolean DEBUG_INSTANT = Build.IS_DEBUGGABLE;
Todd Kennedy02a6b732017-04-05 14:24:58 -070052 private static final String TAG = "PackageManager";
53
Todd Kennedyd3c51062017-03-17 16:03:29 -070054 /** @hide */
Todd Kennedy1fb34042017-03-01 13:56:58 -080055 public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
Todd Kennedyd3c51062017-03-17 16:03:29 -070056 /** @hide */
Todd Kennedy1fb34042017-03-01 13:56:58 -080057 public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
Todd Kennedy1fb34042017-03-01 13:56:58 -080058 Handler mHandler;
59
60 /**
Patrick Baumann577d4022018-01-31 16:55:10 +000061 * Called to retrieve resolve info for instant applications immediately.
Todd Kennedy1fb34042017-03-01 13:56:58 -080062 *
63 * @param digestPrefix The hash prefix of the instant app's domain.
Winson81fef842019-08-28 12:19:08 -070064 *
65 * @deprecated Should implement {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo,
66 * InstantAppResolutionCallback)}
Todd Kennedy1fb34042017-03-01 13:56:58 -080067 */
Patrick Baumann577d4022018-01-31 16:55:10 +000068 @Deprecated
Todd Kennedy63ff4642019-03-25 11:20:01 -070069 public void onGetInstantAppResolveInfo(@Nullable int[] digestPrefix, @NonNull String token,
70 @NonNull InstantAppResolutionCallback callback) {
Patrick Baumann3abf5472018-03-01 09:58:23 -080071 throw new IllegalStateException("Must define onGetInstantAppResolveInfo");
Todd Kennedy1fb34042017-03-01 13:56:58 -080072 }
73
74 /**
Patrick Baumann577d4022018-01-31 16:55:10 +000075 * Called to retrieve intent filters for instant applications from potentially expensive
76 * sources.
Todd Kennedy1fb34042017-03-01 13:56:58 -080077 *
78 * @param digestPrefix The hash prefix of the instant app's domain.
Winson81fef842019-08-28 12:19:08 -070079 *
80 * @deprecated Should implement {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
81 * InstantAppResolutionCallback)}
Todd Kennedy1fb34042017-03-01 13:56:58 -080082 */
Patrick Baumann577d4022018-01-31 16:55:10 +000083 @Deprecated
Todd Kennedy63ff4642019-03-25 11:20:01 -070084 public void onGetInstantAppIntentFilter(@Nullable int[] digestPrefix, @NonNull String token,
85 @NonNull InstantAppResolutionCallback callback) {
Patrick Baumann577d4022018-01-31 16:55:10 +000086 throw new IllegalStateException("Must define onGetInstantAppIntentFilter");
87 }
88
89 /**
Patrick Baumann3abf5472018-03-01 09:58:23 -080090 * Called to retrieve resolve info for instant applications immediately. The response will be
91 * ignored if not provided within a reasonable time. {@link InstantAppResolveInfo}s provided
92 * in response to this method may be partial to request a second phase of resolution which will
93 * result in a subsequent call to
94 * {@link #onGetInstantAppIntentFilter(Intent, int[], String, InstantAppResolutionCallback)}
Patrick Baumann577d4022018-01-31 16:55:10 +000095 *
Patrick Baumann3abf5472018-03-01 09:58:23 -080096 * @param sanitizedIntent The sanitized {@link Intent} used for resolution. A sanitized Intent
97 * is an intent with potential PII removed from the original intent.
98 * Fields removed include extras and the host + path of the data, if
99 * defined.
Patrick Baumann577d4022018-01-31 16:55:10 +0000100 * @param hostDigestPrefix The hash prefix of the instant app's domain.
Patrick Baumann3abf5472018-03-01 09:58:23 -0800101 * @param token A unique identifier that will be provided in calls to
102 * {@link #onGetInstantAppIntentFilter(Intent, int[], String,
103 * InstantAppResolutionCallback)}
104 * and provided to the installer via {@link Intent#EXTRA_INSTANT_APP_TOKEN} to
105 * tie a single launch together.
106 * @param callback The {@link InstantAppResolutionCallback} to provide results to.
107 *
108 * @see InstantAppResolveInfo
Hai Zhangbfa4f902018-08-21 11:33:33 -0700109 *
Winson81fef842019-08-28 12:19:08 -0700110 * @deprecated Should implement {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo,
111 * InstantAppResolutionCallback)}
Patrick Baumann577d4022018-01-31 16:55:10 +0000112 */
Hai Zhangbfa4f902018-08-21 11:33:33 -0700113 @Deprecated
Todd Kennedy63ff4642019-03-25 11:20:01 -0700114 public void onGetInstantAppResolveInfo(@NonNull Intent sanitizedIntent,
115 @Nullable int[] hostDigestPrefix, @NonNull String token,
116 @NonNull InstantAppResolutionCallback callback) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000117 // if not overridden, forward to old methods and filter out non-web intents
Patrick Baumann0da85372018-02-02 16:07:35 -0800118 if (sanitizedIntent.isWebIntent()) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000119 onGetInstantAppResolveInfo(hostDigestPrefix, token, callback);
120 } else {
121 callback.onInstantAppResolveInfo(Collections.emptyList());
122 }
123 }
124
125 /**
Patrick Baumann3abf5472018-03-01 09:58:23 -0800126 * Called to retrieve intent filters for potentially matching instant applications. Unlike
127 * {@link #onGetInstantAppResolveInfo(Intent, int[], String, InstantAppResolutionCallback)},
128 * the response may take as long as necessary to respond. All {@link InstantAppResolveInfo}s
129 * provided in response to this method must be completely populated.
Patrick Baumann577d4022018-01-31 16:55:10 +0000130 *
131 * @param sanitizedIntent The sanitized {@link Intent} used for resolution.
132 * @param hostDigestPrefix The hash prefix of the instant app's domain or null if no host is
133 * defined.
Patrick Baumann3abf5472018-03-01 09:58:23 -0800134 * @param token A unique identifier that was provided in
135 * {@link #onGetInstantAppResolveInfo(Intent, int[], String,
136 * InstantAppResolutionCallback)}
137 * and provided to the currently visible installer via
138 * {@link Intent#EXTRA_INSTANT_APP_TOKEN}.
Hai Zhangbfa4f902018-08-21 11:33:33 -0700139 * @param callback The {@link InstantAppResolutionCallback} to provide results to.
140 *
Winson81fef842019-08-28 12:19:08 -0700141 * @deprecated Should implement {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
142 * InstantAppResolutionCallback)}
Patrick Baumann577d4022018-01-31 16:55:10 +0000143 */
Hai Zhangbfa4f902018-08-21 11:33:33 -0700144 @Deprecated
Todd Kennedy63ff4642019-03-25 11:20:01 -0700145 public void onGetInstantAppIntentFilter(@NonNull Intent sanitizedIntent,
146 @Nullable int[] hostDigestPrefix,
147 @NonNull String token, @NonNull InstantAppResolutionCallback callback) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000148 Log.e(TAG, "New onGetInstantAppIntentFilter is not overridden");
149 // if not overridden, forward to old methods and filter out non-web intents
Patrick Baumann0da85372018-02-02 16:07:35 -0800150 if (sanitizedIntent.isWebIntent()) {
Patrick Baumann577d4022018-01-31 16:55:10 +0000151 onGetInstantAppIntentFilter(hostDigestPrefix, token, callback);
152 } else {
153 callback.onInstantAppResolveInfo(Collections.emptyList());
154 }
Todd Kennedy1fb34042017-03-01 13:56:58 -0800155 }
156
157 /**
Hai Zhangbfa4f902018-08-21 11:33:33 -0700158 * Called to retrieve resolve info for instant applications immediately. The response will be
159 * ignored if not provided within a reasonable time. {@link InstantAppResolveInfo}s provided
160 * in response to this method may be partial to request a second phase of resolution which will
161 * result in a subsequent call to {@link #onGetInstantAppIntentFilter(Intent, int[], UserHandle,
162 * String, InstantAppResolutionCallback)}
163 *
164 * @param sanitizedIntent The sanitized {@link Intent} used for resolution. A sanitized Intent
165 * is an intent with potential PII removed from the original intent.
166 * Fields removed include extras and the host + path of the data, if
167 * defined.
168 * @param hostDigestPrefix The hash prefix of the instant app's domain.
169 * @param userHandle The user for which to resolve the instant app.
170 * @param token A unique identifier that will be provided in calls to {@link
171 * #onGetInstantAppIntentFilter(Intent, int[], UserHandle, String,
172 * InstantAppResolutionCallback)} and provided to the installer via {@link
173 * Intent#EXTRA_INSTANT_APP_TOKEN} to tie a single launch together.
174 * @param callback The {@link InstantAppResolutionCallback} to provide results to.
175 *
176 * @see InstantAppResolveInfo
Winson81fef842019-08-28 12:19:08 -0700177 *
178 * @deprecated Should implement {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo,
179 * InstantAppResolutionCallback
Hai Zhangbfa4f902018-08-21 11:33:33 -0700180 */
Winson81fef842019-08-28 12:19:08 -0700181 @Deprecated
Todd Kennedy63ff4642019-03-25 11:20:01 -0700182 public void onGetInstantAppResolveInfo(@NonNull Intent sanitizedIntent,
183 @Nullable int[] hostDigestPrefix, @NonNull UserHandle userHandle,
184 @NonNull String token, @NonNull InstantAppResolutionCallback callback) {
Hai Zhangbfa4f902018-08-21 11:33:33 -0700185 // If not overridden, forward to the old method.
186 onGetInstantAppResolveInfo(sanitizedIntent, hostDigestPrefix, token, callback);
187 }
188
189 /**
190 * Called to retrieve intent filters for potentially matching instant applications. Unlike
191 * {@link #onGetInstantAppResolveInfo(Intent, int[], UserHandle, String,
192 * InstantAppResolutionCallback)}, the response may take as long as necessary to respond. All
193 * {@link InstantAppResolveInfo}s provided in response to this method must be completely
194 * populated.
195 *
196 * @param sanitizedIntent The sanitized {@link Intent} used for resolution.
197 * @param hostDigestPrefix The hash prefix of the instant app's domain or null if no host is
198 * defined.
199 * @param userHandle The user for which to resolve the instant app.
200 * @param token A unique identifier that was provided in {@link #onGetInstantAppResolveInfo(
201 * Intent, int[], UserHandle, String, InstantAppResolutionCallback)} and provided
202 * to the currently visible installer via {@link Intent#EXTRA_INSTANT_APP_TOKEN}.
203 * @param callback The {@link InstantAppResolutionCallback} to provide results to.
Winson81fef842019-08-28 12:19:08 -0700204 *
205 * @deprecated Should implement {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
206 * InstantAppResolutionCallback)}
Hai Zhangbfa4f902018-08-21 11:33:33 -0700207 */
Winson81fef842019-08-28 12:19:08 -0700208 @Deprecated
Todd Kennedy63ff4642019-03-25 11:20:01 -0700209 public void onGetInstantAppIntentFilter(@NonNull Intent sanitizedIntent,
210 @Nullable int[] hostDigestPrefix, @NonNull UserHandle userHandle,
211 @NonNull String token, @NonNull InstantAppResolutionCallback callback) {
Hai Zhangbfa4f902018-08-21 11:33:33 -0700212 // If not overridden, forward to the old method.
213 onGetInstantAppIntentFilter(sanitizedIntent, hostDigestPrefix, token, callback);
214 }
215
216 /**
Winson81fef842019-08-28 12:19:08 -0700217 * Called to retrieve resolve info for instant applications immediately. The response will be
218 * ignored if not provided within a reasonable time. {@link InstantAppResolveInfo}s provided
219 * in response to this method may be partial to request a second phase of resolution which will
220 * result in a subsequent call to {@link #onGetInstantAppIntentFilter(InstantAppRequestInfo,
221 * InstantAppResolutionCallback)}
222 *
223 * @param request The parameters for this resolution request
224 * @param callback The {@link InstantAppResolutionCallback} to provide results to.
225 *
226 * @see InstantAppResolveInfo
227 */
228 public void onGetInstantAppResolveInfo(@NonNull InstantAppRequestInfo request,
229 @NonNull InstantAppResolutionCallback callback) {
230 // If not overridden, forward to the old method.
231 onGetInstantAppResolveInfo(request.intent, request.hostDigestPrefix, request.userHandle,
232 request.token, callback);
233 }
234
235 /**
236 * Called to retrieve intent filters for potentially matching instant applications. Unlike
237 * {@link #onGetInstantAppResolveInfo(InstantAppRequestInfo, InstantAppResolutionCallback)},
238 * the response may take as long as necessary to respond. All {@link InstantAppResolveInfo}s
239 * provided in response to this method must be completely populated.
240 *
241 * @param request The parameters for this resolution request
242 * @param callback The {@link InstantAppResolutionCallback} to provide results to.
243 */
244 public void onGetInstantAppIntentFilter(@NonNull InstantAppRequestInfo request,
245 @NonNull InstantAppResolutionCallback callback) {
246 // If not overridden, forward to the old method.
247 onGetInstantAppIntentFilter(request.intent, request.hostDigestPrefix, request.userHandle,
248 request.token, callback);
249 }
250
251 /**
Todd Kennedy1fb34042017-03-01 13:56:58 -0800252 * Returns a {@link Looper} to perform service operations on.
253 */
254 Looper getLooper() {
255 return getBaseContext().getMainLooper();
256 }
257
258 @Override
259 public final void attachBaseContext(Context base) {
260 super.attachBaseContext(base);
261 mHandler = new ServiceHandler(getLooper());
262 }
263
264 @Override
265 public final IBinder onBind(Intent intent) {
266 return new IInstantAppResolver.Stub() {
267 @Override
Winson81fef842019-08-28 12:19:08 -0700268 public void getInstantAppResolveInfoList(InstantAppRequestInfo request, int sequence,
269 IRemoteCallback callback) {
Patrick Baumann43c97a02018-01-31 20:09:03 +0000270 if (DEBUG_INSTANT) {
Winson81fef842019-08-28 12:19:08 -0700271 Slog.v(TAG, "[" + request.token + "] Phase1 called; posting");
Todd Kennedy46b4f2b2017-04-21 12:20:03 -0700272 }
Todd Kennedyd3c51062017-03-17 16:03:29 -0700273 final SomeArgs args = SomeArgs.obtain();
Winson81fef842019-08-28 12:19:08 -0700274 args.arg1 = request;
275 args.arg2 = callback;
276 mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence,
277 0, args).sendToTarget();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800278 }
279
280 @Override
Winson81fef842019-08-28 12:19:08 -0700281 public void getInstantAppIntentFilterList(InstantAppRequestInfo request,
282 IRemoteCallback callback) {
Patrick Baumann43c97a02018-01-31 20:09:03 +0000283 if (DEBUG_INSTANT) {
Winson81fef842019-08-28 12:19:08 -0700284 Slog.v(TAG, "[" + request.token + "] Phase2 called; posting");
Todd Kennedy46b4f2b2017-04-21 12:20:03 -0700285 }
Todd Kennedyd3c51062017-03-17 16:03:29 -0700286 final SomeArgs args = SomeArgs.obtain();
Winson81fef842019-08-28 12:19:08 -0700287 args.arg1 = request;
288 args.arg2 = callback;
289 mHandler.obtainMessage(ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, args)
290 .sendToTarget();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800291 }
292 };
293 }
294
295 /**
296 * Callback to post results from instant app resolution.
297 */
298 public static final class InstantAppResolutionCallback {
299 private final IRemoteCallback mCallback;
300 private final int mSequence;
Winson191069d2019-12-20 15:35:29 -0800301
302 /** @hide **/
303 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
304 public InstantAppResolutionCallback(int sequence, IRemoteCallback callback) {
Todd Kennedy1fb34042017-03-01 13:56:58 -0800305 mCallback = callback;
306 mSequence = sequence;
307 }
308
309 public void onInstantAppResolveInfo(List<InstantAppResolveInfo> resolveInfo) {
310 final Bundle data = new Bundle();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800311 data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
Todd Kennedyd3c51062017-03-17 16:03:29 -0700312 data.putInt(EXTRA_SEQUENCE, mSequence);
Todd Kennedy1fb34042017-03-01 13:56:58 -0800313 try {
314 mCallback.sendResult(data);
315 } catch (RemoteException e) {
316 }
317 }
318 }
319
Todd Kennedy1fb34042017-03-01 13:56:58 -0800320 private final class ServiceHandler extends Handler {
321 public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1;
322 public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800323 public ServiceHandler(Looper looper) {
324 super(looper, null /*callback*/, true /*async*/);
325 }
326
327 @Override
328 @SuppressWarnings("unchecked")
329 public void handleMessage(Message message) {
330 final int action = message.what;
331 switch (action) {
332 case MSG_GET_INSTANT_APP_RESOLVE_INFO: {
Todd Kennedyd3c51062017-03-17 16:03:29 -0700333 final SomeArgs args = (SomeArgs) message.obj;
Winson81fef842019-08-28 12:19:08 -0700334 final InstantAppRequestInfo request = (InstantAppRequestInfo) args.arg1;
335 final IRemoteCallback callback = (IRemoteCallback) args.arg2;
336 args.recycle();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800337 final int sequence = message.arg1;
Patrick Baumann43c97a02018-01-31 20:09:03 +0000338 if (DEBUG_INSTANT) {
Winson81fef842019-08-28 12:19:08 -0700339 Slog.d(TAG, "[" + request.token + "] Phase1 request;"
340 + " prefix: " + Arrays.toString(request.hostDigestPrefix)
341 + ", userId: " + request.userHandle.getIdentifier());
Patrick Baumann577d4022018-01-31 16:55:10 +0000342 }
Winson81fef842019-08-28 12:19:08 -0700343 onGetInstantAppResolveInfo(request,
Todd Kennedyd3c51062017-03-17 16:03:29 -0700344 new InstantAppResolutionCallback(sequence, callback));
Todd Kennedy1fb34042017-03-01 13:56:58 -0800345 } break;
346
347 case MSG_GET_INSTANT_APP_INTENT_FILTER: {
Todd Kennedyd3c51062017-03-17 16:03:29 -0700348 final SomeArgs args = (SomeArgs) message.obj;
Winson81fef842019-08-28 12:19:08 -0700349 final InstantAppRequestInfo request = (InstantAppRequestInfo) args.arg1;
350 final IRemoteCallback callback = (IRemoteCallback) args.arg2;
351 args.recycle();
Patrick Baumann43c97a02018-01-31 20:09:03 +0000352 if (DEBUG_INSTANT) {
Winson81fef842019-08-28 12:19:08 -0700353 Slog.d(TAG, "[" + request.token + "] Phase2 request;"
354 + " prefix: " + Arrays.toString(request.hostDigestPrefix)
355 + ", userId: " + request.userHandle.getIdentifier());
Patrick Baumann577d4022018-01-31 16:55:10 +0000356 }
Winson81fef842019-08-28 12:19:08 -0700357 onGetInstantAppIntentFilter(request,
Todd Kennedyd3c51062017-03-17 16:03:29 -0700358 new InstantAppResolutionCallback(-1 /*sequence*/, callback));
Winson81fef842019-08-28 12:19:08 -0700359 }
360 break;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800361
362 default: {
363 throw new IllegalArgumentException("Unknown message: " + action);
364 }
365 }
366 }
367 }
368}