/*
 * 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.car;

import android.annotation.NonNull;
import android.car.Car;
import android.car.occupantawareness.IOccupantAwarenessEventCallback;
import android.car.occupantawareness.OccupantAwarenessDetection;
import android.car.occupantawareness.OccupantAwarenessDetection.VehicleOccupantRole;
import android.car.occupantawareness.SystemStatusEvent;
import android.car.occupantawareness.SystemStatusEvent.DetectionTypeFlags;
import android.content.Context;
import android.hardware.automotive.occupant_awareness.IOccupantAwareness;
import android.hardware.automotive.occupant_awareness.IOccupantAwarenessClientCallback;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.IndentingPrintWriter;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.lang.ref.WeakReference;

/**
 * A service that listens to an Occupant Awareness Detection system across a HAL boundary and
 * exposes the data to system clients in Android via a {@link
 * android.car.occupantawareness.OccupantAwarenessManager}.
 *
 * <p>The service exposes the following detections types:
 *
 * <h1>Presence Detection</h1>
 *
 * Detects whether a person is present for each seat location.
 *
 * <h1>Gaze Detection</h1>
 *
 * Detects where an occupant is looking and for how long they have been looking at the specified
 * target.
 *
 * <h1>Driver Monitoring</h1>
 *
 * Detects whether a driver is looking on or off-road and for how long they have been looking there.
 */
