/*
 * 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 android.hardware.soundtrigger;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.media.soundtrigger_middleware.ISoundTriggerCallback;
import android.media.soundtrigger_middleware.ISoundTriggerMiddlewareService;
import android.media.soundtrigger_middleware.ISoundTriggerModule;
import android.media.soundtrigger_middleware.PhraseRecognitionEvent;
import android.media.soundtrigger_middleware.PhraseSoundModel;
import android.media.soundtrigger_middleware.RecognitionEvent;
import android.media.soundtrigger_middleware.SoundModel;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.Log;

/**
 * The SoundTriggerModule provides APIs to control sound models and sound detection
 * on a given sound trigger hardware module.
 *
 * @hide
 */
public class SoundTriggerModule {
    private static final String TAG = "SoundTriggerModule";

    private static final int EVENT_RECOGNITION = 1;
    private static final int EVENT_SERVICE_DIED = 2;
    private static final int EVENT_SERVICE_STATE_CHANGE = 3;
    @UnsupportedAppUsage
    private int mId;
    private EventHandlerDelegate mEventHandlerDelegate;
    private ISoundTriggerModule mService;

    SoundTriggerModule(@NonNull ISoundTriggerMiddlewareService service,
            int moduleId, @NonNull SoundTrigger.StatusListener listener, @NonNull Looper looper)
            throws RemoteException {
        mId = moduleId;
        mEventHandlerDelegate = new EventHandlerDelegate(listener, looper);
        mService = service.attach(moduleId, mEventHandlerDelegate);
        mService.asBinder().linkToDeath(mEventHandlerDelegate, 0);
    }

    @Override
    protected void finalize() {
        detach();
    }

    /**
     * Detach from this module. The {@link SoundTrigger.StatusListener} callback will not be called
     * anymore and associated resources will be released.
     * All models must have been unloaded prior to detaching.
     */
    @UnsupportedAppUsage
    public synchronized void detach() {
        try {
            if (mService != null) {
                mService.asBinder().unlinkToDeath(mEventHandlerDelegate, 0);
                mService.detach();
                mService = null;
            }
        } catch (Exception e) {
            SoundTrigger.handleException(e);
        }
    }

    /**
     * Load a {@link SoundTrigger.SoundModel} to the hardware. A sound model must be loaded in
     * order to start listening to a key phrase in this model.
     * @param model The sound model to load.
     * @param soundModelHandle an array of int where the sound model handle will be returned.
     * @return - {@link SoundTrigger#STATUS_OK} in case of success
     *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
     *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
     *         system permission
     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
     *         - {@link SoundTrigger#STATUS_BAD_VALUE} if parameters are invalid
     *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
     *         service fails
     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
     */
    @UnsupportedAppUsage
    public synchronized int loadSoundModel(@NonNull SoundTrigger.SoundModel model,
            @NonNull int[] soundModelHandle) {
        try {
            if (model instanceof SoundTrigger.GenericSoundModel) {
                SoundModel aidlModel = ConversionUtil.api2aidlGenericSoundModel(
                        (SoundTrigger.GenericSoundModel) model);
                soundModelHandle[0] = mService.loadModel(aidlModel);
                return SoundTrigger.STATUS_OK;
            }
            if (model instanceof SoundTrigger.KeyphraseSoundModel) {
                PhraseSoundModel aidlModel = ConversionUtil.api2aidlPhraseSoundModel(
                        (SoundTrigger.KeyphraseSoundModel) model);
                soundModelHandle[0] = mService.loadPhraseModel(aidlModel);
                return SoundTrigger.STATUS_OK;
            }
            return SoundTrigger.STATUS_BAD_VALUE;
        } catch (Exception e) {
            return SoundTrigger.handleException(e);
        }
    }

