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

import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.SoundTrigger;
import android.hardware.soundtrigger.SoundTrigger.GenericRecognitionEvent;
import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
import android.hardware.soundtrigger.SoundTrigger.Keyphrase;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
import android.hardware.soundtrigger.SoundTrigger.SoundModel;
import android.hardware.soundtrigger.SoundTrigger.SoundModelEvent;
import android.hardware.soundtrigger.SoundTriggerModule;
import android.os.PowerManager;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Slog;
import com.android.internal.logging.MetricsLogger;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;

/**
 * Helper for {@link SoundTrigger} APIs. Supports two types of models:
 * (i) A voice model which is exported via the {@link VoiceInteractionService}. There can only be
 * a single voice model running on the DSP at any given time.
 *
 * (ii) Generic sound-trigger models: Supports multiple of these.
 *
 * Currently this just acts as an abstraction over all SoundTrigger API calls.
 * @hide
 */
public class SoundTriggerHelper implements SoundTrigger.StatusListener {
    static final String TAG = "SoundTriggerHelper";
    static final boolean DBG = false;

    /**
     * Return codes for {@link #startRecognition(int, KeyphraseSoundModel,
     *      IRecognitionStatusCallback, RecognitionConfig)},
     * {@link #stopRecognition(int, IRecognitionStatusCallback)}
     */
    public static final int STATUS_ERROR = SoundTrigger.STATUS_ERROR;
    public static final int STATUS_OK = SoundTrigger.STATUS_OK;

    private static final int INVALID_VALUE = Integer.MIN_VALUE;

    /** The {@link ModuleProperties} for the system, or null if none exists. */
    final ModuleProperties mModuleProperties;

    /** The properties for the DSP module */
    private SoundTriggerModule mModule;
    private final Object mLock = new Object();
    private final Context mContext;
    private final TelephonyManager mTelephonyManager;
    private final PhoneStateListener mPhoneStateListener;
    private final PowerManager mPowerManager;

    // The SoundTriggerManager layer handles multiple recognition models of type generic and
    // keyphrase. We store the ModelData here in a hashmap.
    private final HashMap<UUID, ModelData> mModelDataMap;

    // An index of keyphrase sound models so that we can reach them easily. We support indexing
    // keyphrase sound models with a keyphrase ID. Sound model with the same keyphrase ID will
    // replace an existing model, thus there is a 1:1 mapping from keyphrase ID to a voice
    // sound model.
    private HashMap<Integer, UUID> mKeyphraseUuidMap;

    private boolean mCallActive = false;
    private boolean mIsPowerSaveMode = false;
    // Indicates if the native sound trigger service is disabled or not.
    // This is an indirect indication of the microphone being open in some other application.
    private boolean mServiceDisabled = false;

    // Whether we have ANY recognition (keyphrase or generic) running.
    private boolean mRecognitionRunning = false;

    private PowerSaveModeListener mPowerSaveModeListener;

    SoundTriggerHelper(Context context) {
        ArrayList <ModuleProperties> modules = new ArrayList<>();
        int status = SoundTrigger.listModules(modules);
        mContext = context;
        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mModelDataMap = new HashMap<UUID, ModelData>();
        mKeyphraseUuidMap = new HashMap<Integer, UUID>();
        mPhoneStateListener = new MyCallStateListener();
        if (status != SoundTrigger.STATUS_OK || modules.size() == 0) {
            Slog.w(TAG, "listModules status=" + status + ", # of modules=" + modules.size());
            mModuleProperties = null;
            mModule = null;
        } else {
            // TODO: Figure out how to determine which module corresponds to the DSP hardware.
            mModuleProperties = modules.get(0);
        }
    }

