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