public class OccupantAwarenessService
        extends android.car.occupantawareness.IOccupantAwarenessManager.Stub
        implements CarServiceBase {
    private static final String TAG = CarLog.tagFor(OccupantAwarenessService.class);
    private static final boolean DBG = false;

    // HAL service identifier name.
    @VisibleForTesting
    static final String OAS_SERVICE_ID =
            "android.hardware.automotive.occupant_awareness.IOccupantAwareness/default";

    private final Object mLock = new Object();
    private final Context mContext;

    @GuardedBy("mLock")
    private IOccupantAwareness mOasHal;

    private final ChangeListenerToHalService mHalListener = new ChangeListenerToHalService(this);

    private class ChangeCallbackList extends RemoteCallbackList<IOccupantAwarenessEventCallback> {
        private final WeakReference<OccupantAwarenessService> mOasService;

        ChangeCallbackList(OccupantAwarenessService oasService) {
            mOasService = new WeakReference<>(oasService);
        }

        /** Handle callback death. */
        @Override
        public void onCallbackDied(IOccupantAwarenessEventCallback listener) {
            Slog.i(TAG, "binderDied: " + listener.asBinder());

            OccupantAwarenessService service = mOasService.get();
            if (service != null) {
                service.handleClientDisconnected();
            }
        }
    }

    @GuardedBy("mLock")
    private final ChangeCallbackList mListeners = new ChangeCallbackList(this);

    /** Creates an OccupantAwarenessService instance given a {@link Context}. */
    public OccupantAwarenessService(Context context) {
        mContext = context;
    }

    /** Creates an OccupantAwarenessService instance given a {@link Context}. */
    @VisibleForTesting
    OccupantAwarenessService(Context context, IOccupantAwareness oasInterface) {
        mContext = context;
        mOasHal = oasInterface;
    }

    @Override
    public void init() {
        logd("Initializing service");
        connectToHalServiceIfNotConnected();
    }

    @Override
    public void release() {
        logd("Will stop detection and disconnect listeners");
        stopDetectionGraph();
        mListeners.kill();
    }

    @Override
    public void dump(IndentingPrintWriter writer) {
        writer.println("*OccupantAwarenessService*");
        writer.println(
                String.format(
                        "%s to HAL service", mOasHal == null ? "NOT connected" : "Connected"));
        writer.println(
                String.format(
                        "%d change listeners subscribed.",
                        mListeners.getRegisteredCallbackCount()));
    }

    /** Attempts to connect to the HAL service if it is not already connected. */
    private void connectToHalServiceIfNotConnected() {
        logd("connectToHalServiceIfNotConnected()");

        synchronized (mLock) {
            // If already connected, nothing more needs to be done.
            if (mOasHal != null) {
                logd("Client is already connected, nothing more to do");
                return;
            }

            // Attempt to find the HAL service.
            logd("Attempting to connect to client at: " + OAS_SERVICE_ID);
            mOasHal =
                    android.hardware.automotive.occupant_awareness.IOccupantAwareness.Stub
                            .asInterface(ServiceManager.getService(OAS_SERVICE_ID));

            if (mOasHal == null) {
                Slog.e(TAG, "Failed to find OAS hal_service at: [" + OAS_SERVICE_ID + "]");
                return;
            }

            // Register for callbacks.
            try {
                mOasHal.setCallback(mHalListener);
            } catch (RemoteException e) {
                mOasHal = null;
                Slog.e(TAG, "Failed to set callback: " + e);
                return;
            }

            logd("Successfully connected to hal_service at: [" + OAS_SERVICE_ID + "]");
        }
    }

    /** Sends a message via the HAL to start the detection graph. */
    private void startDetectionGraph() {
        logd("Attempting to start detection graph");

        // Grab a copy of 'mOasHal' to avoid sitting on the lock longer than is necessary.
        IOccupantAwareness hal;
        synchronized (mLock) {
            hal = mOasHal;
        }

        if (hal != null) {
            try {
                hal.startDetection();
            } catch (RemoteException e) {
                Slog.e(TAG, "startDetection() HAL invocation failed: " + e, e);

                synchronized (mLock) {
                    mOasHal = null;
                }
            }
        } else {
            Slog.e(TAG, "No HAL is connected. Cannot request graph start");
        }
    }

    /** Sends a message via the HAL to stop the detection graph. */
    private void stopDetectionGraph() {
        logd("Attempting to stop detection graph.");

        // Grab a copy of 'mOasHal' to avoid sitting on the lock longer than is necessary.
        IOccupantAwareness hal;
        synchronized (mLock) {
            hal = mOasHal;
        }

        if (hal != null) {
            try {
                hal.stopDetection();
            } catch (RemoteException e) {
                Slog.e(TAG, "stopDetection() HAL invocation failed: " + e, e);

                synchronized (mLock) {
                    mOasHal = null;
                }
            }
        } else {
            Slog.e(TAG, "No HAL is connected. Cannot request graph stop");
        }
    }

    /**
     * Gets the vehicle capabilities for a given role.
     *
     * <p>Capabilities are static for a given vehicle configuration and need only be queried once
     * per vehicle. Once capability is determined, clients should query system status to see if the
     * subsystem is currently ready to serve.
     *
     * <p>Requires {@link android.car.Car.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE} read
     * permissions to access.
     *
     * @param role {@link VehicleOccupantRole} to query for.
     * @return Flags indicating supported capabilities for the role.
     */
    public @DetectionTypeFlags int getCapabilityForRole(@VehicleOccupantRole int role) {
        ICarImpl.assertPermission(mContext, Car.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE);

        connectToHalServiceIfNotConnected();

        // Grab a copy of 'mOasHal' to avoid sitting on the lock longer than is necessary.
        IOccupantAwareness hal;
        synchronized (mLock) {
            hal = mOasHal;
        }

        if (hal != null) {
            try {
                return hal.getCapabilityForRole(role);
            } catch (RemoteException e) {

                Slog.e(TAG, "getCapabilityForRole() HAL invocation failed: " + e, e);

                synchronized (mLock) {
                    mOasHal = null;
                }

                return SystemStatusEvent.DETECTION_TYPE_NONE;
            }
        } else {
            Slog.e(
                    TAG,
                    "getCapabilityForRole(): No HAL interface has been provided. Cannot get"
                            + " capabilities");
            return SystemStatusEvent.DETECTION_TYPE_NONE;
        }
    }

    /**
     * Registers a {@link IOccupantAwarenessEventCallback} to be notified for changes in the system
     * state.
     *
     * <p>Requires {@link android.car.Car.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE} read
     * permissions to access.
     *
     * @param listener {@link IOccupantAwarenessEventCallback} listener to register.
     */
    @Override
    public void registerEventListener(@NonNull IOccupantAwarenessEventCallback listener) {
        ICarImpl.assertPermission(mContext, Car.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE);

        connectToHalServiceIfNotConnected();

        synchronized (mLock) {
            if (mOasHal == null) {
                Slog.e(TAG, "Attempting to register a listener, but could not connect to HAL.");
                return;
            }

            logd("Registering a new listener");
            mListeners.register(listener);

            // After the first client connects, request that the detection graph start.
            if (mListeners.getRegisteredCallbackCount() == 1) {
                startDetectionGraph();
            }
        }
    }

    /**
     * Unregister the given {@link IOccupantAwarenessEventCallback} listener from receiving events.
     *
     * <p>Requires {@link android.car.Car.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE} read
     * permissions to access.
     *
     * @param listener {@link IOccupantAwarenessEventCallback} client to unregister.
     */
    @Override
    public void unregisterEventListener(@NonNull IOccupantAwarenessEventCallback listener) {
        ICarImpl.assertPermission(mContext, Car.PERMISSION_READ_CAR_OCCUPANT_AWARENESS_STATE);

        connectToHalServiceIfNotConnected();

        synchronized (mLock) {
            mListeners.unregister(listener);
        }

        // When the last client disconnects, request that the detection graph stop.
        handleClientDisconnected();
    }

    /** Processes a detection event and propagates it to registered clients. */
    @VisibleForTesting
    void processStatusEvent(@NonNull SystemStatusEvent statusEvent) {
        int idx = mListeners.beginBroadcast();
        while (idx-- > 0) {
            IOccupantAwarenessEventCallback listener = mListeners.getBroadcastItem(idx);
            try {
                listener.onStatusChanged(statusEvent);
            } catch (RemoteException e) {
                // It's likely the connection snapped. Let binder death handle the situation.
                Slog.e(TAG, "onStatusChanged() invocation failed: " + e, e);
            }
        }
        mListeners.finishBroadcast();
    }

    /** Processes a detection event and propagates it to registered clients. */
    @VisibleForTesting
    void processDetectionEvent(@NonNull OccupantAwarenessDetection detection) {
        int idx = mListeners.beginBroadcast();
        while (idx-- > 0) {
            IOccupantAwarenessEventCallback listener = mListeners.getBroadcastItem(idx);
            try {
                listener.onDetectionEvent(detection);
            } catch (RemoteException e) {
                // It's likely the connection snapped. Let binder death handle the situation.
                Slog.e(TAG, "onDetectionEvent() invocation failed: " + e, e);
            }
        }
        mListeners.finishBroadcast();
    }

    /** Handle client disconnections, possibly stopping the detection graph. */
    void handleClientDisconnected() {
        // If the last client disconnects, requests that the graph stops.
        synchronized (mLock) {
            if (mListeners.getRegisteredCallbackCount() == 0) {
                stopDetectionGraph();
            }
        }
    }

    private static void logd(String msg) {
        if (DBG) {
            Slog.d(TAG, msg);
        }
    }

    /**
     * Class that implements the listener interface and gets called back from the {@link
     * android.hardware.automotive.occupant_awareness.IOccupantAwarenessClientCallback} across the
     * binder interface.
     */
    private static class ChangeListenerToHalService extends IOccupantAwarenessClientCallback.Stub {
        private final WeakReference<OccupantAwarenessService> mOasService;

        ChangeListenerToHalService(OccupantAwarenessService oasService) {
            mOasService = new WeakReference<>(oasService);
        }

        @Override
        public void onSystemStatusChanged(int inputDetectionFlags, byte inputStatus) {
            OccupantAwarenessService service = mOasService.get();
            if (service != null) {
                service.processStatusEvent(
                        OccupantAwarenessUtils.convertToStatusEvent(
                                inputDetectionFlags, inputStatus));
            }
        }

        @Override
        public void onDetectionEvent(
                android.hardware.automotive.occupant_awareness.OccupantDetections detections) {
            OccupantAwarenessService service = mOasService.get();
            if (service != null) {
                for (android.hardware.automotive.occupant_awareness.OccupantDetection detection :
                        detections.detections) {
                    service.processDetectionEvent(
                            OccupantAwarenessUtils.convertToDetectionEvent(
                                    detections.timeStampMillis, detection));
                }
            }
        }

        @Override
        public int getInterfaceVersion() {
            return this.VERSION;
        }

        @Override
        public String getInterfaceHash() {
            return this.HASH;
        }
    }
}
