1/*
2 * Copyright (C) 2015 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.EphemeralResolveInfo;
24import android.os.Bundle;
25import android.os.Handler;
26import android.os.IBinder;
27import android.os.IRemoteCallback;
28import android.os.Looper;
29import android.os.Message;
30import android.os.RemoteException;
31
32import java.util.List;
33
34/**
35 * Base class for implementing the resolver service.
36 * @hide
37 */
38@SystemApi
39public abstract class EphemeralResolverService extends Service {
40    public static final String EXTRA_RESOLVE_INFO = "android.app.extra.RESOLVE_INFO";
41    public static final String EXTRA_SEQUENCE = "android.app.extra.SEQUENCE";
42    private static final String EXTRA_PREFIX = "android.app.PREFIX";
43    private Handler mHandler;
44
45    /**
46     * Called to retrieve resolve info for ephemeral applications.
47     *
48     * @param digestPrefix The hash prefix of the ephemeral's domain.
49     * @param prefixMask A mask that was applied to each digest prefix. This should
50     *      be used when comparing against the digest prefixes as all bits might
51     *      not be set.
52     */
53    public abstract List<EphemeralResolveInfo> onEphemeralResolveInfoList(
54            int digestPrefix[], int prefixMask);
55
56    @Override
57    public final void attachBaseContext(Context base) {
58        super.attachBaseContext(base);
59        mHandler = new ServiceHandler(base.getMainLooper());
60    }
61
62    @Override
63    public final IBinder onBind(Intent intent) {
64        return new IEphemeralResolver.Stub() {
65            @Override
66            public void getEphemeralResolveInfoList(
67                    IRemoteCallback callback, int digestPrefix[], int prefixMask, int sequence) {
68                final Message msg = mHandler.obtainMessage(
69                        ServiceHandler.MSG_GET_EPHEMERAL_RESOLVE_INFO, prefixMask, sequence, callback);
70                final Bundle data = new Bundle();
71                data.putIntArray(EXTRA_PREFIX, digestPrefix);
72                msg.setData(data);
73                msg.sendToTarget();
74            }
75        };
76    }
77
78    private final class ServiceHandler extends Handler {
79        public static final int MSG_GET_EPHEMERAL_RESOLVE_INFO = 1;
80
81        public ServiceHandler(Looper looper) {
82            super(looper, null /*callback*/, true /*async*/);
83        }
84
85        @Override
86        @SuppressWarnings("unchecked")
87        public void handleMessage(Message message) {
88            final int action = message.what;
89            switch (action) {
90                case MSG_GET_EPHEMERAL_RESOLVE_INFO: {
91                    final IRemoteCallback callback = (IRemoteCallback) message.obj;
92                    final int[] digestPrefix = message.getData().getIntArray(EXTRA_PREFIX);
93                    final List<EphemeralResolveInfo> resolveInfo =
94                            onEphemeralResolveInfoList(digestPrefix, message.arg1);
95                    final Bundle data = new Bundle();
96                    data.putInt(EXTRA_SEQUENCE, message.arg2);
97                    data.putParcelableList(EXTRA_RESOLVE_INFO, resolveInfo);
98                    try {
99                        callback.sendResult(data);
100                    } catch (RemoteException e) {
101                    }
102                } break;
103
104                default: {
105                    throw new IllegalArgumentException("Unknown message: " + action);
106                }
107            }
108        }
109    }
110}
111