Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package android.app; |
| 18 | |
| 19 | import android.annotation.SystemApi; |
| 20 | import android.app.Service; |
| 21 | import android.content.Context; |
| 22 | import android.content.Intent; |
| 23 | import android.content.pm.InstantAppResolveInfo; |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 24 | import android.os.Build; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 25 | import android.os.Bundle; |
| 26 | import android.os.Handler; |
| 27 | import android.os.IBinder; |
| 28 | import android.os.IRemoteCallback; |
| 29 | import android.os.Looper; |
| 30 | import android.os.Message; |
| 31 | import android.os.RemoteException; |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 32 | import android.util.Log; |
| 33 | import android.util.Slog; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 34 | |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 35 | import com.android.internal.os.SomeArgs; |
| 36 | |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 37 | import java.util.Arrays; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 38 | import java.util.List; |
| 39 | |
| 40 | /** |
| 41 | * Base class for implementing the resolver service. |
| 42 | * @hide |
| 43 | */ |
| 44 | @SystemApi |
| 45 | public abstract class InstantAppResolverService extends Service { |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 46 | private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; |
| 47 | private static final String TAG = "PackageManager"; |
| 48 | |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 49 | /** @hide */ |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 50 | public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO"; |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 51 | /** @hide */ |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 52 | public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE"; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 53 | 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 Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 61 | int digestPrefix[], String token, InstantAppResolutionCallback callback) { |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 62 | 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 Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 71 | int digestPrefix[], String token, InstantAppResolutionCallback callback) { |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 72 | 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 Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 93 | int digestPrefix[], String token, int sequence, IRemoteCallback callback) { |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 94 | if (DEBUG_EPHEMERAL) { |
| 95 | Slog.v(TAG, "[" + token + "] Phase1 called; posting"); |
| 96 | } |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 97 | 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 Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | @Override |
| 107 | public void getInstantAppIntentFilterList( |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 108 | int digestPrefix[], String token, String hostName, IRemoteCallback callback) { |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 109 | if (DEBUG_EPHEMERAL) { |
| 110 | Slog.v(TAG, "[" + token + "] Phase2 called; posting"); |
| 111 | } |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 112 | 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 Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 119 | } |
| 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 Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 136 | data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo); |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 137 | data.putInt(EXTRA_SEQUENCE, mSequence); |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 138 | try { |
| 139 | mCallback.sendResult(data); |
| 140 | } catch (RemoteException e) { |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | @Deprecated |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 146 | void _onGetInstantAppResolveInfo(int[] digestPrefix, String token, |
| 147 | InstantAppResolutionCallback callback) { |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 148 | if (DEBUG_EPHEMERAL) { |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 149 | Slog.d(TAG, "[" + token + "] Phase1 request;" |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 150 | + " prefix: " + Arrays.toString(digestPrefix)); |
| 151 | } |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 152 | onGetInstantAppResolveInfo(digestPrefix, token, callback); |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 153 | } |
| 154 | @Deprecated |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 155 | void _onGetInstantAppIntentFilter(int digestPrefix[], String token, String hostName, |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 156 | InstantAppResolutionCallback callback) { |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 157 | if (DEBUG_EPHEMERAL) { |
Todd Kennedy | 46b4f2b | 2017-04-21 12:20:03 -0700 | [diff] [blame] | 158 | Slog.d(TAG, "[" + token + "] Phase2 request;" |
Todd Kennedy | 02a6b73 | 2017-04-05 14:24:58 -0700 | [diff] [blame] | 159 | + " prefix: " + Arrays.toString(digestPrefix)); |
| 160 | } |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 161 | onGetInstantAppIntentFilter(digestPrefix, token, callback); |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 162 | } |
| 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 Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 178 | 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 Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 182 | final int sequence = message.arg1; |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 183 | _onGetInstantAppResolveInfo( |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 184 | digestPrefix, token, |
| 185 | new InstantAppResolutionCallback(sequence, callback)); |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 186 | } break; |
| 187 | |
| 188 | case MSG_GET_INSTANT_APP_INTENT_FILTER: { |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 189 | 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 Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 194 | _onGetInstantAppIntentFilter( |
Todd Kennedy | d3c5106 | 2017-03-17 16:03:29 -0700 | [diff] [blame] | 195 | digestPrefix, token, hostName, |
| 196 | new InstantAppResolutionCallback(-1 /*sequence*/, callback)); |
Todd Kennedy | 1fb3404 | 2017-03-01 13:56:58 -0800 | [diff] [blame] | 197 | } break; |
| 198 | |
| 199 | default: { |
| 200 | throw new IllegalArgumentException("Unknown message: " + action); |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | } |
| 205 | } |