/**
 * Copyright (C) 2014 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.fingerprint;

import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.MessageQueue;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Slog;

import com.android.server.SystemService;

import android.hardware.fingerprint.FingerprintUtils;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceReceiver;

import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.USE_FINGERPRINT;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * A service to manage multiple clients that want to access the fingerprint HAL API.
 * The service is responsible for maintaining a list of clients and dispatching all
 * fingerprint -related events.
 *
 * @hide
 */
public class FingerprintService extends SystemService {
    private static final String TAG = "FingerprintService";
    private static final boolean DEBUG = true;
    private ClientMonitor mAuthClient = null;
    private ClientMonitor mEnrollClient = null;
    private ClientMonitor mRemoveClient = null;

    private static final int MSG_NOTIFY = 10;

    private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute

    // Message types. Used internally to dispatch messages to the correct callback.
    // Must agree with the list in fingerprint.h
    private static final int FINGERPRINT_ERROR = -1;
    private static final int FINGERPRINT_ACQUIRED = 1;
    private static final int FINGERPRINT_TEMPLATE_ENROLLING = 3;
    private static final int FINGERPRINT_TEMPLATE_REMOVED = 4;
    private static final int FINGERPRINT_AUTHENTICATED = 5;

    Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case MSG_NOTIFY:
                    FpHalMsg m = (FpHalMsg) msg.obj;
                    handleNotify(m.type, m.arg1, m.arg2, m.arg3);
                    break;

