11fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy/* 21fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Copyright (C) 2017 The Android Open Source Project 31fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * 41fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Licensed under the Apache License, Version 2.0 (the "License"); 51fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * you may not use this file except in compliance with the License. 61fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * You may obtain a copy of the License at 71fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * 81fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * http://www.apache.org/licenses/LICENSE-2.0 91fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * 101fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Unless required by applicable law or agreed to in writing, software 111fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * distributed under the License is distributed on an "AS IS" BASIS, 121fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * See the License for the specific language governing permissions and 141fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * limitations under the License. 151fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy */ 161fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 171fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedypackage android.app; 181fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 191fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.annotation.SystemApi; 201fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.app.Service; 211fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.content.Context; 221fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.content.Intent; 231fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.content.pm.InstantAppResolveInfo; 2402a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedyimport android.os.Build; 251fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.Bundle; 261fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.Handler; 271fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.IBinder; 281fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.IRemoteCallback; 291fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.Looper; 301fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.Message; 311fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport android.os.RemoteException; 3202a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedyimport android.util.Log; 3302a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedyimport android.util.Slog; 341fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 35d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedyimport com.android.internal.os.SomeArgs; 36d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy 3702a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedyimport java.util.Arrays; 381fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedyimport java.util.List; 391fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 401fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy/** 411fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Base class for implementing the resolver service. 421fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * @hide 431fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy */ 441fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy@SystemApi 451fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedypublic abstract class InstantAppResolverService extends Service { 4602a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy private static final boolean DEBUG_EPHEMERAL = Build.IS_DEBUGGABLE; 4702a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy private static final String TAG = "PackageManager"; 4802a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy 49d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy /** @hide */ 501fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO"; 51d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy /** @hide */ 521fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE"; 531fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy Handler mHandler; 541fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 551fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy /** 561fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Called to retrieve resolve info for instant applications. 571fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * 581fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * @param digestPrefix The hash prefix of the instant app's domain. 591fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy */ 601fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public void onGetInstantAppResolveInfo( 61d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy int digestPrefix[], String token, InstantAppResolutionCallback callback) { 621fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy throw new IllegalStateException("Must define"); 631fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 641fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 651fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy /** 661fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Called to retrieve intent filters for instant applications. 671fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * 681fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * @param digestPrefix The hash prefix of the instant app's domain. 691fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy */ 701fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public void onGetInstantAppIntentFilter( 71d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy int digestPrefix[], String token, InstantAppResolutionCallback callback) { 721fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy throw new IllegalStateException("Must define"); 731fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 741fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 751fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy /** 761fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Returns a {@link Looper} to perform service operations on. 771fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy */ 781fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy Looper getLooper() { 791fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy return getBaseContext().getMainLooper(); 801fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 811fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 821fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Override 831fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public final void attachBaseContext(Context base) { 841fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy super.attachBaseContext(base); 851fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy mHandler = new ServiceHandler(getLooper()); 861fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 871fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 881fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Override 891fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public final IBinder onBind(Intent intent) { 901fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy return new IInstantAppResolver.Stub() { 911fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Override 921fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public void getInstantAppResolveInfoList( 93d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy int digestPrefix[], String token, int sequence, IRemoteCallback callback) { 9446b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy if (DEBUG_EPHEMERAL) { 9546b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy Slog.v(TAG, "[" + token + "] Phase1 called; posting"); 9646b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy } 97d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final SomeArgs args = SomeArgs.obtain(); 98d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg1 = callback; 99d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg2 = digestPrefix; 100d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg3 = token; 101d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy mHandler.obtainMessage( 102d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy ServiceHandler.MSG_GET_INSTANT_APP_RESOLVE_INFO, sequence, 0, args) 103d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy .sendToTarget(); 1041fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1051fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1061fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Override 1071fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public void getInstantAppIntentFilterList( 108d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy int digestPrefix[], String token, String hostName, IRemoteCallback callback) { 10946b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy if (DEBUG_EPHEMERAL) { 11046b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy Slog.v(TAG, "[" + token + "] Phase2 called; posting"); 11146b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy } 112d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final SomeArgs args = SomeArgs.obtain(); 113d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg1 = callback; 114d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg2 = digestPrefix; 115d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg3 = token; 116d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy args.arg4 = hostName; 117d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy mHandler.obtainMessage( 118d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy ServiceHandler.MSG_GET_INSTANT_APP_INTENT_FILTER, callback).sendToTarget(); 1191fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1201fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy }; 1211fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1221fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1231fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy /** 1241fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy * Callback to post results from instant app resolution. 1251fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy */ 1261fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public static final class InstantAppResolutionCallback { 1271fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy private final IRemoteCallback mCallback; 1281fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy private final int mSequence; 1291fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy InstantAppResolutionCallback(int sequence, IRemoteCallback callback) { 1301fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy mCallback = callback; 1311fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy mSequence = sequence; 1321fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1331fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1341fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public void onInstantAppResolveInfo(List<InstantAppResolveInfo> resolveInfo) { 1351fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy final Bundle data = new Bundle(); 1361fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo); 137d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy data.putInt(EXTRA_SEQUENCE, mSequence); 1381fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy try { 1391fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy mCallback.sendResult(data); 1401fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } catch (RemoteException e) { 1411fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1421fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1431fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1441fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1451fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Deprecated 146d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy void _onGetInstantAppResolveInfo(int[] digestPrefix, String token, 147d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy InstantAppResolutionCallback callback) { 14802a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy if (DEBUG_EPHEMERAL) { 14946b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy Slog.d(TAG, "[" + token + "] Phase1 request;" 15002a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy + " prefix: " + Arrays.toString(digestPrefix)); 15102a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy } 152d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy onGetInstantAppResolveInfo(digestPrefix, token, callback); 1531fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1541fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Deprecated 155d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy void _onGetInstantAppIntentFilter(int digestPrefix[], String token, String hostName, 1561fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy InstantAppResolutionCallback callback) { 15702a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy if (DEBUG_EPHEMERAL) { 15846b4f2b7956e61cc2d4bc2f086c20ac859d44ba4Todd Kennedy Slog.d(TAG, "[" + token + "] Phase2 request;" 15902a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy + " prefix: " + Arrays.toString(digestPrefix)); 16002a6b73e979e07bfd20cbaca01cb16a165c7b791Todd Kennedy } 161d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy onGetInstantAppIntentFilter(digestPrefix, token, callback); 1621fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1631fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1641fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy private final class ServiceHandler extends Handler { 1651fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public static final int MSG_GET_INSTANT_APP_RESOLVE_INFO = 1; 1661fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public static final int MSG_GET_INSTANT_APP_INTENT_FILTER = 2; 1671fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1681fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public ServiceHandler(Looper looper) { 1691fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy super(looper, null /*callback*/, true /*async*/); 1701fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 1711fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1721fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @Override 1731fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy @SuppressWarnings("unchecked") 1741fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy public void handleMessage(Message message) { 1751fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy final int action = message.what; 1761fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy switch (action) { 1771fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy case MSG_GET_INSTANT_APP_RESOLVE_INFO: { 178d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final SomeArgs args = (SomeArgs) message.obj; 179d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final IRemoteCallback callback = (IRemoteCallback) args.arg1; 180d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final int[] digestPrefix = (int[]) args.arg2; 181d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final String token = (String) args.arg3; 1821fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy final int sequence = message.arg1; 1831fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy _onGetInstantAppResolveInfo( 184d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy digestPrefix, token, 185d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy new InstantAppResolutionCallback(sequence, callback)); 1861fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } break; 1871fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1881fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy case MSG_GET_INSTANT_APP_INTENT_FILTER: { 189d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final SomeArgs args = (SomeArgs) message.obj; 190d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final IRemoteCallback callback = (IRemoteCallback) args.arg1; 191d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final int[] digestPrefix = (int[]) args.arg2; 192d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final String token = (String) args.arg3; 193d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy final String hostName = (String) args.arg4; 1941fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy _onGetInstantAppIntentFilter( 195d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy digestPrefix, token, hostName, 196d3c5106940838f2867afbbbfe251aaad38ab24b5Todd Kennedy new InstantAppResolutionCallback(-1 /*sequence*/, callback)); 1971fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } break; 1981fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy 1991fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy default: { 2001fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy throw new IllegalArgumentException("Unknown message: " + action); 2011fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 2021fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 2031fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 2041fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy } 2051fb3404b2ba69a823e961bec2d9ed61622107052Todd Kennedy} 206