    /**
     * Starts recognition for the given generic sound model ID. This is a wrapper around {@link
     * startRecognition()}.
     *
     * @param modelId UUID of the sound model.
     * @param soundModel The generic sound model to use for recognition.
     * @param callback Callack for the recognition events related to the given keyphrase.
     * @param recognitionConfig Instance of RecognitionConfig containing the parameters for the
     * recognition.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int startGenericRecognition(UUID modelId, GenericSoundModel soundModel,
            IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
        MetricsLogger.count(mContext, "sth_start_recognition", 1);
        if (modelId == null || soundModel == null || callback == null ||
                recognitionConfig == null) {
            Slog.w(TAG, "Passed in bad data to startGenericRecognition().");
            return STATUS_ERROR;
        }

        synchronized (mLock) {
            ModelData modelData = getOrCreateGenericModelDataLocked(modelId);
            if (modelData == null) {
                Slog.w(TAG, "Irrecoverable error occurred, check UUID / sound model data.");
                return STATUS_ERROR;
            }
            return startRecognition(soundModel, modelData, callback, recognitionConfig,
                    INVALID_VALUE /* keyphraseId */);
        }
    }

    /**
     * Starts recognition for the given keyphraseId.
     *
     * @param keyphraseId The identifier of the keyphrase for which
     *        the recognition is to be started.
     * @param soundModel The sound model to use for recognition.
     * @param callback The callback for the recognition events related to the given keyphrase.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int startKeyphraseRecognition(int keyphraseId, KeyphraseSoundModel soundModel,
            IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_start_recognition", 1);
            if (soundModel == null || callback == null || recognitionConfig == null) {
                return STATUS_ERROR;
            }

            if (DBG) {
                Slog.d(TAG, "startKeyphraseRecognition for keyphraseId=" + keyphraseId
                        + " soundModel=" + soundModel + ", callback=" + callback.asBinder()
                        + ", recognitionConfig=" + recognitionConfig);
                Slog.d(TAG, "moduleProperties=" + mModuleProperties);
                dumpModelStateLocked();
            }

            ModelData model = getKeyphraseModelDataLocked(keyphraseId);
            if (model != null && !model.isKeyphraseModel()) {
                Slog.e(TAG, "Generic model with same UUID exists.");
                return STATUS_ERROR;
            }

            // Process existing model first.
            if (model != null && !model.getModelId().equals(soundModel.uuid)) {
                // The existing model has a different UUID, should be replaced.
                int status = cleanUpExistingKeyphraseModel(model);
                if (status != STATUS_OK) {
                    return status;
                }
                removeKeyphraseModelLocked(keyphraseId);
                model = null;
            }

            // We need to create a new one: either no previous models existed for given keyphrase id
            // or the existing model had a different UUID and was cleaned up.
            if (model == null) {
                model = createKeyphraseModelDataLocked(soundModel.uuid, keyphraseId);
            }

            return startRecognition(soundModel, model, callback, recognitionConfig,
                    keyphraseId);
        }
    }

    private int cleanUpExistingKeyphraseModel(ModelData modelData) {
        // Stop and clean up a previous ModelData if one exists. This usually is used when the
        // previous model has a different UUID for the same keyphrase ID.
        int status = tryStopAndUnloadLocked(modelData, true /* stop */, true /* unload */);
        if (status != STATUS_OK) {
            Slog.w(TAG, "Unable to stop or unload previous model: " +
                    modelData.toString());
        }
        return status;
    }

    /**
     * Starts recognition for the given sound model. A single routine for both keyphrase and
     * generic sound models.
     *
     * @param soundModel The sound model to use for recognition.
     * @param modelData Instance of {@link #ModelData} for the given model.
     * @param callback Callback for the recognition events related to the given keyphrase.
     * @param recognitionConfig Instance of {@link RecognitionConfig} containing the parameters
     * @param keyphraseId Keyphrase ID for keyphrase models only. Pass in INVALID_VALUE for other
     * models.
     * for the recognition.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int startRecognition(SoundModel soundModel, ModelData modelData,
            IRecognitionStatusCallback callback, RecognitionConfig recognitionConfig,
            int keyphraseId) {
        synchronized (mLock) {
            if (mModuleProperties == null) {
                Slog.w(TAG, "Attempting startRecognition without the capability");
                return STATUS_ERROR;
            }
            if (mModule == null) {
                mModule = SoundTrigger.attachModule(mModuleProperties.id, this, null);
                if (mModule == null) {
                    Slog.w(TAG, "startRecognition cannot attach to sound trigger module");
                    return STATUS_ERROR;
                }
            }

            // Initialize power save, call active state monitoring logic.
            if (!mRecognitionRunning) {
                initializeTelephonyAndPowerStateListeners();
            }

            // If the existing SoundModel is different (for the same UUID for Generic and same
            // keyphrase ID for voice), ensure that it is unloaded and stopped before proceeding.
            // This works for both keyphrase and generic models. This logic also ensures that a
            // previously loaded (or started) model is appropriately stopped. Since this is a
            // generalization of the previous logic with a single keyphrase model, we should have
            // no regression with the previous version of this code as was given in the
            // startKeyphrase() routine.
            if (modelData.getSoundModel() != null) {
                boolean stopModel = false; // Stop the model after checking that it is started.
                boolean unloadModel = false;
                if (modelData.getSoundModel().equals(soundModel) && modelData.isModelStarted()) {
                    // The model has not changed, but the previous model is "started".
                    // Stop the previously running model.
                    stopModel = true;
                    unloadModel = false; // No need to unload if the model hasn't changed.
                } else if (!modelData.getSoundModel().equals(soundModel)) {
                    // We have a different model for this UUID. Stop and unload if needed. This
                    // helps maintain the singleton restriction for keyphrase sound models.
                    stopModel = modelData.isModelStarted();
                    unloadModel = modelData.isModelLoaded();
                }
                if (stopModel || unloadModel) {
                    int status = tryStopAndUnloadLocked(modelData, stopModel, unloadModel);
                    if (status != STATUS_OK) {
                        Slog.w(TAG, "Unable to stop or unload previous model: " +
                                modelData.toString());
                        return status;
                    }
                }
            }

            IRecognitionStatusCallback oldCallback = modelData.getCallback();
            if (oldCallback != null && oldCallback.asBinder() != callback.asBinder()) {
                Slog.w(TAG, "Canceling previous recognition for model id: " +
                        modelData.getModelId());
                try {
                    oldCallback.onError(STATUS_ERROR);
                } catch (RemoteException e) {
                    Slog.w(TAG, "RemoteException in onDetectionStopped", e);
                }
                modelData.clearCallback();
            }

            // Load the model if it is not loaded.
            if (!modelData.isModelLoaded()) {
                // Load the model
                int[] handle = new int[] { INVALID_VALUE };
                int status = mModule.loadSoundModel(soundModel, handle);
                if (status != SoundTrigger.STATUS_OK) {
                    Slog.w(TAG, "loadSoundModel call failed with " + status);
                    return status;
                }
                if (handle[0] == INVALID_VALUE) {
                    Slog.w(TAG, "loadSoundModel call returned invalid sound model handle");
                    return STATUS_ERROR;
                }
                modelData.setHandle(handle[0]);
                modelData.setLoaded();
                Slog.d(TAG, "Sound model loaded with handle:" + handle[0]);
            }
            modelData.setCallback(callback);
            modelData.setRequested(true);
            modelData.setRecognitionConfig(recognitionConfig);
            modelData.setSoundModel(soundModel);

            return startRecognitionLocked(modelData,
                    false /* Don't notify for synchronous calls */);
        }
    }

    /**
     * Stops recognition for the given generic sound model. This is a wrapper for {@link
     * #stopRecognition}.
     *
     * @param modelId The identifier of the generic sound model for which
     *        the recognition is to be stopped.
     * @param callback The callback for the recognition events related to the given sound model.
     *
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int stopGenericRecognition(UUID modelId, IRecognitionStatusCallback callback) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_stop_recognition", 1);
            if (callback == null || modelId == null) {
                Slog.e(TAG, "Null callbackreceived for stopGenericRecognition() for modelid:" +
                        modelId);
                return STATUS_ERROR;
            }

            ModelData modelData = mModelDataMap.get(modelId);
            if (modelData == null || !modelData.isGenericModel()) {
                Slog.w(TAG, "Attempting stopRecognition on invalid model with id:" + modelId);
                return STATUS_ERROR;
            }

            int status = stopRecognition(modelData, callback);
            if (status != SoundTrigger.STATUS_OK) {
                Slog.w(TAG, "stopGenericRecognition failed: " + status);
            }
            return status;
        }
    }

    /**
     * Stops recognition for the given {@link Keyphrase} if a recognition is
     * currently active. This is a wrapper for {@link #stopRecognition()}.
     *
     * @param keyphraseId The identifier of the keyphrase for which
     *        the recognition is to be stopped.
     * @param callback The callback for the recognition events related to the given keyphrase.
     *
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    int stopKeyphraseRecognition(int keyphraseId, IRecognitionStatusCallback callback) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_stop_recognition", 1);
            if (callback == null) {
                Slog.e(TAG, "Null callback received for stopKeyphraseRecognition() for keyphraseId:" +
                        keyphraseId);
                return STATUS_ERROR;
            }

            ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
            if (modelData == null || !modelData.isKeyphraseModel()) {
                Slog.e(TAG, "No model exists for given keyphrase Id.");
                return STATUS_ERROR;
            }

            if (DBG) {
                Slog.d(TAG, "stopRecognition for keyphraseId=" + keyphraseId + ", callback =" +
                        callback.asBinder());
                Slog.d(TAG, "current callback=" + (modelData == null ? "null" :
                            modelData.getCallback().asBinder()));
            }
            int status = stopRecognition(modelData, callback);
            if (status != SoundTrigger.STATUS_OK) {
                return status;
            }

            return status;
        }
    }

    /**
     * Stops recognition for the given ModelData instance.
     *
     * @param modelData Instance of {@link #ModelData} sound model.
     * @param callback The callback for the recognition events related to the given keyphrase.
     * @return One of {@link #STATUS_ERROR} or {@link #STATUS_OK}.
     */
    private int stopRecognition(ModelData modelData, IRecognitionStatusCallback callback) {
        synchronized (mLock) {
            if (callback == null) {
                return STATUS_ERROR;
            }
            if (mModuleProperties == null || mModule == null) {
                Slog.w(TAG, "Attempting stopRecognition without the capability");
                return STATUS_ERROR;
            }

            IRecognitionStatusCallback currentCallback = modelData.getCallback();
            if (modelData == null || currentCallback == null ||
                    (!modelData.isRequested() && !modelData.isModelStarted())) {
                // startGenericRecognition hasn't been called or it failed.
                Slog.w(TAG, "Attempting stopRecognition without a successful startRecognition");
                return STATUS_ERROR;
            }

            if (currentCallback.asBinder() != callback.asBinder()) {
                // We don't allow a different listener to stop the recognition than the one
                // that started it.
                Slog.w(TAG, "Attempting stopRecognition for another recognition");
                return STATUS_ERROR;
            }

            // Request stop recognition via the update() method.
            modelData.setRequested(false);
            int status = updateRecognitionLocked(modelData, isRecognitionAllowed(),
                    false /* don't notify for synchronous calls */);
            if (status != SoundTrigger.STATUS_OK) {
                return status;
            }

            // We leave the sound model loaded but not started, this helps us when we start back.
            // Also clear the internal state once the recognition has been stopped.
            modelData.setLoaded();
            modelData.clearCallback();
            modelData.setRecognitionConfig(null);

            if (!computeRecognitionRunningLocked()) {
                internalClearGlobalStateLocked();
            }

            return status;
        }
    }

    // Stop a previously started model if it was started. Optionally, unload if the previous model
    // is stale and is about to be replaced.
    // Needs to be called with the mLock held.
    private int tryStopAndUnloadLocked(ModelData modelData, boolean stopModel,
            boolean unloadModel) {
        int status = STATUS_OK;
        if (modelData.isModelNotLoaded()) {
            return status;
        }
        if (stopModel && modelData.isModelStarted()) {
            status = stopRecognitionLocked(modelData,
                    false /* don't notify for synchronous calls */);
            if (status != SoundTrigger.STATUS_OK) {
                Slog.w(TAG, "stopRecognition failed: " + status);
                return status;
            }
        }

        if (unloadModel && modelData.isModelLoaded()) {
            Slog.d(TAG, "Unloading previously loaded stale model.");
            status = mModule.unloadSoundModel(modelData.getHandle());
            MetricsLogger.count(mContext, "sth_unloading_stale_model", 1);
            if (status != SoundTrigger.STATUS_OK) {
                Slog.w(TAG, "unloadSoundModel call failed with " + status);
            } else {
                // Clear the ModelData state if successful.
                modelData.clearState();
            }
        }
        return status;
    }

    public ModuleProperties getModuleProperties() {
        return mModuleProperties;
    }

    int unloadKeyphraseSoundModel(int keyphraseId) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_unload_keyphrase_sound_model", 1);
            ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);
            if (mModule == null || modelData == null || modelData.getHandle() == INVALID_VALUE ||
                    !modelData.isKeyphraseModel()) {
                return STATUS_ERROR;
            }

            // Stop recognition if it's the current one.
            modelData.setRequested(false);
            int status = updateRecognitionLocked(modelData, isRecognitionAllowed(),
                    false /* don't notify */);
            if (status != SoundTrigger.STATUS_OK) {
                Slog.w(TAG, "Stop recognition failed for keyphrase ID:" + status);
            }

            status = mModule.unloadSoundModel(modelData.getHandle());
            if (status != SoundTrigger.STATUS_OK) {
                Slog.w(TAG, "unloadKeyphraseSoundModel call failed with " + status);
            }

            // Remove it from existence.
            removeKeyphraseModelLocked(keyphraseId);
            return status;
        }
    }

    int unloadGenericSoundModel(UUID modelId) {
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_unload_generic_sound_model", 1);
            if (modelId == null || mModule == null) {
                return STATUS_ERROR;
            }
            ModelData modelData = mModelDataMap.get(modelId);
            if (modelData == null || !modelData.isGenericModel()) {
                Slog.w(TAG, "Unload error: Attempting unload invalid generic model with id:" +
                        modelId);
                return STATUS_ERROR;
            }
            if (!modelData.isModelLoaded()) {
                // Nothing to do here.
                Slog.i(TAG, "Unload: Given generic model is not loaded:" + modelId);
                return STATUS_OK;
            }
            if (modelData.isModelStarted()) {
                int status = stopRecognitionLocked(modelData,
                        false /* don't notify for synchronous calls */);
                if (status != SoundTrigger.STATUS_OK) {
                    Slog.w(TAG, "stopGenericRecognition failed: " + status);
                }
            }

            int status = mModule.unloadSoundModel(modelData.getHandle());
            if (status != SoundTrigger.STATUS_OK) {
                Slog.w(TAG, "unloadGenericSoundModel() call failed with " + status);
                Slog.w(TAG, "unloadGenericSoundModel() force-marking model as unloaded.");
            }

            // Remove it from existence.
            mModelDataMap.remove(modelId);
            if (DBG) dumpModelStateLocked();
            return status;
        }
    }

    //---- SoundTrigger.StatusListener methods
    @Override
    public void onRecognition(RecognitionEvent event) {
        if (event == null) {
            Slog.w(TAG, "Null recognition event!");
            return;
        }

        if (!(event instanceof KeyphraseRecognitionEvent) &&
                !(event instanceof GenericRecognitionEvent)) {
            Slog.w(TAG, "Invalid recognition event type (not one of generic or keyphrase)!");
            return;
        }

        if (DBG) Slog.d(TAG, "onRecognition: " + event);
        synchronized (mLock) {
            switch (event.status) {
                case SoundTrigger.RECOGNITION_STATUS_ABORT:
                    onRecognitionAbortLocked(event);
                    break;
                case SoundTrigger.RECOGNITION_STATUS_FAILURE:
                    // Fire failures to all listeners since it's not tied to a keyphrase.
                    onRecognitionFailureLocked();
                    break;
                case SoundTrigger.RECOGNITION_STATUS_SUCCESS:
                    if (isKeyphraseRecognitionEvent(event)) {
                        onKeyphraseRecognitionSuccessLocked((KeyphraseRecognitionEvent) event);
                    } else {
                        onGenericRecognitionSuccessLocked((GenericRecognitionEvent) event);
                    }
                    break;
            }
        }
    }

    private boolean isKeyphraseRecognitionEvent(RecognitionEvent event) {
        return event instanceof KeyphraseRecognitionEvent;
    }

    private void onGenericRecognitionSuccessLocked(GenericRecognitionEvent event) {
        MetricsLogger.count(mContext, "sth_generic_recognition_event", 1);
        if (event.status != SoundTrigger.RECOGNITION_STATUS_SUCCESS) {
            return;
        }
        ModelData model = getModelDataForLocked(event.soundModelHandle);
        if (model == null || !model.isGenericModel()) {
            Slog.w(TAG, "Generic recognition event: Model does not exist for handle: " +
                    event.soundModelHandle);
            return;
        }

        IRecognitionStatusCallback callback = model.getCallback();
        if (callback == null) {
            Slog.w(TAG, "Generic recognition event: Null callback for model handle: " +
                    event.soundModelHandle);
            return;
        }

        try {
            callback.onGenericSoundTriggerDetected((GenericRecognitionEvent) event);
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException in onGenericSoundTriggerDetected", e);
        }

        model.setStopped();
        RecognitionConfig config = model.getRecognitionConfig();
        if (config == null) {
            Slog.w(TAG, "Generic recognition event: Null RecognitionConfig for model handle: " +
                    event.soundModelHandle);
            return;
        }

        model.setRequested(config.allowMultipleTriggers);
        // TODO: Remove this block if the lower layer supports multiple triggers.
        if (model.isRequested()) {
            updateRecognitionLocked(model, isRecognitionAllowed() /* isAllowed */,
                    true /* notify */);
        }
    }

    @Override
    public void onSoundModelUpdate(SoundModelEvent event) {
        if (event == null) {
            Slog.w(TAG, "Invalid sound model event!");
            return;
        }
        if (DBG) Slog.d(TAG, "onSoundModelUpdate: " + event);
        synchronized (mLock) {
            MetricsLogger.count(mContext, "sth_sound_model_updated", 1);
            onSoundModelUpdatedLocked(event);
        }
    }

    @Override
    public void onServiceStateChange(int state) {
        if (DBG) Slog.d(TAG, "onServiceStateChange, state: " + state);
        synchronized (mLock) {
            onServiceStateChangedLocked(SoundTrigger.SERVICE_STATE_DISABLED == state);
        }
    }

    @Override
    public void onServiceDied() {
        Slog.e(TAG, "onServiceDied!!");
        MetricsLogger.count(mContext, "sth_service_died", 1);
        synchronized (mLock) {
            onServiceDiedLocked();
        }
    }

    private void onCallStateChangedLocked(boolean callActive) {
        if (mCallActive == callActive) {
            // We consider multiple call states as being active
            // so we check if something really changed or not here.
            return;
        }
        mCallActive = callActive;
        updateAllRecognitionsLocked(true /* notify */);
    }

    private void onPowerSaveModeChangedLocked(boolean isPowerSaveMode) {
        if (mIsPowerSaveMode == isPowerSaveMode) {
            return;
        }
        mIsPowerSaveMode = isPowerSaveMode;
        updateAllRecognitionsLocked(true /* notify */);
    }

    private void onSoundModelUpdatedLocked(SoundModelEvent event) {
        // TODO: Handle sound model update here.
    }

    private void onServiceStateChangedLocked(boolean disabled) {
        if (disabled == mServiceDisabled) {
            return;
        }
        mServiceDisabled = disabled;
        updateAllRecognitionsLocked(true /* notify */);
    }

    private void onRecognitionAbortLocked(RecognitionEvent event) {
        Slog.w(TAG, "Recognition aborted");
        MetricsLogger.count(mContext, "sth_recognition_aborted", 1);
        ModelData modelData = getModelDataForLocked(event.soundModelHandle);
        if (modelData != null && modelData.isModelStarted()) {
            modelData.setStopped();
            try {
                modelData.getCallback().onRecognitionPaused();
            } catch (RemoteException e) {
                Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
            }
        }
    }

    private void onRecognitionFailureLocked() {
        Slog.w(TAG, "Recognition failure");
        MetricsLogger.count(mContext, "sth_recognition_failure_event", 1);
        try {
            sendErrorCallbacksToAll(STATUS_ERROR);
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException in onError", e);
        } finally {
            internalClearModelStateLocked();
            internalClearGlobalStateLocked();
        }
    }

    private int getKeyphraseIdFromEvent(KeyphraseRecognitionEvent event) {
        if (event == null) {
            Slog.w(TAG, "Null RecognitionEvent received.");
            return INVALID_VALUE;
        }
        KeyphraseRecognitionExtra[] keyphraseExtras =
                ((KeyphraseRecognitionEvent) event).keyphraseExtras;
        if (keyphraseExtras == null || keyphraseExtras.length == 0) {
            Slog.w(TAG, "Invalid keyphrase recognition event!");
            return INVALID_VALUE;
        }
        // TODO: Handle more than one keyphrase extras.
        return keyphraseExtras[0].id;
    }

    private void onKeyphraseRecognitionSuccessLocked(KeyphraseRecognitionEvent event) {
        Slog.i(TAG, "Recognition success");
        MetricsLogger.count(mContext, "sth_keyphrase_recognition_event", 1);
        int keyphraseId = getKeyphraseIdFromEvent(event);
        ModelData modelData = getKeyphraseModelDataLocked(keyphraseId);

        if (modelData == null || !modelData.isKeyphraseModel()) {
            Slog.e(TAG, "Keyphase model data does not exist for ID:" + keyphraseId);
            return;
        }

        if (modelData.getCallback() == null) {
            Slog.w(TAG, "Received onRecognition event without callback for keyphrase model.");
            return;
        }

        try {
            modelData.getCallback().onKeyphraseDetected((KeyphraseRecognitionEvent) event);
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException in onKeyphraseDetected", e);
        }

        modelData.setStopped();

        RecognitionConfig config = modelData.getRecognitionConfig();
        if (config != null) {
            // Whether we should continue by starting this again.
            modelData.setRequested(config.allowMultipleTriggers);
        }
        // TODO: Remove this block if the lower layer supports multiple triggers.
        if (modelData.isRequested()) {
            updateRecognitionLocked(modelData, isRecognitionAllowed(), true /* notify */);
        }
    }

    private void updateAllRecognitionsLocked(boolean notify) {
        boolean isAllowed = isRecognitionAllowed();
        for (ModelData modelData : mModelDataMap.values()) {
            updateRecognitionLocked(modelData, isAllowed, notify);
        }
    }

    private int updateRecognitionLocked(ModelData model, boolean isAllowed,
        boolean notify) {
        boolean start = model.isRequested() && isAllowed;
        if (start == model.isModelStarted()) {
            // No-op.
            return STATUS_OK;
        }
        if (start) {
            return startRecognitionLocked(model, notify);
        } else {
            return stopRecognitionLocked(model, notify);
        }
    }

    private void onServiceDiedLocked() {
        try {
          MetricsLogger.count(mContext, "sth_service_died", 1);
            sendErrorCallbacksToAll(SoundTrigger.STATUS_DEAD_OBJECT);
        } catch (RemoteException e) {
            Slog.w(TAG, "RemoteException in onError", e);
        } finally {
            internalClearModelStateLocked();
            internalClearGlobalStateLocked();
            if (mModule != null) {
                mModule.detach();
                mModule = null;
            }
        }
    }

    // internalClearGlobalStateLocked() cleans up the telephony and power save listeners.
    private void internalClearGlobalStateLocked() {
        // Unregister from call state changes.
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);

        // Unregister from power save mode changes.
        if (mPowerSaveModeListener != null) {
            mContext.unregisterReceiver(mPowerSaveModeListener);
            mPowerSaveModeListener = null;
        }
    }

    // Clears state for all models (generic and keyphrase).
    private void internalClearModelStateLocked() {
        for (ModelData modelData : mModelDataMap.values()) {
            modelData.clearState();
        }
    }

    class MyCallStateListener extends PhoneStateListener {
        @Override
        public void onCallStateChanged(int state, String arg1) {
            if (DBG) Slog.d(TAG, "onCallStateChanged: " + state);
            synchronized (mLock) {
                onCallStateChangedLocked(TelephonyManager.CALL_STATE_IDLE != state);
            }
        }
    }

    class PowerSaveModeListener extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
                return;
            }
            boolean active = mPowerManager.isPowerSaveMode();
            if (DBG) Slog.d(TAG, "onPowerSaveModeChanged: " + active);
            synchronized (mLock) {
                onPowerSaveModeChangedLocked(active);
            }
        }
    }

    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (mLock) {
            pw.print("  module properties=");
            pw.println(mModuleProperties == null ? "null" : mModuleProperties);

            pw.print("  call active="); pw.println(mCallActive);
            pw.print("  power save mode active="); pw.println(mIsPowerSaveMode);
            pw.print("  service disabled="); pw.println(mServiceDisabled);
        }
    }

    private void initializeTelephonyAndPowerStateListeners() {
        // Get the current call state synchronously for the first recognition.
        mCallActive = mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;

        // Register for call state changes when the first call to start recognition occurs.
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

        // Register for power saver mode changes when the first call to start recognition
        // occurs.
        if (mPowerSaveModeListener == null) {
            mPowerSaveModeListener = new PowerSaveModeListener();
            mContext.registerReceiver(mPowerSaveModeListener,
                    new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
        }
        mIsPowerSaveMode = mPowerManager.isPowerSaveMode();
    }

    // Sends an error callback to all models with a valid registered callback.
    private void sendErrorCallbacksToAll(int errorCode) throws RemoteException {
        for (ModelData modelData : mModelDataMap.values()) {
            IRecognitionStatusCallback callback = modelData.getCallback();
            if (callback != null) {
                callback.onError(STATUS_ERROR);
            }
        }
    }

    private ModelData getOrCreateGenericModelDataLocked(UUID modelId) {
        ModelData modelData = mModelDataMap.get(modelId);
        if (modelData == null) {
            modelData = ModelData.createGenericModelData(modelId);
            mModelDataMap.put(modelId, modelData);
        } else if (!modelData.isGenericModel()) {
            Slog.e(TAG, "UUID already used for non-generic model.");
            return null;
        }
        return modelData;
    }

    private void removeKeyphraseModelLocked(int keyphraseId) {
        UUID uuid = mKeyphraseUuidMap.get(keyphraseId);
        if (uuid == null) {
            return;
        }
        mModelDataMap.remove(uuid);
        mKeyphraseUuidMap.remove(keyphraseId);
    }

    private ModelData getKeyphraseModelDataLocked(int keyphraseId) {
        UUID uuid = mKeyphraseUuidMap.get(keyphraseId);
        if (uuid == null) {
            return null;
        }
        return mModelDataMap.get(uuid);
    }

    // Use this to create a new ModelData entry for a keyphrase Id. It will overwrite existing
    // mapping if one exists.
    private ModelData createKeyphraseModelDataLocked(UUID modelId, int keyphraseId) {
        mKeyphraseUuidMap.remove(keyphraseId);
        mModelDataMap.remove(modelId);
        mKeyphraseUuidMap.put(keyphraseId, modelId);
        ModelData modelData = ModelData.createKeyphraseModelData(modelId);
        mModelDataMap.put(modelId, modelData);
        return modelData;
    }

    // Instead of maintaining a second hashmap of modelHandle -> ModelData, we just
    // iterate through to find the right object (since we don't expect 100s of models
    // to be stored).
    private ModelData getModelDataForLocked(int modelHandle) {
        // Fetch ModelData object corresponding to the model handle.
        for (ModelData model : mModelDataMap.values()) {
            if (model.getHandle() == modelHandle) {
                return model;
            }
        }
        return null;
    }

    // Whether we are allowed to run any recognition at all. The conditions that let us run
    // a recognition include: no active phone call or not being in a power save mode. Also,
    // the native service should be enabled.
    private boolean isRecognitionAllowed() {
        return !mCallActive && !mServiceDisabled && !mIsPowerSaveMode;
    }

    // A single routine that implements the start recognition logic for both generic and keyphrase
    // models.
    private int startRecognitionLocked(ModelData modelData, boolean notify) {
        IRecognitionStatusCallback callback = modelData.getCallback();
        int handle = modelData.getHandle();
        RecognitionConfig config = modelData.getRecognitionConfig();
        if (callback == null || handle == INVALID_VALUE || config == null) {
            // Nothing to do here.
            Slog.w(TAG, "startRecognition: Bad data passed in.");
            MetricsLogger.count(mContext, "sth_start_recognition_error", 1);
            return STATUS_ERROR;
        }

        if (!isRecognitionAllowed()) {
            // Nothing to do here.
            Slog.w(TAG, "startRecognition requested but not allowed.");
            MetricsLogger.count(mContext, "sth_start_recognition_not_allowed", 1);
            return STATUS_OK;
        }

        int status = mModule.startRecognition(handle, config);
        if (status != SoundTrigger.STATUS_OK) {
            Slog.w(TAG, "startRecognition failed with " + status);
            MetricsLogger.count(mContext, "sth_start_recognition_error", 1);
            // Notify of error if needed.
            if (notify) {
                try {
                    callback.onError(status);
                } catch (RemoteException e) {
                    Slog.w(TAG, "RemoteException in onError", e);
                }
            }
        } else {
            Slog.i(TAG, "startRecognition successful.");
            MetricsLogger.count(mContext, "sth_start_recognition_success", 1);
            modelData.setStarted();
            // Notify of resume if needed.
            if (notify) {
                try {
                    callback.onRecognitionResumed();
                } catch (RemoteException e) {
                    Slog.w(TAG, "RemoteException in onRecognitionResumed", e);
                }
            }
        }
        if (DBG) {
            Slog.d(TAG, "Model being started :" + modelData.toString());
        }
        return status;
    }

    private int stopRecognitionLocked(ModelData modelData, boolean notify) {
        IRecognitionStatusCallback callback = modelData.getCallback();

        // Stop recognition.
        int status = STATUS_OK;

        status = mModule.stopRecognition(modelData.getHandle());

        if (status != SoundTrigger.STATUS_OK) {
            Slog.w(TAG, "stopRecognition call failed with " + status);
            MetricsLogger.count(mContext, "sth_stop_recognition_error", 1);
            if (notify) {
                try {
                    callback.onError(status);
                } catch (RemoteException e) {
                    Slog.w(TAG, "RemoteException in onError", e);
                }
            }
        } else {
            modelData.setStopped();
            MetricsLogger.count(mContext, "sth_stop_recognition_success", 1);
            // Notify of pause if needed.
            if (notify) {
                try {
                    callback.onRecognitionPaused();
                } catch (RemoteException e) {
                    Slog.w(TAG, "RemoteException in onRecognitionPaused", e);
                }
            }
        }
        if (DBG) {
            Slog.d(TAG, "Model being stopped :" + modelData.toString());
        }
        return status;
    }

    private void dumpModelStateLocked() {
        for (UUID modelId : mModelDataMap.keySet()) {
            ModelData modelData = mModelDataMap.get(modelId);
            Slog.i(TAG, "Model :" + modelData.toString());
        }
    }

    // Computes whether we have any recognition running at all (voice or generic). Sets
    // the mRecognitionRunning variable with the result.
    private boolean computeRecognitionRunningLocked() {
        if (mModuleProperties == null || mModule == null) {
            mRecognitionRunning = false;
            return mRecognitionRunning;
        }
        for (ModelData modelData : mModelDataMap.values()) {
            if (modelData.isModelStarted()) {
                mRecognitionRunning = true;
                return mRecognitionRunning;
            }
        }
        mRecognitionRunning = false;
        return mRecognitionRunning;
    }

    // This class encapsulates the callbacks, state, handles and any other information that
    // represents a model.
    private static class ModelData {
        // Model not loaded (and hence not started).
        static final int MODEL_NOTLOADED = 0;

        // Loaded implies model was successfully loaded. Model not started yet.
        static final int MODEL_LOADED = 1;

        // Started implies model was successfully loaded and start was called.
        static final int MODEL_STARTED = 2;

        // One of MODEL_NOTLOADED, MODEL_LOADED, MODEL_STARTED (which implies loaded).
        private int mModelState;
        private UUID mModelId;

        // mRequested captures the explicit intent that a start was requested for this model. We
        // continue to capture and retain this state even after the model gets started, so that we
        // know when a model gets stopped due to "other" reasons, that we should start it again.
        // This was the intended behavior of the "mRequested" variable in the previous version of
        // this code that we are replicating here.
        //
        // The "other" reasons include power save, abort being called from the lower layer (due
        // to concurrent capture not being supported) and phone call state. Once we recover from
        // these transient disruptions, we would start such models again where mRequested == true.
        // Thus, mRequested gets reset only when there is an explicit intent to stop the model
        // coming from the SoundTriggerService layer that uses this class (and thus eventually
        // from the app that manages this model).
        private boolean mRequested = false;

        // One of SoundModel.TYPE_GENERIC or SoundModel.TYPE_KEYPHRASE. Initially set
        // to SoundModel.TYPE_UNKNOWN;
        private int mModelType = SoundModel.TYPE_UNKNOWN;

        private IRecognitionStatusCallback mCallback = null;
        private RecognitionConfig mRecognitionConfig = null;

        // Model handle is an integer used by the HAL as an identifier for sound
        // models.
        private int mModelHandle = INVALID_VALUE;

        // The SoundModel instance, one of KeyphraseSoundModel or GenericSoundModel.
        private SoundModel mSoundModel = null;

        private ModelData(UUID modelId, int modelType) {
            mModelId = modelId;
            // Private constructor, since we require modelType to be one of TYPE_GENERIC,
            // TYPE_KEYPHRASE or TYPE_UNKNOWN.
            mModelType = modelType;
        }

        static ModelData createKeyphraseModelData(UUID modelId) {
            return new ModelData(modelId, SoundModel.TYPE_KEYPHRASE);
        }

        static ModelData createGenericModelData(UUID modelId) {
            return new ModelData(modelId, SoundModel.TYPE_GENERIC_SOUND);
        }

        // Note that most of the functionality in this Java class will not work for
        // SoundModel.TYPE_UNKNOWN nevertheless we have it since lower layers support it.
        static ModelData createModelDataOfUnknownType(UUID modelId) {
            return new ModelData(modelId, SoundModel.TYPE_UNKNOWN);
        }

        synchronized void setCallback(IRecognitionStatusCallback callback) {
            mCallback = callback;
        }

        synchronized IRecognitionStatusCallback getCallback() {
            return mCallback;
        }

        synchronized boolean isModelLoaded() {
            return (mModelState == MODEL_LOADED || mModelState == MODEL_STARTED);
        }

        synchronized boolean isModelNotLoaded() {
            return mModelState == MODEL_NOTLOADED;
        }

        synchronized void setStarted() {
            mModelState = MODEL_STARTED;
        }

        synchronized void setStopped() {
            mModelState = MODEL_LOADED;
        }

        synchronized void setLoaded() {
            mModelState = MODEL_LOADED;
        }

        synchronized boolean isModelStarted() {
            return mModelState == MODEL_STARTED;
        }

        synchronized void clearState() {
            mModelState = MODEL_NOTLOADED;
            mModelHandle = INVALID_VALUE;
            mRecognitionConfig = null;
            mRequested = false;
            mCallback = null;
        }

        synchronized void clearCallback() {
            mCallback = null;
        }

        synchronized void setHandle(int handle) {
            mModelHandle = handle;
        }

        synchronized void setRecognitionConfig(RecognitionConfig config) {
            mRecognitionConfig = config;
        }

        synchronized int getHandle() {
            return mModelHandle;
        }

        synchronized UUID getModelId() {
            return mModelId;
        }

        synchronized RecognitionConfig getRecognitionConfig() {
            return mRecognitionConfig;
        }

        // Whether a start recognition was requested.
        synchronized boolean isRequested() {
            return mRequested;
        }

        synchronized void setRequested(boolean requested) {
            mRequested = requested;
        }

        synchronized void setSoundModel(SoundModel soundModel) {
            mSoundModel = soundModel;
        }

        synchronized SoundModel getSoundModel() {
            return mSoundModel;
        }

        synchronized int getModelType() {
            return mModelType;
        }

        synchronized boolean isKeyphraseModel() {
            return mModelType == SoundModel.TYPE_KEYPHRASE;
        }

        synchronized boolean isGenericModel() {
            return mModelType == SoundModel.TYPE_GENERIC_SOUND;
        }

        synchronized String stateToString() {
            switch(mModelState) {
                case MODEL_NOTLOADED: return "NOT_LOADED";
                case MODEL_LOADED: return "LOADED";
                case MODEL_STARTED: return "STARTED";
            }
            return "Unknown state";
        }

        synchronized String requestedToString() {
            return "Requested: " + (mRequested ? "Yes" : "No");
        }

        synchronized String callbackToString() {
            return "Callback: " + (mCallback != null ? mCallback.asBinder() : "null");
        }

        synchronized String uuidToString() {
            return "UUID: " + mModelId;
        }

        synchronized public String toString() {
            return "Handle: " + mModelHandle + "\n" +
                    "ModelState: " + stateToString() + "\n" +
                    requestedToString() + "\n" +
                    callbackToString() + "\n" +
                    uuidToString() + "\n" + modelTypeToString();
        }

        synchronized String modelTypeToString() {
            String type = null;
            switch (mModelType) {
                case SoundModel.TYPE_GENERIC_SOUND: type = "Generic"; break;
                case SoundModel.TYPE_UNKNOWN: type = "Unknown"; break;
                case SoundModel.TYPE_KEYPHRASE: type = "Keyphrase"; break;
            }
            return "Model type: " + type + "\n";
        }
    }
}