    /**
     * Unload a {@link SoundTrigger.SoundModel} and abort any pendiong recognition
     * @param soundModelHandle The sound model handle
     * @return - {@link SoundTrigger#STATUS_OK} in case of success
     *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
     *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
     *         system permission
     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
     *         - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid
     *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
     *         service fails
     */
    @UnsupportedAppUsage
    public synchronized int unloadSoundModel(int soundModelHandle) {
        try {
            mService.unloadModel(soundModelHandle);
            return SoundTrigger.STATUS_OK;
        } catch (Exception e) {
            return SoundTrigger.handleException(e);
        }
    }

    /**
     * Start listening to all key phrases in a {@link SoundTrigger.SoundModel}.
     * Recognition must be restarted after each callback (success or failure) received on
     * the {@link SoundTrigger.StatusListener}.
     * @param soundModelHandle The sound model handle to start listening to
     * @param config contains configuration information for this recognition request:
     *  recognition mode, keyphrases, users, minimum confidence levels...
     * @return - {@link SoundTrigger#STATUS_OK} in case of success
     *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
     *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
     *         system permission
     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
     *         - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid
     *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
     *         service fails
     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
     */
    @UnsupportedAppUsage
    public synchronized int startRecognition(int soundModelHandle,
            SoundTrigger.RecognitionConfig config) {
        try {
            mService.startRecognition(soundModelHandle,
                    ConversionUtil.api2aidlRecognitionConfig(config));
            return SoundTrigger.STATUS_OK;
        } catch (Exception e) {
            return SoundTrigger.handleException(e);
        }
    }

    /**
     * Stop listening to all key phrases in a {@link SoundTrigger.SoundModel}
     * @param soundModelHandle The sound model handle to stop listening to
     * @return - {@link SoundTrigger#STATUS_OK} in case of success
     *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
     *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
     *         system permission
     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
     *         - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid
     *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
     *         service fails
     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
     */
    @UnsupportedAppUsage
    public synchronized int stopRecognition(int soundModelHandle) {
        try {
            mService.stopRecognition(soundModelHandle);
            return SoundTrigger.STATUS_OK;
        } catch (Exception e) {
            return SoundTrigger.handleException(e);
        }
    }

    /**
     * Get the current state of a {@link SoundTrigger.SoundModel}.
     * The state will be returned asynchronously as a {@link SoundTrigger.RecognitionEvent}
     * in the callback registered in the
     * {@link SoundTrigger#attachModule(int, SoundTrigger.StatusListener, Handler)} method.
     * @param soundModelHandle The sound model handle indicating which model's state to return
     * @return - {@link SoundTrigger#STATUS_OK} in case of success
     *         - {@link SoundTrigger#STATUS_ERROR} in case of unspecified error
     *         - {@link SoundTrigger#STATUS_PERMISSION_DENIED} if the caller does not have
     *         system permission
     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
     *         - {@link SoundTrigger#STATUS_BAD_VALUE} if the sound model handle is invalid
     *         - {@link SoundTrigger#STATUS_DEAD_OBJECT} if the binder transaction to the native
     *         service fails
     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence
     */
    public synchronized int getModelState(int soundModelHandle) {
        try {
            mService.forceRecognitionEvent(soundModelHandle);
            return SoundTrigger.STATUS_OK;
        } catch (Exception e) {
            return SoundTrigger.handleException(e);
        }
    }

    /**
     * Set a model specific {@link ModelParams} with the given value. This
     * parameter will keep its value for the duration the model is loaded regardless of starting
     * and stopping recognition. Once the model is unloaded, the value will be lost.
     * {@link #queryParameter} should be checked first before calling this method.
     *
     * @param soundModelHandle handle of model to apply parameter
     * @param modelParam       {@link ModelParams}
     * @param value            Value to set
     * @return - {@link SoundTrigger#STATUS_OK} in case of success
     * - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
     * - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
     * - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
     * if API is not supported by HAL
     */
    public synchronized int setParameter(int soundModelHandle, @ModelParams int modelParam,
            int value) {
        try {
            mService.setModelParameter(soundModelHandle,
                    ConversionUtil.api2aidlModelParameter(modelParam), value);
            return SoundTrigger.STATUS_OK;
        } catch (Exception e) {
            return SoundTrigger.handleException(e);
        }
    }

