Home | History | Annotate | Download | only in audio_extn
      1 /*
      2 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
      3 *
      4 * Redistribution and use in source and binary forms, with or without
      5 * modification, are permitted provided that the following conditions are
      6 * met:
      7 *     * Redistributions of source code must retain the above copyright
      8 *       notice, this list of conditions and the following disclaimer.
      9 *     * Redistributions in binary form must reproduce the above
     10 *       copyright notice, this list of conditions and the following
     11 *       disclaimer in the documentation and/or other materials provided
     12 *       with the distribution.
     13 *     * Neither the name of The Linux Foundation nor the names of its
     14 *       contributors may be used to endorse or promote products derived
     15 *       from this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 #define LOG_TAG "split_a2dp"
     30 /*#define LOG_NDEBUG 0*/
     31 #define LOG_NDDEBUG 0
     32 #include <errno.h>
     33 #include <cutils/log.h>
     34 
     35 #include "audio_hw.h"
     36 #include "platform.h"
     37 #include "platform_api.h"
     38 #include <stdlib.h>
     39 #include <cutils/str_parms.h>
     40 #include <hardware/audio.h>
     41 #include <hardware/hardware.h>
     42 
     43 #ifdef SPLIT_A2DP_ENABLED
     44 
     45 struct a2dp_data{
     46     struct audio_stream_out *a2dp_stream;
     47     struct audio_hw_device *a2dp_device;
     48     bool a2dp_started;
     49     bool a2dp_suspended;
     50 };
     51 
     52 struct a2dp_data a2dp;
     53 
     54 #define AUDIO_PARAMETER_A2DP_STARTED "A2dpStarted"
     55 
     56 static int open_a2dp_output()
     57 {
     58     hw_module_t *mod;
     59     int      format = AUDIO_FORMAT_PCM_16_BIT;
     60     int rc=0;
     61     uint32_t channels = AUDIO_CHANNEL_OUT_STEREO;
     62     uint32_t sampleRate = DEFAULT_OUTPUT_SAMPLING_RATE;
     63     struct audio_config config;
     64 
     65     ALOGV("open_a2dp_output");
     66 
     67     config.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
     68     config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
     69     config.format = AUDIO_FORMAT_PCM_16_BIT;
     70 
     71     if (a2dp.a2dp_device == NULL){
     72         rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, (const char*)"a2dp",
     73                                     (const hw_module_t**)&mod);
     74         if (rc != 0) {
     75             ALOGE("Could not get a2dp hardware module");
     76             return rc;
     77         }
     78         ALOGV("Opening A2DP device HAL for the first time");
     79         rc = audio_hw_device_open(mod, &a2dp.a2dp_device);
     80         if (rc != 0) {
     81             ALOGE("couldn't open a2dp audio hw device");
     82             return rc;
     83         }
     84     }
     85 
     86     rc = a2dp.a2dp_device->open_output_stream(a2dp.a2dp_device, 0,AUDIO_DEVICE_OUT_BLUETOOTH_A2DP,
     87                                     (audio_output_flags_t)AUDIO_OUTPUT_FLAG_NONE, &config, &a2dp.a2dp_stream, NULL);
     88 
     89     if( rc != 0 ) {
     90         ALOGE("Failed to open output stream for a2dp: status %d", rc);
     91     }
     92 
     93     a2dp.a2dp_suspended = false;
     94     return rc;
     95 }
     96 
     97 static int close_a2dp_output()
     98 {
     99 
    100     ALOGV("close_a2dp_output");
    101     if(!a2dp.a2dp_device && !a2dp.a2dp_stream){
    102         ALOGE("No Active A2dp output found");
    103         return 0;
    104     }
    105 
    106     a2dp.a2dp_device->close_output_stream(a2dp.a2dp_device, a2dp.a2dp_stream);
    107     a2dp.a2dp_stream = NULL;
    108     a2dp.a2dp_started = false;
    109     a2dp.a2dp_suspended = true;
    110 
    111     return 0;
    112 }
    113 
    114 void audio_extn_a2dp_set_parameters(struct str_parms *parms)
    115 {
    116      int ret, val;
    117      char value[32]={0};
    118 
    119      ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value,
    120                             sizeof(value));
    121      if( ret >= 0) {
    122          val = atoi(value);
    123          if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
    124              ALOGV("Received device connect request for A2DP");
    125              open_a2dp_output();
    126          }
    127      }
    128 
    129      ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value,
    130                          sizeof(value));
    131 
    132      if( ret >= 0) {
    133          val = atoi(value);
    134          if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
    135              ALOGV("Received device dis- connect request");
    136              close_a2dp_output();
    137          }
    138      }
    139 
    140      ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
    141      if (ret >= 0) {
    142          if (a2dp.a2dp_device && a2dp.a2dp_stream) {
    143              a2dp.a2dp_device->set_parameters(a2dp.a2dp_device, str_parms_to_str(parms));
    144              if (!strncmp(value,"true",sizeof(value))) {
    145                  a2dp.a2dp_suspended = true;
    146              } else {
    147                  a2dp.a2dp_suspended = false;
    148              }
    149          }
    150      }
    151 }
    152 
    153 void audio_extn_a2dp_start_playback()
    154 {
    155     int ret = 0;
    156     char buf[20]={0};
    157 
    158     if (!a2dp.a2dp_started && a2dp.a2dp_device && a2dp.a2dp_stream) {
    159 
    160          snprintf(buf,sizeof(buf),"%s=true",AUDIO_PARAMETER_A2DP_STARTED);
    161         /* This call indicates BT HAL to start playback */
    162         ret =  a2dp.a2dp_device->set_parameters(a2dp.a2dp_device, buf);
    163         if (ret < 0 ) {
    164            ALOGE("BT controller start failed, retry on the next write");
    165            a2dp.a2dp_started = false;
    166         } else {
    167            a2dp.a2dp_started = true;
    168            ALOGV("Start playback successful to BT HAL");
    169         }
    170     }
    171 }
    172 
    173 void audio_extn_a2dp_stop_playback()
    174 {
    175     int ret =0;
    176     char buf[20]={0};
    177 
    178     if ( a2dp.a2dp_started && a2dp.a2dp_device && a2dp.a2dp_stream) {
    179 
    180        snprintf(buf,sizeof(buf),"%s=false",AUDIO_PARAMETER_A2DP_STARTED);
    181 
    182         ret = a2dp.a2dp_device->set_parameters(a2dp.a2dp_device, buf);
    183 
    184         if (ret < 0)
    185             ALOGE("out_standby to BT HAL failed");
    186         else
    187             ALOGV("out_standby to BT HAL successful");
    188 
    189     }
    190     a2dp.a2dp_started = false;
    191     a2dp.a2dp_suspended = true;
    192 }
    193 
    194 void audio_extn_a2dp_init ()
    195 {
    196   a2dp.a2dp_started = false;
    197   a2dp.a2dp_suspended = true;
    198   a2dp.a2dp_stream = NULL;
    199   a2dp.a2dp_device = NULL;
    200 }
    201 #endif // SPLIT_A2DP_ENABLED
    202