/*
 * 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 com.android.server.biometrics.sensors.fingerprint.hidl;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.trust.TrustManager;
import android.content.ContentResolver;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseBooleanArray;

import com.android.internal.R;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.LockoutResetDispatcher;
import com.android.server.biometrics.sensors.fingerprint.FingerprintStateCallback;
import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * A mockable/testable provider of the {@link android.hardware.biometrics.fingerprint.V2_3} HIDL
 * interface. This class is intended simulate UDFPS logic for devices that do not have an actual
 * fingerprint@2.3 HAL (where UDFPS starts to become supported)
 *
 * UDFPS "accept" can only happen within a set amount of time after a sensor authentication. This is
 * specified by {@link MockHalResultController#AUTH_VALIDITY_MS}. Touches after this duration will
 * be treated as "reject".
 *
 * This class provides framework logic to emulate, for testing only, the UDFPS functionalies below:
 *
 * 1) IF either A) the caller is keyguard, and the device is not in a trusted state (authenticated
 *    via biometric sensor or unlocked with a trust agent {@see android.app.trust.TrustManager}, OR
 *    B) the caller is not keyguard, and regardless of trusted state, AND (following applies to both
 *    (A) and (B) above) {@link FingerprintManager#onFingerDown(int, int, float, float)} is
 *    received, this class will respond with {@link AuthenticationCallback#onAuthenticationFailed()}
 *    after a tunable flat_time + variance_time.
 *
 *    In the case above (1), callers must not receive a successful authentication event here because
 *    the sensor has not actually been authenticated.
 *
 * 2) IF A) the caller is keyguard and the device is not in a trusted state, OR B) the caller is not
 *    keyguard and regardless of trusted state, AND (following applies to both (A) and (B)) the
 *    sensor is touched and the fingerprint is accepted by the HAL, and then
 *    {@link FingerprintManager#onFingerDown(int, int, float, float)} is received, this class will
 *    respond with {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)}
 *    after a tunable flat_time + variance_time. Note that the authentication callback from the
 *    sensor is held until {@link FingerprintManager#onFingerDown(int, int, float, float)} is
 *    invoked.
 *
 *    In the case above (2), callers can receive a successful authentication callback because the
 *    real sensor was authenticated. Note that even though the real sensor was touched, keyguard
 *    fingerprint authentication does not put keyguard into a trusted state because the
 *    authentication callback is held until onFingerDown was invoked. This allows callers such as
 *    keyguard to simulate a realistic path.
 *
 * 3) IF the caller is keyguard AND the device in a trusted state and then
 *    {@link FingerprintManager#onFingerDown(int, int, float, float)} is received, this class will
 *    respond with {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)}
 *    after a tunable flat_time + variance time.
 *
 *    In the case above (3), since the device is already unlockable via trust agent, it's fine to
 *    simulate the successful auth path. Non-keyguard clients will fall into either (1) or (2)
 *    above.
 *
 *  This class currently does not simulate false rejection. Conversely, this class relies on the
 *  real hardware sensor so does not affect false acceptance.
 */
