blob: c5dc86c79ef954262eb6438c93267357a8d4fa8d [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
19import android.annotation.SystemApi;
20import android.app.Service;
21import android.content.Context;
22import android.content.Intent;
23import android.content.pm.InstantAppResolveInfo;
Todd Kennedy02a6b732017-04-05 14:24:58 -070024import android.os.Build;
Todd Kennedy1fb34042017-03-01 13:56:58 -080025import android.os.Bundle;
26import android.os.Handler;
27import android.os.IBinder;
28import android.os.IRemoteCallback;
29import android.os.Looper;
30import android.os.Message;
31import android.os.RemoteException;
Todd Kennedy02a6b732017-04-05 14:24:58 -070032import android.util.Log;
33import android.util.Slog;
Todd Kennedy1fb34042017-03-01 13:56:58 -080034
Todd Kennedyd3c51062017-03-17 16:03:29 -070035import com.android.internal.os.SomeArgs;
36
Todd Kennedy02a6b732017-04-05 14:24:58 -070037import java.util.Arrays;
Todd Kennedy1fb34042017-03-01 13:56:58 -080038import java.util.List;
39
40/**
41 * Base class for implementing the resolver service.
42 * @hide
43 */
44@SystemApi
45public abstract class InstantAppResolverService extends Service {
Todd Kennedy02a6b732017-04-05 14:24:58 -070046 private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE;
47 private static final String TAG = "PackageManager";
48
Todd Kennedyd3c51062017-03-17 16:03:29 -070049 /** @hide */
Todd Kennedy1fb34042017-03-01 13:56:58 -080050 public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
Todd Kennedyd3c51062017-03-17 16:03:29 -070051 /** @hide */
Todd Kennedy1fb34042017-03-01 13:56:58 -080052 public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
Todd Kennedy1fb34042017-03-01 13:56:58 -080053 Handler mHandler;
54
55 /**
56 * Called to retrieve resolve info for instant applications.
57 *
58 * @param digestPrefix The hash prefix of the instant app's domain.
59 */
60 public void onGetInstantAppResolveInfo(
Todd Kennedyd3c51062017-03-17 16:03:29 -070061 int digestPrefix[], String token, InstantAppResolutionCallback callback) {
Todd Kennedy1fb34042017-03-01 13:56:58 -080062 throw new IllegalStateException("Must define");
63 }
64
65 /**
66 * Called to retrieve intent filters for instant applications.
67 *
68 * @param digestPrefix The hash prefix of the instant app's domain.
69 */
70 public void onGetInstantAppIntentFilter(
Todd Kennedyd3c51062017-03-17 16:03:29 -070071 int digestPrefix[], String token, InstantAppResolutionCallback callback) {
Todd Kennedy1fb34042017-03-01 13:56:58 -080072 throw new IllegalStateException("Must define");
73 }
74
75 /**
76 * Returns a {@link Looper} to perform service operations on.
77 */
78 Looper getLooper() {
79 return getBaseContext().getMainLooper();
80 }
81
82 @Override
83 public final void attachBaseContext(Context base) {
84 super.attachBaseContext(base);
85 mHandler = new ServiceHandler(getLooper());
86 }
87
88 @Override
89 public final IBinder onBind(Intent intent) {
90 return new IInstantAppResolver.Stub() {
91 @Override
92 public void getInstantAppResolveInfoList(
Todd Kennedyd3c51062017-03-17 16:03:29 -070093 int digestPrefix[], String token, int sequence, IRemoteCallback callback) {
Todd Kennedy46b4f2b2017-04-21 12:20:03 -070094 if (DEBUG_EPHEMERAL) {
95 Slog.v(TAG, "[" + token + "] Phase1 called; posting");
96 }
Todd Kennedyd3c51062017-03-17 16:03:29 -070097 final SomeArgs args = SomeArgs.obtain();
98 args.arg1 = callback;
99 args.arg2 = digestPrefix;
100 args.arg3 = token;
101 mHandler.obtainMessage(
102 ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence, 0, args)
103 .sendToTarget();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800104 }
105
106 @Override
107 public void getInstantAppIntentFilterList(
Todd Kennedyd3c51062017-03-17 16:03:29 -0700108 int digestPrefix[], String token, String hostName, IRemoteCallback callback) {
Todd Kennedy46b4f2b2017-04-21 12:20:03 -0700109 if (DEBUG_EPHEMERAL) {
110 Slog.v(TAG, "[" + token + "] Phase2 called; posting");
111 }
Todd Kennedyd3c51062017-03-17 16:03:29 -0700112 final SomeArgs args = SomeArgs.obtain();
113 args.arg1 = callback;
114 args.arg2 = digestPrefix;
115 args.arg3 = token;
116 args.arg4 = hostName;
117 mHandler.obtainMessage(
118 ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, callback).sendToTarget();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800119 }
120 };
121 }
122
123 /**
124 * Callback to post results from instant app resolution.
125 */
126 public static final class InstantAppResolutionCallback {
127 private final IRemoteCallback mCallback;
128 private final int mSequence;
129 InstantAppResolutionCallback(int sequence, IRemoteCallback callback) {
130 mCallback = callback;
131 mSequence = sequence;
132 }
133
134 public void onInstantAppResolveInfo(List<InstantAppResolveInfo> resolveInfo) {
135 final Bundle data = new Bundle();
Todd Kennedy1fb34042017-03-01 13:56:58 -0800136 data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
Todd Kennedyd3c51062017-03-17 16:03:29 -0700137 data.putInt(EXTRA_SEQUENCE, mSequence);
Todd Kennedy1fb34042017-03-01 13:56:58 -0800138 try {
139 mCallback.sendResult(data);
140 } catch (RemoteException e) {
141 }
142 }
143 }
144
145 @Deprecated
Todd Kennedyd3c51062017-03-17 16:03:29 -0700146 void _onGetInstantAppResolveInfo(int[] digestPrefix, String token,
147 InstantAppResolutionCallback callback) {
Todd Kennedy02a6b732017-04-05 14:24:58 -0700148 if (DEBUG_EPHEMERAL) {
Todd Kennedy46b4f2b2017-04-21 12:20:03 -0700149 Slog.d(TAG, "[" + token + "] Phase1 request;"
Todd Kennedy02a6b732017-04-05 14:24:58 -0700150 + " prefix: " + Arrays.toString(digestPrefix));
151 }
Todd Kennedyd3c51062017-03-17 16:03:29 -0700152 onGetInstantAppResolveInfo(digestPrefix, token, callback);
Todd Kennedy1fb34042017-03-01 13:56:58 -0800153 }
154 @Deprecated
Todd Kennedyd3c51062017-03-17 16:03:29 -0700155 void _onGetInstantAppIntentFilter(int digestPrefix[], String token, String hostName,
Todd Kennedy1fb34042017-03-01 13:56:58 -0800156 InstantAppResolutionCallback callback) {
Todd Kennedy02a6b732017-04-05 14:24:58 -0700157 if (DEBUG_EPHEMERAL) {
Todd Kennedy46b4f2b2017-04-21 12:20:03 -0700158 Slog.d(TAG, "[" + token + "] Phase2 request;"
Todd Kennedy02a6b732017-04-05 14:24:58 -0700159 + " prefix: " + Arrays.toString(digestPrefix));
160 }
Todd Kennedyd3c51062017-03-17 16:03:29 -0700161 onGetInstantAppIntentFilter(digestPrefix, token, callback);
Todd Kennedy1fb34042017-03-01 13:56:58 -0800162 }
163
164 private final class ServiceHandler extends Handler {
165 public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1;
166 public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2;
167
168 public ServiceHandler(Looper looper) {
169 super(looper, null /*callback*/, true /*async*/);
170 }
171
172 @Override
173 @SuppressWarnings("unchecked")
174 public void handleMessage(Message message) {
175 final int action = message.what;
176 switch (action) {
177 case MSG_GET_INSTANT_APP_RESOLVE_INFO: {
Todd Kennedyd3c51062017-03-17 16:03:29 -0700178 final SomeArgs args = (SomeArgs) message.obj;
179 final IRemoteCallback callback = (IRemoteCallback) args.arg1;
180 final int[] digestPrefix = (int[]) args.arg2;
181 final String token = (String) args.arg3;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800182 final int sequence = message.arg1;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800183 _onGetInstantAppResolveInfo(
Todd Kennedyd3c51062017-03-17 16:03:29 -0700184 digestPrefix, token,
185 new InstantAppResolutionCallback(sequence, callback));
Todd Kennedy1fb34042017-03-01 13:56:58 -0800186 } break;
187
188 case MSG_GET_INSTANT_APP_INTENT_FILTER: {
Todd Kennedyd3c51062017-03-17 16:03:29 -0700189 final SomeArgs args = (SomeArgs) message.obj;
190 final IRemoteCallback callback = (IRemoteCallback) args.arg1;
191 final int[] digestPrefix = (int[]) args.arg2;
192 final String token = (String) args.arg3;
193 final String hostName = (String) args.arg4;
Todd Kennedy1fb34042017-03-01 13:56:58 -0800194 _onGetInstantAppIntentFilter(
Todd Kennedyd3c51062017-03-17 16:03:29 -0700195 digestPrefix, token, hostName,
196 new InstantAppResolutionCallback(-1 /*sequence*/, callback));
Todd Kennedy1fb34042017-03-01 13:56:58 -0800197 } break;
198
199 default: {
200 throw new IllegalArgumentException("Unknown message: " + action);
201 }
202 }
203 }
204 }
205}