blob: f809090ef71b0c70b21299fda888b7211ffead42 [file] [log] [blame]
/*
* 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.ext.services.displayhash;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM;
import static android.view.displayhash.DisplayHashResultCallback.DISPLAY_HASH_ERROR_UNKNOWN;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.service.displayhash.DisplayHashParams;
import android.service.displayhash.DisplayHasherService;
import android.util.ArrayMap;
import android.util.Log;
import android.view.displayhash.DisplayHash;
import android.view.displayhash.DisplayHashResultCallback;
import android.view.displayhash.VerifiedDisplayHash;
import androidx.annotation.NonNull;
import com.google.common.annotations.VisibleForTesting;
import java.util.Map;
/**
* The implementation service for {@link DisplayHasherService}
*/
public class DisplayHasherServiceImpl extends DisplayHasherService {
static final String TAG = "DisplayHasherService";
private ImageHashManager mImageHashManager = new ImageHashManager();
private final HmacKeyManager mHmacKeyManager = new HmacKeyManager();
private final ArrayMap<String, DisplayHashParams> mDisplayHashParams = new ArrayMap<>();
@Override
public void onCreate() {
super.onCreate();
mDisplayHashParams.put("PHASH", new DisplayHashParams.Builder()
.setBufferSize(32, 32)
.setGrayscaleBuffer(true).build());
}
@Override
public void onGenerateDisplayHash(@NonNull byte[] salt,
@NonNull HardwareBuffer buffer, @NonNull Rect bounds,
@NonNull String hashAlgorithm, @NonNull DisplayHashResultCallback callback) {
if (salt == null) {
Log.w(TAG, "Failed to generate display hash: salt was null");
callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
return;
}
int hashAlgorithmIndex = getIndexForHashAlgorithm(hashAlgorithm);
if (hashAlgorithmIndex < 0) {
Log.w(TAG, "Failed to generate display hash: invalid hash request");
callback.onDisplayHashError(DISPLAY_HASH_ERROR_INVALID_HASH_ALGORITHM);
return;
}
if (buffer == null) {
Log.w(TAG, "Failed to generate display hash: null buffer");
callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
return;
}
long timestamp = System.currentTimeMillis();
byte[] imageHash = mImageHashManager.generateHash(buffer, hashAlgorithm);
if (imageHash == null) {
Log.w(TAG, "Failed to generate display hash: failed to create image hash");
callback.onDisplayHashError(DISPLAY_HASH_ERROR_UNKNOWN);
return;
}
byte[] hmac = mHmacKeyManager.generateHmac(salt, timestamp, bounds, hashAlgorithmIndex,
imageHash);
callback.onDisplayHashResult(
new DisplayHash(timestamp, bounds, hashAlgorithm, imageHash, hmac));
}
@Override
public VerifiedDisplayHash onVerifyDisplayHash(@NonNull byte[] salt,
@NonNull DisplayHash displayHash) {
if (displayHash == null || salt == null) {
Log.w(TAG, "Failed to verify display hash: invalid token or salt");
return null;
}
boolean verified = mHmacKeyManager.verifyHmac(salt,
displayHash.getTimeMillis(), displayHash.getBoundsInWindow(),
getIndexForHashAlgorithm(displayHash.getHashAlgorithm()),
displayHash.getImageHash(), displayHash.getHmac());
if (verified) {
return new VerifiedDisplayHash(displayHash.getTimeMillis(),
displayHash.getBoundsInWindow(), displayHash.getHashAlgorithm(),
displayHash.getImageHash());
} else {
return null;
}
}
private int getIndexForHashAlgorithm(String hashAlgorithm) {
return mDisplayHashParams.indexOfKey(hashAlgorithm);
}
@VisibleForTesting
public void setImageHashManager(ImageHashManager imageHashManager) {
mImageHashManager = imageHashManager;
}
@NonNull
@Override
public Map<String, DisplayHashParams> onGetDisplayHashAlgorithms() {
return mDisplayHashParams;
}
}