/*
 * 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 an
 * limitations under the License.
 */

package com.android.server.usb;

import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.midi.MidiDeviceInfo;
import android.os.Bundle;
import android.os.FileObserver;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Slog;

import com.android.internal.alsa.AlsaCardsParser;
import com.android.internal.alsa.AlsaDevicesParser;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.audio.AudioService;

import libcore.io.IoUtils;

import java.io.File;
import java.util.HashMap;

/**
 * UsbAlsaManager manages USB audio and MIDI devices.
 */
public final class UsbAlsaManager {
    private static final String TAG = UsbAlsaManager.class.getSimpleName();
    private static final boolean DEBUG = false;

    private static final String ALSA_DIRECTORY = "/dev/snd/";

    private final Context mContext;
    private IAudioService mAudioService;
    private final boolean mHasMidiFeature;

    private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
    private final AlsaDevicesParser mDevicesParser = new AlsaDevicesParser();

    // this is needed to map USB devices to ALSA Audio Devices, especially to remove an
    // ALSA device when we are notified that its associated USB device has been removed.

    private final HashMap<UsbDevice,UsbAudioDevice>
        mAudioDevices = new HashMap<UsbDevice,UsbAudioDevice>();

    private boolean mIsInputHeadset; // as reported by UsbDescriptorParser
    private boolean mIsOutputHeadset; // as reported by UsbDescriptorParser

    private final HashMap<UsbDevice,UsbMidiDevice>
        mMidiDevices = new HashMap<UsbDevice,UsbMidiDevice>();

    private final HashMap<String,AlsaDevice>
        mAlsaDevices = new HashMap<String,AlsaDevice>();

    private UsbAudioDevice mAccessoryAudioDevice = null;

    // UsbMidiDevice for USB peripheral mode (gadget) device
    private UsbMidiDevice mPeripheralMidiDevice = null;

    private final class AlsaDevice {
        public static final int TYPE_UNKNOWN = 0;
        public static final int TYPE_PLAYBACK = 1;
        public static final int TYPE_CAPTURE = 2;
        public static final int TYPE_MIDI = 3;

        public int mCard;
        public int mDevice;
        public int mType;

        public AlsaDevice(int type, int card, int device) {
            mType = type;
            mCard = card;
            mDevice = device;
        }

        public boolean equals(Object obj) {
            if (! (obj instanceof AlsaDevice)) {
                return false;
            }
            AlsaDevice other = (AlsaDevice)obj;
            return (mType == other.mType && mCard == other.mCard && mDevice == other.mDevice);
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("AlsaDevice: [card: " + mCard);
            sb.append(", device: " + mDevice);
            sb.append(", type: " + mType);
            sb.append("]");
            return sb.toString();
        }
    }

    private final FileObserver mAlsaObserver = new FileObserver(ALSA_DIRECTORY,
            FileObserver.CREATE | FileObserver.DELETE) {
        public void onEvent(int event, String path) {
            switch (event) {
                case FileObserver.CREATE:
                    alsaFileAdded(path);
                    break;
                case FileObserver.DELETE:
                    alsaFileRemoved(path);
                    break;
            }
        }
    };

    /* package */ UsbAlsaManager(Context context) {
        mContext = context;
        mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);

