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

#define LOG_TAG "ATVAudioPolicyManager"
//#define LOG_NDEBUG 0
#include <media/AudioParameter.h>
#include <media/mediarecorder.h>
#include <utils/Log.h>
#include <utils/String16.h>
#include <utils/String8.h>
#include <utils/StrongPointer.h>

#include "AudioHardwareOutput.h"
#include "ATVAudioPolicyManager.h"

#ifdef REMOTE_CONTROL_INTERFACE
#include <IRemoteControlService.h>
#endif


namespace android {
extern AudioHardwareOutput gAudioHardwareOutput;

// ----------------------------------------------------------------------------
// Common audio policy manager code is implemented in AudioPolicyManager class
// ----------------------------------------------------------------------------

// ---  class factory


extern "C" AudioPolicyInterface* createAudioPolicyManager(
        AudioPolicyClientInterface *clientInterface)
{
    return new ATVAudioPolicyManager(clientInterface);
}

extern "C" void destroyAudioPolicyManager(AudioPolicyInterface *interface)
{
    delete interface;
}

ATVAudioPolicyManager::ATVAudioPolicyManager(
        AudioPolicyClientInterface *clientInterface)
    : AudioPolicyManager(clientInterface), mForceSubmixInputSelection(false)
{
}

float ATVAudioPolicyManager::computeVolume(audio_stream_type_t stream,
                                           int index,
                                           audio_devices_t device)
{
    // We only use master volume, so all audio flinger streams
    // should be set to maximum
    (void)stream;
    (void)index;
    (void)device;
    return 0.0; // no attenuation == 0.0dB
}

status_t ATVAudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
                                                         audio_policy_dev_state_t state,
                                                         const char *device_address,
                                                         const char *device_name)
{
    audio_devices_t tmp = AUDIO_DEVICE_NONE;;
    ALOGE("setDeviceConnectionState %08x %x %s", device, state,
          device_address ? device_address : "(null)");

    // If the input device is the remote submix and an address starting with "force=" was
    // specified, enable "force=1" / disable "force=0" the forced selection of the remote submix
    // input device over hardware input devices (e.g RemoteControl).
    if (device == AUDIO_DEVICE_IN_REMOTE_SUBMIX && device_address) {
        AudioParameter parameters = AudioParameter(String8(device_address));
        int forceValue;
        if (parameters.getInt(String8("force"), forceValue) == OK) {
            mForceSubmixInputSelection = forceValue != 0;
        }
    }

    if (audio_is_output_device(device)) {
      switch (state) {
          case AUDIO_POLICY_DEVICE_STATE_AVAILABLE:
              tmp = mAvailableOutputDevices.types() | device;
              break;

          case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE:
              tmp = mAvailableOutputDevices.types() & ~device;
              break;
          default:
              ALOGE("setDeviceConnectionState() invalid state: %x", state);
              return BAD_VALUE;
      }

      gAudioHardwareOutput.updateRouting(tmp);
      tmp = mAvailableOutputDevices.types();
    }

    status_t ret = 0;
    if (device != AUDIO_DEVICE_IN_REMOTE_SUBMIX) {
      ret = AudioPolicyManager::setDeviceConnectionState(
                    device, state, device_address, device_name);
    }

    if (audio_is_output_device(device)) {
      if (tmp != mAvailableOutputDevices.types())
          gAudioHardwareOutput.updateRouting(mAvailableOutputDevices.types());
    }

    return ret;
}

audio_devices_t ATVAudioPolicyManager::getDeviceForInputSource(audio_source_t inputSource)
{
    uint32_t device = AUDIO_DEVICE_NONE;
    bool usePhysRemote = true;
    const audio_devices_t availableDeviceTypes = mAvailableInputDevices.types() &
            ~AUDIO_DEVICE_BIT_IN;

    if (inputSource == AUDIO_SOURCE_VOICE_RECOGNITION) {
#ifdef REMOTE_CONTROL_INTERFACE
      ALOGI("Using REMOTE_CONTROL_INTERFACE.");
      // Check if remote is actually connected or we should move on
      sp<IRemoteControlService> service = IRemoteControlService::getInstance();
      if (service == NULL) {
          ALOGV("getDeviceForInputSource No RemoteControl service detected, ignoring");
          usePhysRemote = false;
      } else if (!service->hasActiveRemote()) {
          if (mForceSubmixInputSelection == false && service->hasConnectedRemotes()) {
              ALOGV("getDeviceForInputSource connected remote and submix not forced");
              usePhysRemote = true;
          } else {
              ALOGV("getDeviceForInputSource No active connected device, passing onto submix");
              usePhysRemote = false;
          }
      }
#endif
      ALOGV("getDeviceForInputSource %s %s", usePhysRemote ? "use physical" : "",
          mForceSubmixInputSelection ? "use virtual" : "");
      if (availableDeviceTypes & AUDIO_DEVICE_IN_WIRED_HEADSET &&
            usePhysRemote) {
          // User a wired headset (physical remote) if available, connected and active
          ALOGV("Wired Headset available");
          device = AUDIO_DEVICE_IN_WIRED_HEADSET;
      } else if (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX &&
            mForceSubmixInputSelection) {
          // REMOTE_SUBMIX should always be avaible, let's make sure it's being forced at the moment
          ALOGV("Virtual remote available");
          device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
      } else if (availableDeviceTypes & AUDIO_DEVICE_IN_USB_DEVICE) {
          ALOGV("Use USB audio input");
          device = AUDIO_DEVICE_IN_USB_DEVICE;
      }
    } else if ((availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX) &&
            (inputSource == AUDIO_SOURCE_REMOTE_SUBMIX)) {
        device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
    }

    ALOGV("getDeviceForInputSource() input source %d, device %08x", inputSource, device);
    return device;
}

}  // namespace android
