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

import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_EXT_ROUTING_HINT;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_FOCUS;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_HW_VARIANT;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_PARAMETERS;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_ROUTING_POLICY;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_STREAM_STATE;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_VOLUME;
import static android.hardware.automotive.vehicle.V2_0.VehicleProperty.AUDIO_VOLUME_LIMIT;
import static com.android.car.CarServiceUtils.toIntArray;

import android.annotation.Nullable;
import android.car.VehicleZoneUtil;
import android.car.media.CarAudioManager;
import android.car.media.CarAudioManager.OnParameterChangeListener;
import android.hardware.automotive.vehicle.V2_0.SubscribeFlags;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioContextFlag;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioExtFocusFlag;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusRequest;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioFocusState;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioHwVariantConfigFlag;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioRoutingPolicyIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeCapabilityFlag;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleAudioVolumeLimitIndex;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.text.TextUtils;
import android.util.Log;

import com.android.car.AudioRoutingPolicy;
import com.android.car.CarAudioAttributesUtil;
import com.android.car.CarLog;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AudioHalService extends HalServiceBase {
    public static final int VEHICLE_AUDIO_FOCUS_REQUEST_INVALID = -1;
    public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN =
            VehicleAudioFocusRequest.REQUEST_GAIN;
    public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT =
            VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT;
    public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK =
            VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_MAY_DUCK;
    public static final int VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_NO_DUCK =
            VehicleAudioFocusRequest.REQUEST_GAIN_TRANSIENT_NO_DUCK;
    public static final int VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE =
            VehicleAudioFocusRequest.REQUEST_RELEASE;

    public static final int VEHICLE_AUDIO_FOCUS_STATE_INVALID = -1;
    public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN =
            VehicleAudioFocusState.STATE_GAIN;
    public static final int VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT =
            VehicleAudioFocusState.STATE_GAIN_TRANSIENT;
    public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_CAN_DUCK =
            VehicleAudioFocusState.STATE_LOSS_TRANSIENT_CAN_DUCK;
    public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT =
            VehicleAudioFocusState.STATE_LOSS_TRANSIENT;
    public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS =
            VehicleAudioFocusState.STATE_LOSS;
    public static final int VEHICLE_AUDIO_FOCUS_STATE_LOSS_TRANSIENT_EXLCUSIVE =
            VehicleAudioFocusState.STATE_LOSS_TRANSIENT_EXLCUSIVE;

    public static final int VEHICLE_AUDIO_STREAM_STATE_STOPPED = 0;
    public static final int VEHICLE_AUDIO_STREAM_STATE_STARTED = 1;

    public static final int VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG =
            VehicleAudioExtFocusFlag.NONE_FLAG;
    public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG =
            VehicleAudioExtFocusFlag.PERMANENT_FLAG;
    public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_TRANSIENT_FLAG =
            VehicleAudioExtFocusFlag.TRANSIENT_FLAG;
    public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG =
            VehicleAudioExtFocusFlag.PLAY_ONLY_FLAG;
    public static final int VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG =
            VehicleAudioExtFocusFlag.MUTE_MEDIA_FLAG;

    public static final int STREAM_NUM_DEFAULT = 0;

    public static final int FOCUS_STATE_ARRAY_INDEX_STATE = 0;
    public static final int FOCUS_STATE_ARRAY_INDEX_STREAMS = 1;
    public static final int FOCUS_STATE_ARRAY_INDEX_EXTERNAL_FOCUS = 2;

    public static final int AUDIO_CONTEXT_MUSIC_FLAG =
            VehicleAudioContextFlag.MUSIC_FLAG;
    public static final int AUDIO_CONTEXT_NAVIGATION_FLAG =
            VehicleAudioContextFlag.NAVIGATION_FLAG;
    public static final int AUDIO_CONTEXT_VOICE_COMMAND_FLAG =
            VehicleAudioContextFlag.VOICE_COMMAND_FLAG;
    public static final int AUDIO_CONTEXT_CALL_FLAG =
            VehicleAudioContextFlag.CALL_FLAG;
    public static final int AUDIO_CONTEXT_ALARM_FLAG =
            VehicleAudioContextFlag.ALARM_FLAG;
    public static final int AUDIO_CONTEXT_NOTIFICATION_FLAG =
            VehicleAudioContextFlag.NOTIFICATION_FLAG;
    public static final int AUDIO_CONTEXT_UNKNOWN_FLAG =
            VehicleAudioContextFlag.UNKNOWN_FLAG;
    public static final int AUDIO_CONTEXT_SAFETY_ALERT_FLAG =
            VehicleAudioContextFlag.SAFETY_ALERT_FLAG;
    public static final int AUDIO_CONTEXT_RADIO_FLAG =
            VehicleAudioContextFlag.RADIO_FLAG;
    public static final int AUDIO_CONTEXT_CD_ROM_FLAG =
            VehicleAudioContextFlag.CD_ROM_FLAG;
    public static final int AUDIO_CONTEXT_AUX_AUDIO_FLAG =
            VehicleAudioContextFlag.AUX_AUDIO_FLAG;
    public static final int AUDIO_CONTEXT_SYSTEM_SOUND_FLAG =
            VehicleAudioContextFlag.SYSTEM_SOUND_FLAG;
    public static final int AUDIO_CONTEXT_EXT_SOURCE_FLAG =
            VehicleAudioContextFlag.EXT_SOURCE_FLAG;

    public interface AudioHalFocusListener {
        /**
         * Audio focus change from car.
         * @param focusState
         * @param streams
         * @param externalFocus Flags of active external audio focus.
         *            0 means no external audio focus.
         */
        void onFocusChange(int focusState, int streams, int externalFocus);
        /**
         * Stream state change (start / stop) from android
         * @param streamNumber stream number like 0, 1, ...
         * @param streamActive Whether the stream is active or not.
         */
        void onStreamStatusChange(int streamNumber, boolean streamActive);
    }

    public interface AudioHalVolumeListener {
        /**
         * Audio volume change from car.
         * @param streamNumber
         * @param volume
         * @param volumeState
         */
        void onVolumeChange(int streamNumber, int volume, int volumeState);
        /**
         * Volume limit change from car.
         * @param streamNumber
         * @param volume
         */
        void onVolumeLimitChange(int streamNumber, int volume);
    }

    private static final boolean DBG = false;

    private final VehicleHal mVehicleHal;
    private AudioHalFocusListener mFocusListener;
    private AudioHalVolumeListener mVolumeListener;
    private int mVariant;

    private final HashMap<Integer, VehiclePropConfig> mProperties = new HashMap<>();

    private OnParameterChangeListener mOnParameterChangeListener;

    public AudioHalService(VehicleHal vehicleHal) {
        mVehicleHal = vehicleHal;
    }

    public synchronized void setFocusListener(AudioHalFocusListener focusListener) {
        mFocusListener = focusListener;
    }

    public synchronized void setVolumeListener(AudioHalVolumeListener volumeListener) {
        mVolumeListener = volumeListener;
    }

    public void setAudioRoutingPolicy(AudioRoutingPolicy policy) {
        if (!mVehicleHal.isPropertySupported(VehicleProperty.AUDIO_ROUTING_POLICY)) {
            Log.w(CarLog.TAG_AUDIO,
                    "Vehicle HAL did not implement VehicleProperty.AUDIO_ROUTING_POLICY");
            return;
        }
        int[] policyToSet = new int[2];
        for (int i = 0; i < policy.getPhysicalStreamsCount(); i++) {
            policyToSet[VehicleAudioRoutingPolicyIndex.STREAM] = i;
            int contexts = 0;
            for (int logicalStream : policy.getLogicalStreamsForPhysicalStream(i)) {
                contexts |= logicalStreamToHalContextType(logicalStream);
            }
            policyToSet[VehicleAudioRoutingPolicyIndex.CONTEXTS] = contexts;
            try {
                mVehicleHal.set(AUDIO_ROUTING_POLICY).to(policyToSet);
            } catch (PropertyTimeoutException e) {
                Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_ROUTING_POLICY", e);
            }
        }
    }

    /**
     * Returns the volume limits of a stream. Returns null if max value wasn't defined for
     * AUDIO_VOLUME property.
     */
    @Nullable
    public synchronized Integer getStreamMaxVolume(int stream) {
        VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_VOLUME);
        if (config == null) {
            throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
        }
        int supportedContext = getSupportedAudioVolumeContexts();

        int MAX_VALUES_FIRST_ELEMENT_INDEX = 4;
        ArrayList<Integer> maxValues = new ArrayList<>();
        for (int i = MAX_VALUES_FIRST_ELEMENT_INDEX; i < config.configArray.size(); i++) {
            maxValues.add(config.configArray.get(i));
        }

        Integer result = null;
        if (supportedContext != 0) {
            int index = VehicleZoneUtil.zoneToIndex(supportedContext, stream);
            if (index < maxValues.size()) {
                result = maxValues.get(index);
            }
        } else {
            if (stream < maxValues.size()) {
                result = maxValues.get(stream);
            }
        }

        if (result == null) {
            Log.e(CarLog.TAG_AUDIO, "No min/max volume found in vehicle" +
                    " prop config for stream: " + stream);
        }

        return result;
    }

    /**
     * Convert car audio manager stream type (usage) into audio context type.
     */
    public static int logicalStreamToHalContextType(int logicalStream) {
        return logicalStreamWithExtTypeToHalContextType(logicalStream, null);
    }

    public static int logicalStreamWithExtTypeToHalContextType(int logicalStream, String extType) {
        switch (logicalStream) {
            case CarAudioManager.CAR_AUDIO_USAGE_RADIO:
                return VehicleAudioContextFlag.RADIO_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL:
                return VehicleAudioContextFlag.CALL_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_MUSIC:
                return VehicleAudioContextFlag.MUSIC_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE:
                return VehicleAudioContextFlag.NAVIGATION_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND:
                return VehicleAudioContextFlag.VOICE_COMMAND_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_ALARM:
                return VehicleAudioContextFlag.ALARM_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION:
                return VehicleAudioContextFlag.NOTIFICATION_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT:
                return VehicleAudioContextFlag.SAFETY_ALERT_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND:
                return VehicleAudioContextFlag.SYSTEM_SOUND_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_DEFAULT:
                return VehicleAudioContextFlag.UNKNOWN_FLAG;
            case CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE:
                if (extType != null) {
                    switch (extType) {
                    case CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_CD_DVD:
                        return AudioHalService.AUDIO_CONTEXT_CD_ROM_FLAG;
                    case CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_AUX_IN0:
                    case CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_AUX_IN1:
                        return AudioHalService.AUDIO_CONTEXT_AUX_AUDIO_FLAG;
                    default:
                        if (extType.startsWith("RADIO_")) {
                            return VehicleAudioContextFlag.RADIO_FLAG;
                        } else {
                            return AudioHalService.AUDIO_CONTEXT_EXT_SOURCE_FLAG;
                        }
                    }
                } else { // no external source specified. fall back to radio
                    return VehicleAudioContextFlag.RADIO_FLAG;
                }
            case CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_BOTTOM:
            case CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_CAR_PROXY:
            case CarAudioAttributesUtil.CAR_AUDIO_USAGE_CARSERVICE_MEDIA_MUTE:
                // internal tag not associated with any stream
                return 0;
            default:
                Log.w(CarLog.TAG_AUDIO, "Unknown logical stream:" + logicalStream);
                return 0;
        }
    }

    /**
     * Converts car audio context type to car stream usage.
     */
    public static int carContextToCarUsage(int carContext) {
        switch (carContext) {
            case VehicleAudioContextFlag.MUSIC_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_MUSIC;
            case VehicleAudioContextFlag.NAVIGATION_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE;
            case VehicleAudioContextFlag.ALARM_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_ALARM;
            case VehicleAudioContextFlag.VOICE_COMMAND_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_VOICE_COMMAND;
            case VehicleAudioContextFlag.AUX_AUDIO_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
            case VehicleAudioContextFlag.CALL_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_VOICE_CALL;
            case VehicleAudioContextFlag.CD_ROM_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
            case VehicleAudioContextFlag.NOTIFICATION_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_NOTIFICATION;
            case VehicleAudioContextFlag.RADIO_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_RADIO;
            case VehicleAudioContextFlag.SAFETY_ALERT_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SAFETY_ALERT;
            case VehicleAudioContextFlag.SYSTEM_SOUND_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_SYSTEM_SOUND;
            case VehicleAudioContextFlag.UNKNOWN_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_DEFAULT;
            case VehicleAudioContextFlag.EXT_SOURCE_FLAG:
                return CarAudioManager.CAR_AUDIO_USAGE_EXTERNAL_AUDIO_SOURCE;
            default:
                Log.w(CarLog.TAG_AUDIO, "Unknown car context:" + carContext);
                return 0;
        }
    }

    public void requestAudioFocusChange(int request, int streams, int audioContexts) {
        requestAudioFocusChange(request, streams, VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG, audioContexts);
    }

    public void requestAudioFocusChange(int request, int streams, int extFocus, int audioContexts) {
        int[] payload = { request, streams, extFocus, audioContexts };
        try {
            mVehicleHal.set(AUDIO_FOCUS).to(payload);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_FOCUS", e);
            // focus timeout will reset it anyway
        }
    }

    public void setStreamVolume(int streamType, int index) {
        int[] payload = {streamType, index, 0};
        try {
            mVehicleHal.set(VehicleProperty.AUDIO_VOLUME).to(payload);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_VOLUME", e);
            //TODO should reset volume, bug: 32096870
        }
    }

    public int getStreamVolume(int stream) {
        int[] volume = {stream, 0, 0};
        VehiclePropValue requestedStreamVolume = new VehiclePropValue();
        requestedStreamVolume.prop = VehicleProperty.AUDIO_VOLUME;
        requestedStreamVolume.value.int32Values.addAll(Arrays.asList(stream, 0 , 0));
        VehiclePropValue propValue;
        try {
            propValue = mVehicleHal.get(requestedStreamVolume);
        }  catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_VOLUME not ready", e);
            return 0;
        }

        if (propValue.value.int32Values.size() != 3) {
            Log.e(CarLog.TAG_AUDIO, "returned value not valid");
            throw new IllegalStateException("Invalid preset returned from service: "
                    + Arrays.toString(propValue.value.int32Values.toArray()));
        }

        int retStreamNum = propValue.value.int32Values.get(0);
        int retVolume = propValue.value.int32Values.get(1);
        int retVolumeState = propValue.value.int32Values.get(2);

        if (retStreamNum != stream) {
            Log.e(CarLog.TAG_AUDIO, "Stream number is not the same: "
                    + stream + " vs " + retStreamNum);
            throw new IllegalStateException("Stream number is not the same");
        }
        return retVolume;
    }

    public synchronized int getHwVariant() {
        return mVariant;
    }

    public synchronized boolean isRadioExternal() {
        VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_HW_VARIANT);
        if (config == null) {
            return true;
        }
        return (config.configArray.get(0)
                & VehicleAudioHwVariantConfigFlag.INTERNAL_RADIO_FLAG) == 0;
    }

    public synchronized boolean isFocusSupported() {
        return isPropertySupportedLocked(AUDIO_FOCUS);
    }

    public synchronized boolean isAudioVolumeSupported() {
        return isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME);
    }

    public synchronized int getSupportedAudioVolumeContexts() {
        if (!isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME)) {
            throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
        }
        VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_VOLUME);
        return config.configArray.get(0);
    }

    /**
     * Whether external audio module can memorize logical audio volumes or not.
     * @return
     */
    public synchronized boolean isExternalAudioVolumePersistent() {
        if (!isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME)) {
            throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
        }
        VehiclePropConfig config = mProperties.get(VehicleProperty.AUDIO_VOLUME);
        if (config.configArray.get(0) == 0) { // physical streams only
            return false;
        }
        if ((config.configArray.get(1)
                & VehicleAudioVolumeCapabilityFlag.PERSISTENT_STORAGE) != 0) {
            return true;
        }
        return false;
    }

    public synchronized boolean isAudioVolumeLimitSupported() {
        return isPropertySupportedLocked(AUDIO_VOLUME_LIMIT);
    }

    public synchronized boolean isAudioVolumeMasterOnly() {
        if (!isPropertySupportedLocked(VehicleProperty.AUDIO_VOLUME)) {
            throw new IllegalStateException("VehicleProperty.AUDIO_VOLUME not supported");
        }
        VehiclePropConfig config = mProperties.get(
                AUDIO_VOLUME);
        if ((config.configArray.get(1) &
                VehicleAudioVolumeCapabilityFlag.MASTER_VOLUME_ONLY)
                != 0) {
            return true;
        }
        return false;
    }

    /**
     * Get the current audio focus state.
     * @return 0: focusState, 1: streams, 2: externalFocus
     */
    public int[] getCurrentFocusState() {
        if (!isFocusSupported()) {
            return new int[] { VEHICLE_AUDIO_FOCUS_STATE_GAIN, 0xffffffff, 0};
        }
        try {
            VehiclePropValue propValue = mVehicleHal.get(VehicleProperty.AUDIO_FOCUS);
            return toIntArray(propValue.value.int32Values);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_HW_VARIANT not ready", e);
            return new int[] { VEHICLE_AUDIO_FOCUS_STATE_LOSS, 0x0, 0};
        }
    }

    public static class ExtRoutingSourceInfo {
        /** Represents an external route which will not disable any physical stream in android side.
         */
        public static final int NO_DISABLED_PHYSICAL_STREAM = -1;

        /** Bit position of this source in vhal */
        public final int bitPosition;
        /**
         * Physical stream replaced by this routing. will be {@link #NO_DISABLED_PHYSICAL_STREAM}
         * if no physical stream for android is replaced by this routing.
         */
        public final int physicalStreamNumber;

        public ExtRoutingSourceInfo(int bitPosition, int physycalStreamNumber) {
            this.bitPosition = bitPosition;
            this.physicalStreamNumber = physycalStreamNumber;
        }

        @Override
        public String toString() {
            return "[bitPosition=" + bitPosition + ", physicalStreamNumber="
                    + physicalStreamNumber + "]";
        }
    }

    /**
     * Get external audio routing types from AUDIO_EXT_ROUTING_HINT property.
     *
     * @return null if AUDIO_EXT_ROUTING_HINT is not supported.
     */
    public Map<String, ExtRoutingSourceInfo> getExternalAudioRoutingTypes() {
        VehiclePropConfig config;
        synchronized (this) {
            if (!isPropertySupportedLocked(AUDIO_EXT_ROUTING_HINT)) {
                if (DBG) {
                    Log.i(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT is not supported");
                }
                return null;
            }
            config = mProperties.get(AUDIO_EXT_ROUTING_HINT);
        }
        if (TextUtils.isEmpty(config.configString)) {
            Log.w(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT with empty config string");
            return null;
        }
        Map<String, ExtRoutingSourceInfo> routingTypes = new HashMap<>();
        String configString = config.configString;
        if (DBG) {
            Log.i(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT config string:" + configString);
        }
        String[] routes = configString.split(",");
        for (String routeString : routes) {
            String[] tokens = routeString.split(":");
            int bitPosition = 0;
            String name = null;
            int physicalStreamNumber = ExtRoutingSourceInfo.NO_DISABLED_PHYSICAL_STREAM;
            if (tokens.length == 2) {
                bitPosition = Integer.parseInt(tokens[0]);
                name = tokens[1];
            } else if (tokens.length == 3) {
                bitPosition = Integer.parseInt(tokens[0]);
                name = tokens[1];
                physicalStreamNumber = Integer.parseInt(tokens[2]);
            } else {
                Log.w(CarLog.TAG_AUDIO, "AUDIO_EXT_ROUTING_HINT has wrong entry:" +
                        routeString);
                continue;
            }
            routingTypes.put(name, new ExtRoutingSourceInfo(bitPosition, physicalStreamNumber));
        }
        return routingTypes;
    }

    public void setExternalRoutingSource(int[] externalRoutings) {
        try {
            mVehicleHal.set(AUDIO_EXT_ROUTING_HINT).to(externalRoutings);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_EXT_ROUTING_HINT", e);
        }
    }

    private boolean isPropertySupportedLocked(int property) {
        VehiclePropConfig config = mProperties.get(property);
        return config != null;
    }

    @Override
    public synchronized void init() {
        for (VehiclePropConfig config : mProperties.values()) {
            if (VehicleHal.isPropertySubscribable(config)) {
                int subsribeFlag = SubscribeFlags.HAL_EVENT;
                if (AUDIO_STREAM_STATE == config.prop) {
                    subsribeFlag |= SubscribeFlags.SET_CALL;
                }
                mVehicleHal.subscribeProperty(this, config.prop, 0, subsribeFlag);
            }
        }
        try {
            mVariant = mVehicleHal.get(int.class, AUDIO_HW_VARIANT);
        } catch (IllegalArgumentException e) {
            // no variant. Set to default, 0.
            mVariant = 0;
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_HW_VARIANT not ready", e);
            mVariant = 0;
        }
    }

    @Override
    public synchronized void release() {
        for (VehiclePropConfig config : mProperties.values()) {
            if (VehicleHal.isPropertySubscribable(config)) {
                mVehicleHal.unsubscribeProperty(this, config.prop);
            }
        }
        mProperties.clear();
    }

    @Override
    public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
            Collection<VehiclePropConfig> allProperties) {
        for (VehiclePropConfig p : allProperties) {
            switch (p.prop) {
                case VehicleProperty.AUDIO_FOCUS:
                case VehicleProperty.AUDIO_VOLUME:
                case VehicleProperty.AUDIO_VOLUME_LIMIT:
                case VehicleProperty.AUDIO_HW_VARIANT:
                case VehicleProperty.AUDIO_EXT_ROUTING_HINT:
                case VehicleProperty.AUDIO_PARAMETERS:
                case VehicleProperty.AUDIO_STREAM_STATE:
                    mProperties.put(p.prop, p);
                    break;
            }
        }
        return new ArrayList<>(mProperties.values());
    }

    @Override
    public void handleHalEvents(List<VehiclePropValue> values) {
        AudioHalFocusListener focusListener;
        AudioHalVolumeListener volumeListener;
        OnParameterChangeListener parameterListener;
        synchronized (this) {
            focusListener = mFocusListener;
            volumeListener = mVolumeListener;
            parameterListener = mOnParameterChangeListener;
        }
        dispatchEventToListener(focusListener, volumeListener, parameterListener, values);
    }

    public String[] getAudioParameterKeys() {
        VehiclePropConfig config;
        synchronized (this) {
            if (!isPropertySupportedLocked(AUDIO_PARAMETERS)) {
                if (DBG) {
                    Log.i(CarLog.TAG_AUDIO, "AUDIO_PARAMETERS is not supported");
                }
                return null;
            }
            config = mProperties.get(AUDIO_PARAMETERS);
        }
        return config.configString.split(";");
    }

    public void setAudioParameters(String parameters) {
        synchronized (this) {
            if (!isPropertySupportedLocked(AUDIO_PARAMETERS)) {
                throw new IllegalStateException("VehicleProperty.AUDIO_PARAMETERS not supported");
            }
        }
        VehiclePropValue value = new VehiclePropValue();
        value.prop = AUDIO_PARAMETERS;
        value.value.stringValue = parameters;
        try {
            mVehicleHal.set(value);
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "Cannot write to VehicleProperty.AUDIO_EXT_ROUTING_HINT", e);
        }
    }

    public String getAudioParameters(String keys) {
        synchronized (this) {
            if (!isPropertySupportedLocked(AUDIO_PARAMETERS)) {
                throw new IllegalStateException("VehicleProperty.AUDIO_PARAMETERS not supported");
            }
        }
        try {
            VehiclePropValue requested = new VehiclePropValue();
            requested.prop = AUDIO_PARAMETERS;
            requested.value.stringValue = keys;
            VehiclePropValue propValue = mVehicleHal.get(requested);
            return propValue.value.stringValue;
        } catch (PropertyTimeoutException e) {
            Log.e(CarLog.TAG_AUDIO, "VehicleProperty.AUDIO_PARAMETERS not ready", e);
            return new String("");
        }
    }

    public synchronized void setOnParameterChangeListener(OnParameterChangeListener listener) {
        mOnParameterChangeListener = listener;
    }

    private void dispatchEventToListener(AudioHalFocusListener focusListener,
            AudioHalVolumeListener volumeListener,
            OnParameterChangeListener parameterListener,
            List<VehiclePropValue> values) {
        for (VehiclePropValue v : values) {
            switch (v.prop) {
                case VehicleProperty.AUDIO_FOCUS: {
                    ArrayList<Integer> vec = v.value.int32Values;
                    int focusState = vec.get(VehicleAudioFocusIndex.FOCUS);
                    int streams = vec.get(VehicleAudioFocusIndex.STREAMS);
                    int externalFocus = vec.get(VehicleAudioFocusIndex.EXTERNAL_FOCUS_STATE);
                    if (focusListener != null) {
                        focusListener.onFocusChange(focusState, streams, externalFocus);
                    }
                } break;
                case VehicleProperty.AUDIO_STREAM_STATE: {
                    ArrayList<Integer> vec = v.value.int32Values;
                    boolean streamStarted = vec.get(0) == VEHICLE_AUDIO_STREAM_STATE_STARTED;
                    int streamNum = vec.get(1);
                    if (focusListener != null) {
                        focusListener.onStreamStatusChange(streamNum, streamStarted);
                    }
                } break;
                case AUDIO_VOLUME: {
                    ArrayList<Integer> vec = v.value.int32Values;
                    int volume = vec.get(VehicleAudioVolumeIndex.INDEX_VOLUME);
                    int streamNum = vec.get(VehicleAudioVolumeIndex.INDEX_STREAM);
                    int volumeState = vec.get(VehicleAudioVolumeIndex.INDEX_STATE);
                    if (volumeListener != null) {
                        volumeListener.onVolumeChange(streamNum, volume, volumeState);
                    }
                } break;
                case AUDIO_VOLUME_LIMIT: {
                    ArrayList<Integer> vec = v.value.int32Values;
                    int stream = vec.get(VehicleAudioVolumeLimitIndex.STREAM);
                    int maxVolume = vec.get(VehicleAudioVolumeLimitIndex.MAX_VOLUME);
                    if (volumeListener != null) {
                        volumeListener.onVolumeLimitChange(stream, maxVolume);
                    }
                } break;
                case AUDIO_PARAMETERS: {
                    String params = v.value.stringValue;
                    if (parameterListener != null) {
                        parameterListener.onParameterChange(params);
                    }
                }
            }
        }
        values.clear();
    }

    @Override
    public void dump(PrintWriter writer) {
        writer.println("*Audio HAL*");
        writer.println(" audio H/W variant:" + mVariant);
        writer.println(" Supported properties");
        VehicleHal.dumpProperties(writer, mProperties.values());
    }

}