        // initial scan
        mCardsParser.scan();
    }

    public void systemReady() {
        mAudioService = IAudioService.Stub.asInterface(
                        ServiceManager.getService(Context.AUDIO_SERVICE));

        mAlsaObserver.startWatching();

        // add existing alsa devices
        File[] files = new File(ALSA_DIRECTORY).listFiles();
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                alsaFileAdded(files[i].getName());
            }
        }
    }

    // Notifies AudioService when a device is added or removed
    // audioDevice - the AudioDevice that was added or removed
    // enabled - if true, we're connecting a device (it's arrived), else disconnecting
    private void notifyDeviceState(UsbAudioDevice audioDevice, boolean enabled) {
        if (DEBUG) {
            Slog.d(TAG, "notifyDeviceState " + enabled + " " + audioDevice);
        }

        if (mAudioService == null) {
            Slog.e(TAG, "no AudioService");
            return;
        }

        // FIXME Does not yet handle the case where the setting is changed
        // after device connection.  Ideally we should handle the settings change
        // in SettingsObserver. Here we should log that a USB device is connected
        // and disconnected with its address (card , device) and force the
        // connection or disconnection when the setting changes.
        int isDisabled = Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.USB_AUDIO_AUTOMATIC_ROUTING_DISABLED, 0);
        if (isDisabled != 0) {
            return;
        }

        int state = (enabled ? 1 : 0);
        int alsaCard = audioDevice.mCard;
        int alsaDevice = audioDevice.mDevice;
        if (alsaCard < 0 || alsaDevice < 0) {
            Slog.e(TAG, "Invalid alsa card or device alsaCard: " + alsaCard +
                        " alsaDevice: " + alsaDevice);
            return;
        }

        String address = AudioService.makeAlsaAddressString(alsaCard, alsaDevice);
        try {
            // Playback Device
            if (audioDevice.mHasPlayback) {
                int device;
                if (mIsOutputHeadset) {
                    device = AudioSystem.DEVICE_OUT_USB_HEADSET;
                } else {
                    device = (audioDevice == mAccessoryAudioDevice
                        ? AudioSystem.DEVICE_OUT_USB_ACCESSORY
                        : AudioSystem.DEVICE_OUT_USB_DEVICE);
                }
                if (DEBUG) {
                    Slog.i(TAG, "pre-call device:0x" + Integer.toHexString(device) +
                            " addr:" + address + " name:" + audioDevice.getDeviceName());
                }
                mAudioService.setWiredDeviceConnectionState(
                        device, state, address, audioDevice.getDeviceName(), TAG);
            }

            // Capture Device
            if (audioDevice.mHasCapture) {
                int device;
                if (mIsInputHeadset) {
                    device = AudioSystem.DEVICE_IN_USB_HEADSET;
                } else {
                    device = (audioDevice == mAccessoryAudioDevice
                        ? AudioSystem.DEVICE_IN_USB_ACCESSORY
                        : AudioSystem.DEVICE_IN_USB_DEVICE);
                }
                mAudioService.setWiredDeviceConnectionState(
                        device, state, address, audioDevice.getDeviceName(), TAG);
            }
        } catch (RemoteException e) {
            Slog.e(TAG, "RemoteException in setWiredDeviceConnectionState");
        }
    }

    private AlsaDevice waitForAlsaDevice(int card, int device, int type) {
        if (DEBUG) {
            Slog.e(TAG, "waitForAlsaDevice(c:" + card + " d:" + device + ")");
        }

        AlsaDevice testDevice = new AlsaDevice(type, card, device);

        // This value was empirically determined.
        final int kWaitTimeMs = 2500;

        synchronized(mAlsaDevices) {
            long timeoutMs = SystemClock.elapsedRealtime() + kWaitTimeMs;
            do {
                if (mAlsaDevices.values().contains(testDevice)) {
                    return testDevice;
                }
                long waitTimeMs = timeoutMs - SystemClock.elapsedRealtime();
                if (waitTimeMs > 0) {
                    try {
                        mAlsaDevices.wait(waitTimeMs);
                    } catch (InterruptedException e) {
                        Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
                    }
                }
            } while (timeoutMs > SystemClock.elapsedRealtime());
        }

        Slog.e(TAG, "waitForAlsaDevice failed for " + testDevice);
        return null;
    }

    private void alsaFileAdded(String name) {
        int type = AlsaDevice.TYPE_UNKNOWN;
        int card = -1, device = -1;

        if (name.startsWith("pcmC")) {
            if (name.endsWith("p")) {
                type = AlsaDevice.TYPE_PLAYBACK;
            } else if (name.endsWith("c")) {
                type = AlsaDevice.TYPE_CAPTURE;
            }
        } else if (name.startsWith("midiC")) {
            type = AlsaDevice.TYPE_MIDI;
        }

        if (type != AlsaDevice.TYPE_UNKNOWN) {
            try {
                int c_index = name.indexOf('C');
                int d_index = name.indexOf('D');
                int end = name.length();
                if (type == AlsaDevice.TYPE_PLAYBACK || type == AlsaDevice.TYPE_CAPTURE) {
                    // skip trailing 'p' or 'c'
                    end--;
                }
                card = Integer.parseInt(name.substring(c_index + 1, d_index));
                device = Integer.parseInt(name.substring(d_index + 1, end));
            } catch (Exception e) {
                Slog.e(TAG, "Could not parse ALSA file name " + name, e);
                return;
            }
            synchronized(mAlsaDevices) {
                if (mAlsaDevices.get(name) == null) {
                    AlsaDevice alsaDevice = new AlsaDevice(type, card, device);
                    Slog.d(TAG, "Adding ALSA device " + alsaDevice);
                    mAlsaDevices.put(name, alsaDevice);
                    mAlsaDevices.notifyAll();
                }
            }
        }
    }

    private void alsaFileRemoved(String path) {
        synchronized(mAlsaDevices) {
            AlsaDevice device = mAlsaDevices.remove(path);
            if (device != null) {
                Slog.d(TAG, "ALSA device removed: " + device);
            }
        }
    }

    /*
     * Select the default device of the specified card.
     */
    /* package */ UsbAudioDevice selectAudioCard(int card) {
        if (DEBUG) {
            Slog.d(TAG, "selectAudioCard() card:" + card
                    + " isCardUsb(): " + mCardsParser.isCardUsb(card));
        }
        if (!mCardsParser.isCardUsb(card)) {
            // Don't. AudioPolicyManager has logic for falling back to internal devices.
            return null;
        }

        mDevicesParser.scan();
        int device = mDevicesParser.getDefaultDeviceNum(card);

        boolean hasPlayback = mDevicesParser.hasPlaybackDevices(card);
        boolean hasCapture = mDevicesParser.hasCaptureDevices(card);
        if (DEBUG) {
            Slog.d(TAG, "usb: hasPlayback:" + hasPlayback + " hasCapture:" + hasCapture);
        }

        int deviceClass =
            (mCardsParser.isCardUsb(card)
                ? UsbAudioDevice.kAudioDeviceClass_External
                : UsbAudioDevice.kAudioDeviceClass_Internal) |
            UsbAudioDevice.kAudioDeviceMeta_Alsa;

        // Playback device file needed/present?
        if (hasPlayback && (waitForAlsaDevice(card, device, AlsaDevice.TYPE_PLAYBACK) == null)) {
            return null;
        }

        // Capture device file needed/present?
        if (hasCapture && (waitForAlsaDevice(card, device, AlsaDevice.TYPE_CAPTURE) == null)) {
            return null;
        }

        UsbAudioDevice audioDevice =
                new UsbAudioDevice(card, device, hasPlayback, hasCapture, deviceClass);
        AlsaCardsParser.AlsaCardRecord cardRecord = mCardsParser.getCardRecordFor(card);
        audioDevice.setDeviceNameAndDescription(cardRecord.mCardName, cardRecord.mCardDescription);

        notifyDeviceState(audioDevice, true /*enabled*/);

        return audioDevice;
    }

    /* package */ UsbAudioDevice selectDefaultDevice() {
        if (DEBUG) {
            Slog.d(TAG, "UsbAudioManager.selectDefaultDevice()");
        }
        return selectAudioCard(mCardsParser.getDefaultCard());
    }

    /* package */ void usbDeviceAdded(UsbDevice usbDevice,
            boolean isInputHeadset, boolean isOutputHeadset) {
        if (DEBUG) {
            Slog.d(TAG, "deviceAdded(): " + usbDevice.getManufacturerName()
                    + " nm:" + usbDevice.getProductName());
        }

        mIsInputHeadset = isInputHeadset;
        mIsOutputHeadset = isOutputHeadset;

        // Is there an audio interface in there?
        boolean isAudioDevice = false;

        // FIXME - handle multiple configurations?
        int interfaceCount = usbDevice.getInterfaceCount();
        for (int ntrfaceIndex = 0; !isAudioDevice && ntrfaceIndex < interfaceCount;
                ntrfaceIndex++) {
            UsbInterface ntrface = usbDevice.getInterface(ntrfaceIndex);
            if (ntrface.getInterfaceClass() == UsbConstants.USB_CLASS_AUDIO) {
                isAudioDevice = true;
            }
        }

        if (DEBUG) {
            Slog.d(TAG, "  isAudioDevice: " + isAudioDevice);
        }
        if (!isAudioDevice) {
            return;
        }

        int addedCard = mCardsParser.getDefaultUsbCard();

        // If the default isn't a USB device, let the existing "select internal mechanism"
        // handle the selection.
        if (DEBUG) {
            Slog.d(TAG, "  mCardsParser.isCardUsb(" + addedCard + ") = "
                        + mCardsParser.isCardUsb(addedCard));
        }
        if (mCardsParser.isCardUsb(addedCard)) {
            UsbAudioDevice audioDevice = selectAudioCard(addedCard);
            if (audioDevice != null) {
                mAudioDevices.put(usbDevice, audioDevice);
                Slog.i(TAG, "USB Audio Device Added: " + audioDevice);
            }

            // look for MIDI devices

            // Don't need to call mDevicesParser.scan() because selectAudioCard() does this above.
            // Uncomment this next line if that behavior changes in the fugure.
            // mDevicesParser.scan()

            boolean hasMidi = mDevicesParser.hasMIDIDevices(addedCard);
            if (hasMidi && mHasMidiFeature) {
                int device = mDevicesParser.getDefaultDeviceNum(addedCard);
                AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
                if (alsaDevice != null) {
                    Bundle properties = new Bundle();
                    String manufacturer = usbDevice.getManufacturerName();
                    String product = usbDevice.getProductName();
                    String version = usbDevice.getVersion();
                    String name;
                    if (manufacturer == null || manufacturer.isEmpty()) {
                        name = product;
                    } else if (product == null || product.isEmpty()) {
                        name = manufacturer;
                    } else {
                        name = manufacturer + " " + product;
                    }
                    properties.putString(MidiDeviceInfo.PROPERTY_NAME, name);
                    properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, manufacturer);
                    properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, product);
                    properties.putString(MidiDeviceInfo.PROPERTY_VERSION, version);
                    properties.putString(MidiDeviceInfo.PROPERTY_SERIAL_NUMBER,
                            usbDevice.getSerialNumber());
                    properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, alsaDevice.mCard);
                    properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, alsaDevice.mDevice);
                    properties.putParcelable(MidiDeviceInfo.PROPERTY_USB_DEVICE, usbDevice);

                    UsbMidiDevice usbMidiDevice = UsbMidiDevice.create(mContext, properties,
                            alsaDevice.mCard, alsaDevice.mDevice);
                    if (usbMidiDevice != null) {
                        mMidiDevices.put(usbDevice, usbMidiDevice);
                    }
                }
            }
        }

        if (DEBUG) {
            Slog.d(TAG, "deviceAdded() - done");
        }
    }

    /* package */ void usbDeviceRemoved(UsbDevice usbDevice) {
        if (DEBUG) {
          Slog.d(TAG, "deviceRemoved(): " + usbDevice.getManufacturerName() +
                  " " + usbDevice.getProductName());
        }

        UsbAudioDevice audioDevice = mAudioDevices.remove(usbDevice);
        Slog.i(TAG, "USB Audio Device Removed: " + audioDevice);
        if (audioDevice != null) {
            if (audioDevice.mHasPlayback || audioDevice.mHasCapture) {
                notifyDeviceState(audioDevice, false /*enabled*/);

                // if there any external devices left, select one of them
                selectDefaultDevice();
            }
        }
        UsbMidiDevice usbMidiDevice = mMidiDevices.remove(usbDevice);
        if (usbMidiDevice != null) {
            IoUtils.closeQuietly(usbMidiDevice);
        }
    }

   /* package */ void setAccessoryAudioState(boolean enabled, int card, int device) {
       if (DEBUG) {
            Slog.d(TAG, "setAccessoryAudioState " + enabled + " " + card + " " + device);
        }
        if (enabled) {
            mAccessoryAudioDevice = new UsbAudioDevice(card, device, true, false,
                    UsbAudioDevice.kAudioDeviceClass_External);
            notifyDeviceState(mAccessoryAudioDevice, true /*enabled*/);
        } else if (mAccessoryAudioDevice != null) {
            notifyDeviceState(mAccessoryAudioDevice, false /*enabled*/);
            mAccessoryAudioDevice = null;
        }
    }

   /* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
        if (!mHasMidiFeature) {
            return;
        }

        if (enabled && mPeripheralMidiDevice == null) {
            Bundle properties = new Bundle();
            Resources r = mContext.getResources();
            properties.putString(MidiDeviceInfo.PROPERTY_NAME, r.getString(
                    com.android.internal.R.string.usb_midi_peripheral_name));
            properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
                    com.android.internal.R.string.usb_midi_peripheral_manufacturer_name));
            properties.putString(MidiDeviceInfo.PROPERTY_PRODUCT, r.getString(
                    com.android.internal.R.string.usb_midi_peripheral_product_name));
            properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
            properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
            mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device);
        } else if (!enabled && mPeripheralMidiDevice != null) {
            IoUtils.closeQuietly(mPeripheralMidiDevice);
            mPeripheralMidiDevice = null;
        }
   }

    //
    // Devices List
    //
/*
    //import java.util.ArrayList;
    public ArrayList<UsbAudioDevice> getConnectedDevices() {
        ArrayList<UsbAudioDevice> devices = new ArrayList<UsbAudioDevice>(mAudioDevices.size());
        for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
            devices.add(entry.getValue());
        }
        return devices;
    }
*/

    //
    // Logging
    //
    // called by UsbService.dump
    public void dump(IndentingPrintWriter pw) {
        pw.println("USB Audio Devices:");
        for (UsbDevice device : mAudioDevices.keySet()) {
            pw.println("  " + device.getDeviceName() + ": " + mAudioDevices.get(device));
        }
        pw.println("USB MIDI Devices:");
        for (UsbDevice device : mMidiDevices.keySet()) {
            pw.println("  " + device.getDeviceName() + ": " + mMidiDevices.get(device));
        }
    }

/*
    public void logDevicesList(String title) {
      if (DEBUG) {
          for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
              Slog.i(TAG, "UsbDevice-------------------");
              Slog.i(TAG, "" + (entry != null ? entry.getKey() : "[none]"));
              Slog.i(TAG, "UsbAudioDevice--------------");
              Slog.i(TAG, "" + entry.getValue());
          }
      }
    }
*/

    // This logs a more terse (and more readable) version of the devices list
/*
    public void logDevices(String title) {
      if (DEBUG) {
          Slog.i(TAG, title);
          for (HashMap.Entry<UsbDevice,UsbAudioDevice> entry : mAudioDevices.entrySet()) {
              Slog.i(TAG, entry.getValue().toShortString());
          }
      }
    }
*/

}