@SuppressWarnings("deprecation")
public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManager.TrustListener {

    private static final String TAG = "Fingerprint21UdfpsMock";

    // Secure setting integer. If true, the system will load this class to enable udfps testing.
    public static final String CONFIG_ENABLE_TEST_UDFPS =
            "com.android.server.biometrics.sensors.fingerprint.test_udfps.enable";
    // Secure setting integer. A fixed duration intended to simulate something like the duration
    // required for image capture.
    private static final String CONFIG_AUTH_DELAY_PT1 =
            "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_pt1";
    // Secure setting integer. A fixed duration intended to simulate something like the duration
    // required for template matching to complete.
    private static final String CONFIG_AUTH_DELAY_PT2 =
            "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_pt2";
    // Secure setting integer. A random value between [-randomness, randomness] will be added to the
    // capture delay above for each accept/reject.
    private static final String CONFIG_AUTH_DELAY_RANDOMNESS =
            "com.android.server.biometrics.sensors.fingerprint.test_udfps.auth_delay_randomness";

    private static final int DEFAULT_AUTH_DELAY_PT1_MS = 300;
    private static final int DEFAULT_AUTH_DELAY_PT2_MS = 400;
    private static final int DEFAULT_AUTH_DELAY_RANDOMNESS_MS = 100;

    @NonNull private final TestableBiometricScheduler mScheduler;
    @NonNull private final Handler mHandler;
    @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties;
    @NonNull private final MockHalResultController mMockHalResultController;
    @NonNull private final TrustManager mTrustManager;
    @NonNull private final SparseBooleanArray mUserHasTrust;
    @NonNull private final Random mRandom;
    @NonNull private final FakeRejectRunnable mFakeRejectRunnable;
    @NonNull private final FakeAcceptRunnable mFakeAcceptRunnable;
    @NonNull private final RestartAuthRunnable mRestartAuthRunnable;

    private static class TestableBiometricScheduler extends BiometricScheduler {
        @NonNull private Fingerprint21UdfpsMock mFingerprint21;

        TestableBiometricScheduler(@NonNull String tag, @NonNull Handler handler,
                @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
            super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER, gestureAvailabilityDispatcher);
        }

        void init(@NonNull Fingerprint21UdfpsMock fingerprint21) {
            mFingerprint21 = fingerprint21;
        }
    }

    /**
     * All of the mocking/testing should happen in here. This way we don't need to modify the
     * {@link BaseClientMonitor} implementations and can run the
     * real path there.
     */
    private static class MockHalResultController extends HalResultController {

        // Duration for which a sensor authentication can be treated as UDFPS success.
        private static final int AUTH_VALIDITY_MS = 10 * 1000; // 10 seconds

        static class LastAuthArgs {
            @NonNull final AuthenticationConsumer lastAuthenticatedClient;
            final long deviceId;
            final int fingerId;
            final int groupId;
            @Nullable final ArrayList<Byte> token;

            LastAuthArgs(@NonNull AuthenticationConsumer authenticationConsumer, long deviceId,
                    int fingerId, int groupId, @Nullable ArrayList<Byte> token) {
                lastAuthenticatedClient = authenticationConsumer;
                this.deviceId = deviceId;
                this.fingerId = fingerId;
                this.groupId = groupId;
                if (token == null) {
                    this.token = null;
                } else {
                    // Store a copy so the owner can be GC'd
                    this.token = new ArrayList<>(token);
                }
            }
        }

        // Initialized after the constructor, but before it's ever used.
        @NonNull private RestartAuthRunnable mRestartAuthRunnable;
        @NonNull private Fingerprint21UdfpsMock mFingerprint21;
        @Nullable private LastAuthArgs mLastAuthArgs;

        MockHalResultController(int sensorId, @NonNull Context context, @NonNull Handler handler,
                @NonNull BiometricScheduler scheduler) {
            super(sensorId, context, handler, scheduler);
        }

        void init(@NonNull RestartAuthRunnable restartAuthRunnable,
                @NonNull Fingerprint21UdfpsMock fingerprint21) {
            mRestartAuthRunnable = restartAuthRunnable;
            mFingerprint21 = fingerprint21;
        }

        @Nullable AuthenticationConsumer getLastAuthenticatedClient() {
            return mLastAuthArgs != null ? mLastAuthArgs.lastAuthenticatedClient : null;
        }

        /**
         * Intercepts the HAL authentication and holds it until the UDFPS simulation decides
         * that authentication finished.
         */
        @Override
        public void onAuthenticated(long deviceId, int fingerId, int groupId,
                ArrayList<Byte> token) {
            mHandler.post(() -> {
                final BaseClientMonitor client = mScheduler.getCurrentClient();
                if (!(client instanceof AuthenticationConsumer)) {
                    Slog.e(TAG, "Non authentication consumer: " + client);
                    return;
                }

                final boolean accepted = fingerId != 0;
                if (accepted) {
                    mFingerprint21.setDebugMessage("Finger accepted");
                } else {
                    mFingerprint21.setDebugMessage("Finger rejected");
                }

                final AuthenticationConsumer authenticationConsumer =
                        (AuthenticationConsumer) client;
                mLastAuthArgs = new LastAuthArgs(authenticationConsumer, deviceId, fingerId,
                        groupId, token);

                // Remove any existing restart runnbables since auth just started, and put a new
                // one on the queue.
                mHandler.removeCallbacks(mRestartAuthRunnable);
                mRestartAuthRunnable.setLastAuthReference(authenticationConsumer);
                mHandler.postDelayed(mRestartAuthRunnable, AUTH_VALIDITY_MS);
            });
        }

        /**
         * Calls through to the real interface and notifies clients of accept/reject.
         */
        void sendAuthenticated(long deviceId, int fingerId, int groupId,
                ArrayList<Byte> token) {
            Slog.d(TAG, "sendAuthenticated: " + (fingerId != 0));
            mFingerprint21.setDebugMessage("Udfps match: " + (fingerId != 0));
            super.onAuthenticated(deviceId, fingerId, groupId, token);
        }
    }

    public static Fingerprint21UdfpsMock newInstance(@NonNull Context context,
            @NonNull FingerprintStateCallback fingerprintStateCallback,
            @NonNull FingerprintSensorPropertiesInternal sensorProps,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
        Slog.d(TAG, "Creating Fingerprint23Mock!");

        final Handler handler = new Handler(Looper.getMainLooper());
        final TestableBiometricScheduler scheduler =
                new TestableBiometricScheduler(TAG, handler, gestureAvailabilityDispatcher);
        final MockHalResultController controller =
                new MockHalResultController(sensorProps.sensorId, context, handler, scheduler);
        return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler,
                handler, lockoutResetDispatcher, controller);
    }

    private static abstract class FakeFingerRunnable implements Runnable {
        private long mFingerDownTime;
        private int mCaptureDuration;

        /**
         * @param fingerDownTime System time when onFingerDown occurred
         * @param captureDuration Duration that the finger needs to be down for
         */
        void setSimulationTime(long fingerDownTime, int captureDuration) {
            mFingerDownTime = fingerDownTime;
            mCaptureDuration = captureDuration;
        }

        @SuppressWarnings("BooleanMethodIsAlwaysInverted")
        boolean isImageCaptureComplete() {
            return System.currentTimeMillis() - mFingerDownTime > mCaptureDuration;
        }
    }

    private final class FakeRejectRunnable extends FakeFingerRunnable {
        @Override
        public void run() {
            mMockHalResultController.sendAuthenticated(0, 0, 0, null);
        }
    }

    private final class FakeAcceptRunnable extends FakeFingerRunnable {
        @Override
        public void run() {
            if (mMockHalResultController.mLastAuthArgs == null) {
                // This can happen if the user has trust agents enabled, which make lockscreen
                // dismissable. Send a fake non-zero (accept) finger.
                Slog.d(TAG, "Sending fake finger");
                mMockHalResultController.sendAuthenticated(1 /* deviceId */,
                        1 /* fingerId */, 1 /* groupId */, null /* token */);
            } else {
                mMockHalResultController.sendAuthenticated(
                        mMockHalResultController.mLastAuthArgs.deviceId,
                        mMockHalResultController.mLastAuthArgs.fingerId,
                        mMockHalResultController.mLastAuthArgs.groupId,
                        mMockHalResultController.mLastAuthArgs.token);
            }
        }
    }

    /**
     * The fingerprint HAL allows multiple (5) fingerprint attempts per HIDL invocation of the
     * authenticate method. However, valid fingerprint authentications are invalidated after
     * {@link MockHalResultController#AUTH_VALIDITY_MS}, meaning UDFPS touches will be reported as
     * rejects if touched after that duration. However, since a valid fingerprint was detected, the
     * HAL and FingerprintService will not look for subsequent fingerprints.
     *
     * In order to keep the FingerprintManager API consistent (that multiple fingerprint attempts
     * are allowed per auth lifecycle), we internally cancel and restart authentication so that the
     * sensor is responsive again.
     */
    private static final class RestartAuthRunnable implements Runnable {
        @NonNull private final Fingerprint21UdfpsMock mFingerprint21;
        @NonNull private final TestableBiometricScheduler mScheduler;

        // Store a reference to the auth consumer that should be invalidated.
        private AuthenticationConsumer mLastAuthConsumer;

        RestartAuthRunnable(@NonNull Fingerprint21UdfpsMock fingerprint21,
                @NonNull TestableBiometricScheduler scheduler) {
            mFingerprint21 = fingerprint21;
            mScheduler = scheduler;
        }

        void setLastAuthReference(AuthenticationConsumer lastAuthConsumer) {
            mLastAuthConsumer = lastAuthConsumer;
        }

        @Override
        public void run() {
            final BaseClientMonitor client = mScheduler.getCurrentClient();

            // We don't care about FingerprintDetectClient, since accept/rejects are both OK. UDFPS
            // rejects will just simulate the path where non-enrolled fingers are presented.
            if (!(client instanceof FingerprintAuthenticationClient)) {
                Slog.e(TAG, "Non-FingerprintAuthenticationClient client: " + client);
                return;
            }

            // Perhaps the runnable is stale, or the user stopped/started auth manually. Do not
            // restart auth in this case.
            if (client != mLastAuthConsumer) {
                Slog.e(TAG, "Current client: " + client
                        + " does not match mLastAuthConsumer: " + mLastAuthConsumer);
                return;
            }

            Slog.d(TAG, "Restarting auth, current: " + client);
            mFingerprint21.setDebugMessage("Auth timed out");

            final FingerprintAuthenticationClient authClient =
                    (FingerprintAuthenticationClient) client;
            // Store the authClient parameters so it can be rescheduled
            final IBinder token = client.getToken();
            final long operationId = authClient.getOperationId();
            final int user = client.getTargetUserId();
            final int cookie = client.getCookie();
            final ClientMonitorCallbackConverter listener = client.getListener();
            final String opPackageName = client.getOwnerString();
            final boolean restricted = authClient.isRestricted();
            final int statsClient = client.getStatsClient();
            final boolean isKeyguard = authClient.isKeyguard();

            // Don't actually send cancel() to the HAL, since successful auth already finishes
            // HAL authenticate() lifecycle. Just
            mScheduler.getInternalCallback().onClientFinished(client, true /* success */);

            // Schedule this only after we invoke onClientFinished for the previous client, so that
            // internal preemption logic is not run.
            mFingerprint21.scheduleAuthenticate(mFingerprint21.mSensorProperties.sensorId, token,
                    operationId, user, cookie, listener, opPackageName, restricted, statsClient,
                    isKeyguard);
        }
    }

    private Fingerprint21UdfpsMock(@NonNull Context context,
            @NonNull FingerprintStateCallback fingerprintStateCallback,
            @NonNull FingerprintSensorPropertiesInternal sensorProps,
            @NonNull TestableBiometricScheduler scheduler,
            @NonNull Handler handler,
            @NonNull LockoutResetDispatcher lockoutResetDispatcher,
            @NonNull MockHalResultController controller) {
        super(context, fingerprintStateCallback, sensorProps, scheduler, handler,
                lockoutResetDispatcher, controller);
        mScheduler = scheduler;
        mScheduler.init(this);
        mHandler = handler;
        // resetLockout is controlled by the framework, so hardwareAuthToken is not required
        final boolean resetLockoutRequiresHardwareAuthToken = false;
        final int maxTemplatesAllowed = mContext.getResources()
                .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
        mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId,
                sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo,
                FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
                resetLockoutRequiresHardwareAuthToken, sensorProps.getAllLocations());
        mMockHalResultController = controller;
        mUserHasTrust = new SparseBooleanArray();
        mTrustManager = context.getSystemService(TrustManager.class);
        mTrustManager.registerTrustListener(this);
        mRandom = new Random();
        mFakeRejectRunnable = new FakeRejectRunnable();
        mFakeAcceptRunnable = new FakeAcceptRunnable();
        mRestartAuthRunnable = new RestartAuthRunnable(this, mScheduler);

        // We can't initialize this during MockHalresultController's constructor due to a circular
        // dependency.
        mMockHalResultController.init(mRestartAuthRunnable, this);
    }

    @Override
    public void onTrustChanged(boolean enabled, int userId, int flags) {
        mUserHasTrust.put(userId, enabled);
    }

    @Override
    public void onTrustManagedChanged(boolean enabled, int userId) {

    }

    @Override
    public void onTrustError(CharSequence message) {

    }

    @Override
    @NonNull
    public List<FingerprintSensorPropertiesInternal> getSensorProperties() {
        final List<FingerprintSensorPropertiesInternal> properties = new ArrayList<>();
        properties.add(mSensorProperties);
        return properties;
    }

    @Override
    public void onPointerDown(int sensorId, int x, int y, float minor, float major) {
        mHandler.post(() -> {
            Slog.d(TAG, "onFingerDown");
            final AuthenticationConsumer lastAuthenticatedConsumer =
                    mMockHalResultController.getLastAuthenticatedClient();
            final BaseClientMonitor currentScheduledClient = mScheduler.getCurrentClient();

            if (currentScheduledClient == null) {
                Slog.d(TAG, "Not authenticating");
                return;
            }

            mHandler.removeCallbacks(mFakeRejectRunnable);
            mHandler.removeCallbacks(mFakeAcceptRunnable);

            // The sensor was authenticated, is still the currently scheduled client, and the
            // user touched the UDFPS affordance. Pretend that auth succeeded.
            final boolean authenticatedClientIsCurrent = lastAuthenticatedConsumer != null
                    && lastAuthenticatedConsumer == currentScheduledClient;
            // User is unlocked on keyguard via Trust Agent
            final boolean keyguardAndTrusted;
            if (currentScheduledClient instanceof FingerprintAuthenticationClient) {
                keyguardAndTrusted = ((FingerprintAuthenticationClient) currentScheduledClient)
                        .isKeyguard()
                        && mUserHasTrust.get(currentScheduledClient.getTargetUserId(), false);
            } else {
                keyguardAndTrusted = false;
            }

            final int captureDuration = getNewCaptureDuration();
            final int matchingDuration = getMatchingDuration();
            final int totalDuration = captureDuration + matchingDuration;
            setDebugMessage("Duration: " + totalDuration
                    + " (" + captureDuration + " + " + matchingDuration + ")");
            if (authenticatedClientIsCurrent || keyguardAndTrusted) {
                mFakeAcceptRunnable.setSimulationTime(System.currentTimeMillis(), captureDuration);
                mHandler.postDelayed(mFakeAcceptRunnable, totalDuration);
            } else if (currentScheduledClient instanceof AuthenticationConsumer) {
                // Something is authenticating but authentication has not succeeded yet. Pretend
                // that auth rejected.
                mFakeRejectRunnable.setSimulationTime(System.currentTimeMillis(), captureDuration);
                mHandler.postDelayed(mFakeRejectRunnable, totalDuration);
            }
        });
    }

    @Override
    public void onPointerUp(int sensorId) {
        mHandler.post(() -> {
            Slog.d(TAG, "onFingerUp");

            // Only one of these can be on the handler at any given time (see onFingerDown). If
            // image capture is not complete, send ACQUIRED_TOO_FAST and remove the runnable from
            // the handler. Image capture (onFingerDown) needs to happen again.
            if (mHandler.hasCallbacks(mFakeRejectRunnable)
                    && !mFakeRejectRunnable.isImageCaptureComplete()) {
                mHandler.removeCallbacks(mFakeRejectRunnable);
                mMockHalResultController.onAcquired(0 /* deviceId */,
                        FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST,
                        0 /* vendorCode */);
            } else if (mHandler.hasCallbacks(mFakeAcceptRunnable)
                    && !mFakeAcceptRunnable.isImageCaptureComplete()) {
                mHandler.removeCallbacks(mFakeAcceptRunnable);
                mMockHalResultController.onAcquired(0 /* deviceId */,
                        FingerprintManager.FINGERPRINT_ACQUIRED_TOO_FAST,
                        0 /* vendorCode */);
            }
        });
    }

    private int getNewCaptureDuration() {
        final ContentResolver contentResolver = mContext.getContentResolver();
        final int captureTime = Settings.Secure.getIntForUser(contentResolver,
                CONFIG_AUTH_DELAY_PT1,
                DEFAULT_AUTH_DELAY_PT1_MS,
                UserHandle.USER_CURRENT);
        final int randomDelayRange = Settings.Secure.getIntForUser(contentResolver,
                CONFIG_AUTH_DELAY_RANDOMNESS,
                DEFAULT_AUTH_DELAY_RANDOMNESS_MS,
                UserHandle.USER_CURRENT);
        final int randomDelay = mRandom.nextInt(randomDelayRange * 2) - randomDelayRange;

        // Must be at least 0
        return Math.max(captureTime + randomDelay, 0);
    }

    private int getMatchingDuration() {
        final int matchingTime = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                CONFIG_AUTH_DELAY_PT2,
                DEFAULT_AUTH_DELAY_PT2_MS,
                UserHandle.USER_CURRENT);

        // Must be at least 0
        return Math.max(matchingTime, 0);
    }

    private void setDebugMessage(String message) {
        try {
            final IUdfpsOverlayController controller = getUdfpsOverlayController();
            // Things can happen before SysUI loads and sets the controller.
            if (controller != null) {
                Slog.d(TAG, "setDebugMessage: " + message);
                controller.setDebugMessage(mSensorProperties.sensorId, message);
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "Remote exception when sending message: " + message, e);
        }
    }
}
