File: DisplayHashingService.java

package info (click to toggle)
android-platform-frameworks-base 1%3A14~beta1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 326,084 kB
  • sloc: java: 2,032,373; xml: 343,016; cpp: 304,181; python: 3,683; ansic: 2,090; sh: 1,871; makefile: 120; sed: 19
file content (204 lines) | stat: -rw-r--r-- 8,609 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.service.displayhash;

import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteCallback;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.DisplayHashResultCallback;
import android.view.displayhash.VerifiedDisplayHash;

import java.util.Map;

/**
 * A service that handles generating and verify {@link DisplayHash}.
 *
 * The service will generate a DisplayHash based on arguments passed in. Then later that
 * same DisplayHash can be verified to determine that it was created by the system.
 *
 * @hide
 */
@SystemApi
public abstract class DisplayHashingService extends Service {

    /** @hide **/
    public static final String EXTRA_VERIFIED_DISPLAY_HASH =
            "android.service.displayhash.extra.VERIFIED_DISPLAY_HASH";

    /** @hide **/
    public static final String EXTRA_INTERVAL_BETWEEN_REQUESTS =
            "android.service.displayhash.extra.INTERVAL_BETWEEN_REQUESTS";

    /**
     * The {@link Intent} action that must be declared as handled by a service in its manifest
     * for the system to recognize it as a DisplayHash providing service.
     *
     * @hide
     */
    @SystemApi
    public static final String SERVICE_INTERFACE =
            "android.service.displayhash.DisplayHashingService";

    private DisplayHashingServiceWrapper mWrapper;
    private Handler mHandler;

    @Override
    public void onCreate() {
        super.onCreate();
        mWrapper = new DisplayHashingServiceWrapper();
        mHandler = new Handler(Looper.getMainLooper(), null, true);
    }

    @NonNull
    @Override
    public final IBinder onBind(@NonNull Intent intent) {
        return mWrapper;
    }

    /**
     * Generates the DisplayHash that can be used to validate that the system generated the
     * token.
     *
     * @param salt          The salt to use when generating the hmac. This should be unique to the
     *                      caller so the token cannot be verified by any other process.
     * @param buffer        The buffer for the content to generate the hash for.
     * @param bounds        The size and position of the content in window space.
     * @param hashAlgorithm The String for the hashing algorithm to use based values in
     *                      {@link #getDisplayHashAlgorithms(RemoteCallback)}.
     * @param callback      The callback to invoke
     *                      {@link DisplayHashResultCallback#onDisplayHashResult(DisplayHash)}
     *                      if successfully generated a DisplayHash or {@link
     *                      DisplayHashResultCallback#onDisplayHashError(int)} if failed.
     */
    public abstract void onGenerateDisplayHash(@NonNull byte[] salt,
            @NonNull HardwareBuffer buffer, @NonNull Rect bounds,
            @NonNull String hashAlgorithm, @NonNull DisplayHashResultCallback callback);

    /**
     * Returns a map of supported algorithms and their {@link DisplayHashParams}
     */
    @NonNull
    public abstract Map<String, DisplayHashParams> onGetDisplayHashAlgorithms();

    /**
     * Call to verify that the DisplayHash passed in was generated by the system.
     *
     * @param salt        The salt value to use when verifying the hmac. This should be the
     *                    same value that was passed to
     *                    {@link #onGenerateDisplayHash(byte[],
     *                    HardwareBuffer, Rect, String, DisplayHashResultCallback)} to
     *                    generate the token.
     * @param displayHash The token to verify that it was generated by the system.
     * @return a {@link VerifiedDisplayHash} if the provided display hash was originally generated
     * by the system or null if the system did not generate the display hash.
     */
    @Nullable
    public abstract VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[] salt,
            @NonNull DisplayHash displayHash);

    private void verifyDisplayHash(byte[] salt, DisplayHash displayHash,
            RemoteCallback callback) {
        VerifiedDisplayHash verifiedDisplayHash = onVerifyDisplayHash(salt,
                displayHash);
        final Bundle data = new Bundle();
        data.putParcelable(EXTRA_VERIFIED_DISPLAY_HASH, verifiedDisplayHash);
        callback.sendResult(data);
    }

    private void getDisplayHashAlgorithms(RemoteCallback callback) {
        Map<String, DisplayHashParams> displayHashParams = onGetDisplayHashAlgorithms();
        final Bundle data = new Bundle();
        for (Map.Entry<String, DisplayHashParams> entry : displayHashParams.entrySet()) {
            data.putParcelable(entry.getKey(), entry.getValue());
        }
        callback.sendResult(data);
    }

    /**
     * Call to get the interval required between display hash requests. Requests made faster than
     * this will be throttled.
     *
     * @return the interval value required between requests.
     */
    public abstract int onGetIntervalBetweenRequestsMillis();

    private void getDurationBetweenRequestsMillis(RemoteCallback callback) {
        int durationBetweenRequestMillis = onGetIntervalBetweenRequestsMillis();
        Bundle data = new Bundle();
        data.putInt(EXTRA_INTERVAL_BETWEEN_REQUESTS, durationBetweenRequestMillis);
        callback.sendResult(data);
    }

    private final class DisplayHashingServiceWrapper extends IDisplayHashingService.Stub {
        @Override
        public void generateDisplayHash(byte[] salt, HardwareBuffer buffer, Rect bounds,
                String hashAlgorithm, RemoteCallback callback) {
            mHandler.sendMessage(
                    obtainMessage(DisplayHashingService::onGenerateDisplayHash,
                            DisplayHashingService.this, salt, buffer, bounds,
                            hashAlgorithm, new DisplayHashResultCallback() {
                                @Override
                                public void onDisplayHashResult(
                                        @NonNull DisplayHash displayHash) {
                                    Bundle result = new Bundle();
                                    result.putParcelable(EXTRA_DISPLAY_HASH, displayHash);
                                    callback.sendResult(result);
                                }

                                @Override
                                public void onDisplayHashError(int errorCode) {
                                    Bundle result = new Bundle();
                                    result.putInt(EXTRA_DISPLAY_HASH_ERROR_CODE, errorCode);
                                    callback.sendResult(result);
                                }
                            }));
        }

        @Override
        public void verifyDisplayHash(byte[] salt, DisplayHash displayHash,
                RemoteCallback callback) {
            mHandler.sendMessage(
                    obtainMessage(DisplayHashingService::verifyDisplayHash,
                            DisplayHashingService.this, salt, displayHash, callback));
        }

        @Override
        public void getDisplayHashAlgorithms(RemoteCallback callback) {
            mHandler.sendMessage(obtainMessage(DisplayHashingService::getDisplayHashAlgorithms,
                    DisplayHashingService.this, callback));
        }

        @Override
        public void getIntervalBetweenRequestsMillis(RemoteCallback callback) {
            mHandler.sendMessage(
                    obtainMessage(DisplayHashingService::getDurationBetweenRequestsMillis,
                            DisplayHashingService.this, callback));
        }
    }
}