                default:
                    Slog.w(TAG, "Unknown message:" + msg.what);
            }
        }
    };
    private Context mContext;
    private int mHalDeviceId;
    private int mFailedAttempts;
    private final Runnable mLockoutReset = new Runnable() {
        @Override
        public void run() {
            resetFailedAttempts();
        }
    };

    private static final int STATE_IDLE = 0;
    private static final int STATE_AUTHENTICATING = 1;
    private static final int STATE_ENROLLING = 2;
    private static final int STATE_REMOVING = 3;
    private static final long MS_PER_SEC = 1000;
    private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
    private static final int MAX_FAILED_ATTEMPTS = 5;

    public FingerprintService(Context context) {
        super(context);
        mContext = context;
        nativeInit(Looper.getMainLooper().getQueue(), this);
    }

    // TODO: Move these into separate process
    // JNI methods to communicate from FingerprintService to HAL
    static native int nativeEnroll(byte [] token, int groupId, int timeout);
    static native long nativePreEnroll();
    static native int nativeStopEnrollment();
    static native int nativeAuthenticate(long sessionId, int groupId);
    static native int nativeStopAuthentication();
    static native int nativeRemove(int fingerId, int groupId);
    static native int nativeOpenHal();
    static native int nativeCloseHal();
    static native void nativeInit(MessageQueue queue, FingerprintService service);

    static final class FpHalMsg {
        int type; // Type of the message. One of the constants in fingerprint.h
        int arg1; // optional arguments
        int arg2;
        int arg3;

        FpHalMsg(int type, int arg1, int arg2, int arg3) {
            this.type = type;
            this.arg1 = arg1;
            this.arg2 = arg2;
            this.arg3 = arg3;
        }
    }

    /**
     * Called from JNI to communicate messages from fingerprint HAL.
     */
    void notify(int type, int arg1, int arg2, int arg3) {
        mHandler.obtainMessage(MSG_NOTIFY, new FpHalMsg(type, arg1, arg2, arg3)).sendToTarget();
    }

    void handleNotify(int type, int arg1, int arg2, int arg3) {
        Slog.v(TAG, "handleNotify(type=" + type + ", arg1=" + arg1 + ", arg2=" + arg2 + ")"
                    + ", mAuthClients = " + mAuthClient + ", mEnrollClient = " + mEnrollClient);
        if (mEnrollClient != null) {
            final IBinder token = mEnrollClient.token;
            if (doNotify(mEnrollClient, type, arg1, arg2, arg3)) {
                stopEnrollment(token);
            }
        }
        if (mAuthClient != null) {
            final IBinder token = mAuthClient.token;
            if (doNotify(mAuthClient, type, arg1, arg2, arg3)) {
                stopAuthentication(token);
            }
        }
        if (mRemoveClient != null) {
            if (doNotify(mRemoveClient, type, arg1, arg2, arg3)) {
                removeClient(mRemoveClient);
            }
        }
    }

    // Returns true if the operation is done, i.e. authentication completed
    boolean doNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
        ContentResolver contentResolver = mContext.getContentResolver();
        boolean operationCompleted = false;
        switch (type) {
            case FINGERPRINT_ERROR:
                {
                    final int error = arg1;
                    clientMonitor.sendError(error);
                    removeClient(clientMonitor);
                    operationCompleted = true; // any error means the operation is done
                }
                break;
            case FINGERPRINT_ACQUIRED:
                clientMonitor.sendAcquired(arg1 /* acquireInfo */);
                break;
            case FINGERPRINT_AUTHENTICATED:
                {
                    final int fpId = arg1;
                    final int groupId = arg2;
                    clientMonitor.sendAuthenticated(fpId, groupId);
                    if (fpId == 0) {
                        if (clientMonitor == mAuthClient) {
                            operationCompleted = handleFailedAttempt(clientMonitor);
                        }
                    } else {
                        mLockoutReset.run(); // a valid fingerprint resets lockout
                    }
                }
                break;
            case FINGERPRINT_TEMPLATE_ENROLLING:
                {
                    final int fpId = arg1;
                    final int groupId = arg2;
                    final int remaining = arg3;
                    clientMonitor.sendEnrollResult(fpId, groupId, remaining);
                    if (remaining == 0) {
                        addTemplateForUser(clientMonitor, contentResolver, fpId);
                        operationCompleted = true; // enroll completed
                    }
                }
                break;
            case FINGERPRINT_TEMPLATE_REMOVED:
                {
                    final int fingerId = arg1;
                    final int groupId = arg2;
                    removeTemplateForUser(clientMonitor, contentResolver, fingerId);
                    if (fingerId == 0) {
                        operationCompleted = true; // remove completed
                    } else {
                        clientMonitor.sendRemoved(fingerId, groupId);
                    }
                }
                break;
        }
        return operationCompleted;
    }

    private void removeClient(ClientMonitor clientMonitor) {
        if (clientMonitor == null) return;
        clientMonitor.destroy();
        if (clientMonitor == mAuthClient) {
            mAuthClient = null;
        } else if (clientMonitor == mEnrollClient) {
            mEnrollClient = null;
        } else if (clientMonitor == mRemoveClient) {
            mRemoveClient = null;
        }
    }

    private boolean inLockoutMode() {
        return mFailedAttempts > MAX_FAILED_ATTEMPTS;
    }

    private void resetFailedAttempts() {
        if (DEBUG) Slog.v(TAG, "Reset fingerprint lockout");
        mFailedAttempts = 0;
    }

    private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
        mFailedAttempts++;
        if (mFailedAttempts > MAX_FAILED_ATTEMPTS) {
            // Failing multiple times will continue to push out the lockout time.
            mHandler.removeCallbacks(mLockoutReset);
            mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS);
            if (clientMonitor != null
                    && !clientMonitor.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
                Slog.w(TAG, "Cannot send lockout message to client");
            }
            return true;
        }
        return false;
    }

    private void removeTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
            final int fingerId) {
        FingerprintUtils.removeFingerprintIdForUser(fingerId, contentResolver,
                clientMonitor.userId);
    }

    private void addTemplateForUser(ClientMonitor clientMonitor, ContentResolver contentResolver,
            final int fingerId) {
        FingerprintUtils.addFingerprintIdForUser(contentResolver, fingerId,
                clientMonitor.userId);
    }

    void startEnrollment(IBinder token, byte[] cryptoToken, int groupId,
            IFingerprintServiceReceiver receiver, int flags) {
        stopPendingOperations();
        mEnrollClient = new ClientMonitor(token, receiver, groupId);
        final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
        final int result = nativeEnroll(cryptoToken, groupId, timeout);
        if (result != 0) {
            Slog.w(TAG, "startEnroll failed, result=" + result);
        }
    }

    public long startPreEnroll(IBinder token) {
        return nativePreEnroll();
    }

    private void stopPendingOperations() {
        if (mEnrollClient != null) {
            stopEnrollment(mEnrollClient.token);
        }
        if (mAuthClient != null) {
            stopAuthentication(mAuthClient.token);
        }
        // mRemoveClient is allowed to continue
    }

    void stopEnrollment(IBinder token) {
        final ClientMonitor client = mEnrollClient;
        if (client == null || client.token != token) return;
        int result = nativeStopEnrollment();
        client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
        removeClient(mEnrollClient);
        if (result != 0) {
            Slog.w(TAG, "startEnrollCancel failed, result=" + result);
        }
    }

    void startAuthentication(IBinder token, long opId, int groupId,
            IFingerprintServiceReceiver receiver, int flags) {
        stopPendingOperations();
        mAuthClient = new ClientMonitor(token, receiver, groupId);
        if (inLockoutMode()) {
            Slog.v(TAG, "In lockout mode; disallowing authentication");
            if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
                Slog.w(TAG, "Cannot send timeout message to client");
            }
            mAuthClient = null;
            return;
        }
        final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
        final int result = nativeAuthenticate(opId, groupId);
        if (result != 0) {
            Slog.w(TAG, "startAuthentication failed, result=" + result);
        }
    }

    void stopAuthentication(IBinder token) {
        final ClientMonitor client = mAuthClient;
        if (client == null || client.token != token) return;
        int result = nativeStopAuthentication();
        client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
        removeClient(mAuthClient);
        if (result != 0) {
            Slog.w(TAG, "stopAuthentication failed, result=" + result);
        }
    }

    void startRemove(IBinder token, int fingerId, int userId,
            IFingerprintServiceReceiver receiver) {
        mRemoveClient = new ClientMonitor(token, receiver, userId);
        // The fingerprint template ids will be removed when we get confirmation from the HAL
        final int result = nativeRemove(fingerId, userId);
        if (result != 0) {
            Slog.w(TAG, "startRemove with id = " + fingerId + " failed with result=" + result);
        }
    }

    public List<Fingerprint> getEnrolledFingerprints(int groupId) {
        ContentResolver resolver = mContext.getContentResolver();
        int[] ids = FingerprintUtils.getFingerprintIdsForUser(resolver, groupId);
        List<Fingerprint> result = new ArrayList<Fingerprint>();
        for (int i = 0; i < ids.length; i++) {
            // TODO: persist names in Settings
            CharSequence name = "Finger" + ids[i];
            final int group = 0; // TODO
            final int fingerId = ids[i];
            final long deviceId = 0; // TODO
            Fingerprint item = new Fingerprint(name, 0, ids[i], 0);
            result.add(item);
        }
        return result;
    }

    public boolean hasEnrolledFingerprints(int groupId) {
        ContentResolver resolver = mContext.getContentResolver();
        return FingerprintUtils.getFingerprintIdsForUser(resolver, groupId).length > 0;
    }

    void checkPermission(String permission) {
        getContext().enforceCallingOrSelfPermission(permission,
                "Must have " + permission + " permission.");
    }

    private class ClientMonitor implements IBinder.DeathRecipient {
        IBinder token;
        WeakReference<IFingerprintServiceReceiver> receiver;
        int userId;

        public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
            this.token = token;
            this.receiver = new WeakReference<IFingerprintServiceReceiver>(receiver);
            this.userId = userId;
            try {
                token.linkToDeath(this, 0);
            } catch (RemoteException e) {
                Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
            }
        }

        public void destroy() {
            if (token != null) {
                token.unlinkToDeath(this, 0);
                token = null;
            }
            receiver = null;
        }

        public void binderDied() {
            token = null;
            removeClient(this);
        }

        protected void finalize() throws Throwable {
            try {
                if (token != null) {
                    if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token);
                    removeClient(this);
                }
            } finally {
                super.finalize();
            }
        }

        private boolean sendRemoved(int fingerId, int groupId) {
            IFingerprintServiceReceiver rx = receiver.get();
            if (rx != null) {
                try {
                    rx.onRemoved(mHalDeviceId, fingerId, groupId);
                    return true;
                } catch (RemoteException e) {
                    if (DEBUG) Slog.v(TAG, "Failed to invoke sendRemoved:", e);
                }
            }
            removeClient(this);
            return false;
        }

        private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
            IFingerprintServiceReceiver rx = receiver.get();
            if (rx != null) {
                try {
                    rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
                    return true;
                } catch (RemoteException e) {
                    if (DEBUG) Slog.v(TAG, "Failed to invoke sendEnrollResult:", e);
                }
            }
            removeClient(this);
            return false;
        }

        private boolean sendAuthenticated(int fpId, int groupId) {
            IFingerprintServiceReceiver rx = receiver.get();
            if (rx != null) {
                try {
                    rx.onAuthenticated(mHalDeviceId, fpId, groupId);
                    return true;
                } catch (RemoteException e) {
                    if (DEBUG) Slog.v(TAG, "Failed to invoke sendProcessed:", e);
                }
            }
            removeClient(this);
            return false;
        }

        private boolean sendAcquired(int acquiredInfo) {
            IFingerprintServiceReceiver rx = receiver.get();
            if (rx != null) {
                try {
                    rx.onAcquired(mHalDeviceId, acquiredInfo);
                    return true;
                } catch (RemoteException e) {
                    if (DEBUG) Slog.v(TAG, "Failed to invoke sendAcquired:", e);
                }
            }
            removeClient(this);
            return false;
        }

        private boolean sendError(int error) {
            IFingerprintServiceReceiver rx = receiver.get();
            if (rx != null) {
                try {
                    rx.onError(mHalDeviceId, error);
                    return true;
                } catch (RemoteException e) {
                    if (DEBUG) Slog.v(TAG, "Failed to invoke sendError:", e);
                }
            }
            removeClient(this);
            return false;
        }
    }

    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
        @Override
        public long preEnroll(IBinder token) {
            checkPermission(MANAGE_FINGERPRINT);
            return startPreEnroll(token);
        }

        @Override
        // Binder call
        public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId,
                final IFingerprintServiceReceiver receiver, final int flags) {
            checkPermission(MANAGE_FINGERPRINT);
            final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startEnrollment(token, cryptoClone, groupId, receiver, flags);
                }
            });
        }

        @Override
        // Binder call
        public void cancelEnrollment(final IBinder token) {
            checkPermission(MANAGE_FINGERPRINT);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    stopEnrollment(token);
                }
            });
        }

        @Override
        // Binder call
        public void authenticate(final IBinder token, final long opId, final int groupId,
                final IFingerprintServiceReceiver receiver, final int flags) {
            checkPermission(USE_FINGERPRINT);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startAuthentication(token, opId, groupId, receiver, flags);
                }
            });
        }

        @Override

        // Binder call
        public void cancelAuthentication(final IBinder token) {
            checkPermission(USE_FINGERPRINT);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    stopAuthentication(token);
                }
            });
        }

        @Override
        // Binder call
        public void remove(final IBinder token, final int fingerId, final int groupId,
                final IFingerprintServiceReceiver receiver) {
            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    startRemove(token, fingerId, groupId, receiver);
                }
            });

        }

        @Override
        // Binder call
        public boolean isHardwareDetected(long deviceId) {
            checkPermission(USE_FINGERPRINT);
            return mHalDeviceId != 0; // TODO
        }

        @Override
        // Binder call
        public void rename(final int fingerId, final int groupId, final String name) {
            checkPermission(MANAGE_FINGERPRINT);
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Slog.w(TAG, "rename id=" + fingerId + ",gid=" + groupId + ",name=" + name);
                }
            });
        }

        @Override
        // Binder call
        public List<Fingerprint> getEnrolledFingerprints(int groupId) {
            checkPermission(USE_FINGERPRINT);
            return FingerprintService.this.getEnrolledFingerprints(groupId);
        }

        @Override
        // Binder call
        public boolean hasEnrolledFingerprints(int groupId) {
            checkPermission(USE_FINGERPRINT);
            return FingerprintService.this.hasEnrolledFingerprints(groupId);
        }
    }

    @Override
    public void onStart() {
        publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
        mHalDeviceId = nativeOpenHal();
        if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
    }

}
