/*
 * Copyright (C) 2020 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.server.biometrics;

import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import android.content.ComponentName;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.SensorProperties;
import android.os.SystemProperties;
import android.os.ParcelFileDescriptor;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.server.wm.Condition;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.server.biometrics.nano.BiometricServiceStateProto;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.util.List;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

public class Utils {

    private static final String TAG = "BiometricTestUtils";
    private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";

    /** adb command for dumping the biometric proto */
    public static final String DUMPSYS_BIOMETRIC = "dumpsys biometric --proto";

    /**
     * Retrieves the current SensorStates.
     */
    public interface SensorStatesSupplier {
        SensorStates getSensorStates() throws Exception;
    }

    /**
     * Waits for the service to become idle
     * @throws Exception
     */
    public static void waitForIdleService(@NonNull SensorStatesSupplier supplier) throws Exception {
        for (int i = 0; i < 10; i++) {
            if (!supplier.getSensorStates().areAllSensorsIdle()) {
                Log.d(TAG, "Not idle yet..");
                Thread.sleep(300);
            } else {
                return;
            }
        }
        Log.d(TAG, "Timed out waiting for idle");
    }

    /**
     * Waits for the specified sensor to become non-idle
     */
    public static void waitForBusySensor(int sensorId, @NonNull SensorStatesSupplier supplier)
            throws Exception {
        for (int i = 0; i < 10; i++) {
            if (!supplier.getSensorStates().sensorStates.get(sensorId).isBusy()) {
                Log.d(TAG, "Not busy yet..");
                Thread.sleep(300);
            } else {
                return;
            }
        }
        Log.d(TAG, "Timed out waiting to become busy");
    }

    public static void waitFor(@NonNull String message, @NonNull BooleanSupplier condition) {
        waitFor(message, condition, null /* onFailure */);
    }

    public static void waitFor(@NonNull String message, @NonNull BooleanSupplier condition,
            @Nullable Consumer<Object> onFailure) {
        Condition.waitFor(new Condition<>(message, condition)
                .setRetryIntervalMs(500)
                .setRetryLimit(20)
                .setOnFailure(onFailure));
    }

    /**
     * Retrieves the current states of all biometric sensor services (e.g. FingerprintService,
     * FaceService, etc).
     *
     * Note that the states are retrieved from BiometricService, instead of individual services.
     * This is because 1) BiometricService is the source of truth for all public API-facing things,
     * and 2) This to include other information, such as UI states, etc as well.
     */
    @NonNull
    public static BiometricServiceState getBiometricServiceCurrentState() throws Exception {
        final byte[] dump = Utils.executeShellCommand(DUMPSYS_BIOMETRIC);
        final BiometricServiceStateProto proto = BiometricServiceStateProto.parseFrom(dump);
        return BiometricServiceState.parseFrom(proto);
    }

    /**
     * Runs a shell command, similar to running "adb shell ..." from the command line.
     * @param cmd A command, without the preceding "adb shell" portion. For example,
     *            passing in "dumpsys fingerprint" would be the equivalent of running
     *            "adb shell dumpsys fingerprint" from the command line.
     * @return The result of the command.
     */
    public static byte[] executeShellCommand(String cmd) {
        Log.d(TAG, "execute: " + cmd);
        try {
            ParcelFileDescriptor pfd = getInstrumentation().getUiAutomation()
                    .executeShellCommand(cmd);
            byte[] buf = new byte[512];
            int bytesRead;
            FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
            ByteArrayOutputStream stdout = new ByteArrayOutputStream();
            while ((bytesRead = fis.read(buf)) != -1) {
                stdout.write(buf, 0, bytesRead);
            }
            fis.close();
            return stdout.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void forceStopActivity(ComponentName componentName) {
        executeShellCommand("am force-stop " + componentName.getPackageName()
                + " " + componentName.getShortClassName().replaceAll("\\.", ""));
    }

    public static int numberOfSpecifiedOperations(@NonNull BiometricServiceState state,
            int sensorId, int operation) {
        int count = 0;
        final List<Integer> recentOps = state.mSensorStates.sensorStates.get(sensorId)
                .getSchedulerState().getRecentOperations();
        for (Integer i : recentOps) {
            if (i == operation) {
                count++;
            }
        }
        return count;
    }

    public static void createTimeBoundSecretKey_deprecated(String keyName, boolean useStrongBox)
            throws Exception {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyGenerator keyGenerator = KeyGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

        // Set the alias of the entry in Android KeyStore where the key will appear
        // and the constrains (purposes) in the constructor of the Builder
        keyGenerator.init(new KeyGenParameterSpec.Builder(keyName,
                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setIsStrongBoxBacked(useStrongBox)
                .setUserAuthenticationValidityDurationSeconds(5 /* seconds */)
                .build());
        keyGenerator.generateKey();
    }

    static void createTimeBoundSecretKey(String keyName, int authTypes, boolean useStrongBox)
            throws Exception {
        KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
        keyStore.load(null);
        KeyGenerator keyGenerator = KeyGenerator.getInstance(
                KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");

        // Set the alias of the entry in Android KeyStore where the key will appear
        // and the constrains (purposes) in the constructor of the Builder
        keyGenerator.init(new KeyGenParameterSpec.Builder(keyName,
                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setUserAuthenticationRequired(true)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setIsStrongBoxBacked(useStrongBox)
                .setUserAuthenticationParameters(1 /* seconds */, authTypes)
                .build());
        keyGenerator.generateKey();
    }

    public static void generateBiometricBoundKey(String keyName, boolean useStrongBox)
            throws Exception {
        final KeyStore keystore = KeyStore.getInstance(KEYSTORE_PROVIDER);
        keystore.load(null);
        KeyGenParameterSpec.Builder builder = new KeyGenParameterSpec.Builder(
                keyName,
                KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
                .setBlockModes(KeyProperties.BLOCK_MODE_CBC)
                .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7)
                .setUserAuthenticationRequired(true)
                .setInvalidatedByBiometricEnrollment(true)
                .setIsStrongBoxBacked(useStrongBox)
                .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG);

        KeyGenerator keyGenerator = KeyGenerator
                .getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
        keyGenerator.init(builder.build());

        // Generates and stores the key in Android KeyStore under the keystoreAlias (keyName)
        // specified in the builder.
        keyGenerator.generateKey();
    }

    public static BiometricPrompt.CryptoObject initializeCryptoObject(String keyName)
            throws Exception {
        final KeyStore keystore = KeyStore.getInstance(KEYSTORE_PROVIDER);
        keystore.load(null);
        final SecretKey secretKey = (SecretKey) keystore.getKey(
                keyName, null /* password */);
        final Cipher cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/"
                + KeyProperties.BLOCK_MODE_CBC + "/"
                + KeyProperties.ENCRYPTION_PADDING_PKCS7);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        final BiometricPrompt.CryptoObject cryptoObject =
                new BiometricPrompt.CryptoObject(cipher);
        return cryptoObject;
    }

    public static boolean isPublicAuthenticatorConstant(int authenticator) {
        switch (authenticator) {
            case BiometricManager.Authenticators.BIOMETRIC_STRONG:
            case BiometricManager.Authenticators.BIOMETRIC_WEAK:
            case BiometricManager.Authenticators.DEVICE_CREDENTIAL:
                return true;
            default:
                return false;
        }
    }

    public static int testApiStrengthToAuthenticatorStrength(int testApiStrength) {
        switch (testApiStrength) {
            case SensorProperties.STRENGTH_STRONG:
                return BiometricManager.Authenticators.BIOMETRIC_STRONG;
            case SensorProperties.STRENGTH_WEAK:
                return BiometricManager.Authenticators.BIOMETRIC_WEAK;
            default:
                throw new IllegalArgumentException("Unable to convert testApiStrength: "
                        + testApiStrength);
        }
    }

    public static boolean isFirstApiLevel29orGreater() {
        int firstApiLevel = SystemProperties.getInt("ro.product.first_api_level", 0);
        if (firstApiLevel >= 29) {
            return true;
        }
        return false;
    }
}