    /**
     * Get a model specific {@link ModelParams}. This parameter will keep its value
     * for the duration the model is loaded regardless of starting and stopping recognition.
     * Once the model is unloaded, the value will be lost. If the value is not set, a default
     * value is returned. See {@link ModelParams} for parameter default values.
     * {@link #queryParameter} should be checked first before
     * calling this method. Otherwise, an exception can be thrown.
     *
     * @param soundModelHandle handle of model to get parameter
     * @param modelParam       {@link ModelParams}
     * @return value of parameter
     */
    public synchronized int getParameter(int soundModelHandle, @ModelParams int modelParam) {
        try {
            return mService.getModelParameter(soundModelHandle,
                    ConversionUtil.api2aidlModelParameter(modelParam));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Query the parameter support and range for a given {@link ModelParams}.
     * This method should be check prior to calling {@link #setParameter} or {@link #getParameter}.
     *
     * @param soundModelHandle handle of model to get parameter
     * @param modelParam       {@link ModelParams}
     * @return supported range of parameter, null if not supported
     */
    @Nullable
    public synchronized SoundTrigger.ModelParamRange queryParameter(int soundModelHandle,
            @ModelParams int modelParam) {
        try {
            return ConversionUtil.aidl2apiModelParameterRange(mService.queryModelParameterSupport(
                    soundModelHandle,
                    ConversionUtil.api2aidlModelParameter(modelParam)));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    private class EventHandlerDelegate extends ISoundTriggerCallback.Stub implements
            IBinder.DeathRecipient {
        private final Handler mHandler;

        EventHandlerDelegate(@NonNull final SoundTrigger.StatusListener listener,
                @NonNull Looper looper) {

            // construct the event handler with this looper
            // implement the event handler delegate
            mHandler = new Handler(looper) {
                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case EVENT_RECOGNITION:
                            listener.onRecognition(
                                    (SoundTrigger.RecognitionEvent) msg.obj);
                            break;
                        case EVENT_SERVICE_STATE_CHANGE:
                            listener.onServiceStateChange(msg.arg1);
                            break;
                        case EVENT_SERVICE_DIED:
                            listener.onServiceDied();
                            break;
                        default:
                            Log.e(TAG, "Unknown message: " + msg.toString());
                            break;
                    }
                }
            };
        }

        @Override
        public synchronized void onRecognition(int handle, RecognitionEvent event)
                throws RemoteException {
            Message m = mHandler.obtainMessage(EVENT_RECOGNITION,
                    ConversionUtil.aidl2apiRecognitionEvent(handle, event));
            mHandler.sendMessage(m);
        }

        @Override
        public synchronized void onPhraseRecognition(int handle, PhraseRecognitionEvent event)
                throws RemoteException {
            Message m = mHandler.obtainMessage(EVENT_RECOGNITION,
                    ConversionUtil.aidl2apiPhraseRecognitionEvent(handle, event));
            mHandler.sendMessage(m);
        }

        @Override
        public synchronized void onRecognitionAvailabilityChange(boolean available)
                throws RemoteException {
            Message m = mHandler.obtainMessage(EVENT_SERVICE_STATE_CHANGE,
                    available ? SoundTrigger.SERVICE_STATE_ENABLED
                            : SoundTrigger.SERVICE_STATE_DISABLED);
            mHandler.sendMessage(m);
        }

        @Override
        public synchronized void onModuleDied() {
            Message m = mHandler.obtainMessage(EVENT_SERVICE_DIED);
            mHandler.sendMessage(m);
        }

        @Override
        public synchronized void binderDied() {
            Message m = mHandler.obtainMessage(EVENT_SERVICE_DIED);
            mHandler.sendMessage(m);
        }
    }
}
