1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "bta_ag_swb_aptx.h"
18 
19 #include <android_bluetooth_sysprop.h>
20 #include <bluetooth/log.h>
21 #include <string.h>
22 
23 #include <cctype>
24 #include <cstdint>
25 #include <cstdlib>
26 #include <string>
27 
28 #include "bta/ag/bta_ag_int.h"
29 #include "bta_ag_api.h"
30 #include "common/strings.h"
31 #include "hardware/bluetooth.h"
32 #include "hardware/bt_hf.h"
33 #include "osi/include/alarm.h"
34 #include "stack/btm/btm_sco_hfp_hal.h"
35 #include "stack/include/btm_api_types.h"
36 #include "types/raw_address.h"
37 
38 using namespace bluetooth;
39 
is_hfp_aptx_voice_enabled()40 bool is_hfp_aptx_voice_enabled() {
41   return android::sysprop::bluetooth::Hfp::codec_aptx_voice().value_or(false);
42 }
43 
44 static bool aptx_swb_codec_status;
45 
get_lc3_swb_codec_status(RawAddress * bd_addr)46 static bool get_lc3_swb_codec_status(RawAddress* bd_addr) {
47   uint16_t p_scb_idx = bta_ag_idx_by_bdaddr(bd_addr);
48   tBTA_AG_SCB* p_scb = bta_ag_scb_by_idx(p_scb_idx);
49   if (p_scb != NULL) {
50     return hfp_hal_interface::get_swb_supported() && (p_scb->peer_codecs & BTM_SCO_CODEC_LC3) &&
51            !(p_scb->disabled_codecs & BTM_SCO_CODEC_LC3);
52   }
53   return false;
54 }
55 
get_aptx_swb_codec_status()56 static bool get_aptx_swb_codec_status() {
57   if (is_hfp_aptx_voice_enabled()) {
58     return aptx_swb_codec_status;
59   }
60   return false;
61 }
62 
get_swb_codec_status(bluetooth::headset::bthf_swb_codec_t swb_codec,RawAddress * bd_addr)63 bool get_swb_codec_status(bluetooth::headset::bthf_swb_codec_t swb_codec, RawAddress* bd_addr) {
64   bool status = false;
65   switch (swb_codec) {
66     case bluetooth::headset::BTHF_SWB_CODEC_LC3:
67       status = get_lc3_swb_codec_status(bd_addr);
68       log::verbose("LC3 SWB status={}", status);
69       break;
70     case bluetooth::headset::BTHF_SWB_CODEC_VENDOR_APTX:
71       status = get_aptx_swb_codec_status();
72       log::verbose("AptX SWB status={}", status);
73       break;
74     default:
75       log::error("Unknown codec: {}", (int)swb_codec);
76       break;
77   }
78   return status;
79 }
80 
enable_aptx_swb_codec(bool enable,RawAddress * bd_addr)81 bt_status_t enable_aptx_swb_codec(bool enable, RawAddress* bd_addr) {
82   if (is_hfp_aptx_voice_enabled() && (get_lc3_swb_codec_status(bd_addr) == false)) {
83     log::verbose("enable={}", enable);
84     aptx_swb_codec_status = enable;
85     return BT_STATUS_SUCCESS;
86   }
87   return BT_STATUS_FAIL;
88 }
89 
bta_ag_swb_handle_vs_at_events(tBTA_AG_SCB * p_scb,uint16_t cmd,int16_t int_arg,tBTA_AG_VAL * val)90 void bta_ag_swb_handle_vs_at_events(tBTA_AG_SCB* p_scb, uint16_t cmd, int16_t int_arg,
91                                     tBTA_AG_VAL* val) {
92   switch (cmd) {
93     case BTA_AG_AT_QAC_EVT:
94       if (!get_swb_codec_status(bluetooth::headset::BTHF_SWB_CODEC_VENDOR_APTX,
95                                 &p_scb->peer_addr)) {
96         bta_ag_send_qac(p_scb);
97         break;
98       }
99       log::verbose("BTA_AG_AT_QAC_EVT");
100       p_scb->codec_updated = true;
101       if (p_scb->peer_codecs & BTA_AG_SCO_APTX_SWB_SETTINGS_Q0_MASK) {
102         p_scb->sco_codec = BTA_AG_SCO_APTX_SWB_SETTINGS_Q0;
103       } else if (p_scb->peer_codecs & BTM_SCO_CODEC_MSBC) {
104         p_scb->sco_codec = BTM_SCO_CODEC_MSBC;
105       }
106       bta_ag_send_qac(p_scb);
107       log::verbose("Received AT+QAC, updating sco codec to SWB: {}", p_scb->sco_codec);
108       val->num = p_scb->peer_codecs;
109       break;
110     case BTA_AG_AT_QCS_EVT: {
111       tBTA_AG_PEER_CODEC codec_type, codec_sent;
112       alarm_cancel(p_scb->codec_negotiation_timer);
113 
114       log::verbose("BTA_AG_AT_QCS_EVT int_arg={}", int_arg);
115       switch (int_arg) {
116         case BTA_AG_SCO_APTX_SWB_SETTINGS_Q0:
117           codec_type = BTA_AG_SCO_APTX_SWB_SETTINGS_Q0;
118           break;
119         case BTA_AG_SCO_APTX_SWB_SETTINGS_Q1:
120           codec_type = BTA_AG_SCO_APTX_SWB_SETTINGS_Q1;
121           break;
122         case BTA_AG_SCO_APTX_SWB_SETTINGS_Q2:
123           codec_type = BTA_AG_SCO_APTX_SWB_SETTINGS_Q2;
124           break;
125         case BTA_AG_SCO_APTX_SWB_SETTINGS_Q3:
126           codec_type = BTA_AG_SCO_APTX_SWB_SETTINGS_Q3;
127           break;
128         default:
129           log::error("Unknown codec_uuid {}", int_arg);
130           p_scb->is_aptx_swb_codec = false;
131           codec_type = BTM_SCO_CODEC_MSBC;
132           p_scb->codec_fallback = true;
133           p_scb->sco_codec = BTM_SCO_CODEC_MSBC;
134           break;
135       }
136 
137       if (p_scb->codec_fallback) {
138         codec_sent = BTM_SCO_CODEC_MSBC;
139       } else {
140         codec_sent = p_scb->sco_codec;
141       }
142 
143       bta_ag_sco_codec_nego(p_scb, codec_type == codec_sent);
144 
145       /* send final codec info to callback */
146       val->num = codec_sent;
147       break;
148     }
149   }
150 }
151 
bta_ag_parse_qac(char * p_s)152 tBTA_AG_PEER_CODEC bta_ag_parse_qac(char* p_s) {
153   tBTA_AG_PEER_CODEC retval = BTM_SCO_CODEC_NONE;
154   tBTA_AG_SCO_APTX_SWB_SETTINGS codec_mode = BTA_AG_SCO_APTX_SWB_SETTINGS_UNKNOWN;
155 
156   auto codec_modes = bluetooth::common::StringSplit(std::string(p_s), ",", SWB_CODECS_NUMBER);
157   for (auto& codec_mode_str : codec_modes) {
158     if (!std::isdigit(*codec_mode_str.c_str())) {
159       continue;
160     }
161     codec_mode = static_cast<tBTA_AG_SCO_APTX_SWB_SETTINGS>(std::atoi(codec_mode_str.c_str()));
162     switch (codec_mode) {
163       case BTA_AG_SCO_APTX_SWB_SETTINGS_Q0:
164         retval |= BTA_AG_SCO_APTX_SWB_SETTINGS_Q0_MASK;
165         break;
166       case BTA_AG_SCO_APTX_SWB_SETTINGS_Q1:
167         retval |= BTA_AG_SCO_APTX_SWB_SETTINGS_Q1_MASK;
168         break;
169       case BTA_AG_SCO_APTX_SWB_SETTINGS_Q2:
170         retval |= BTA_AG_SCO_APTX_SWB_SETTINGS_Q2_MASK;
171         break;
172       case BTA_AG_SCO_APTX_SWB_SETTINGS_Q3:
173         retval |= BTA_AG_SCO_APTX_SWB_SETTINGS_Q3_MASK;
174         break;
175       default:
176         log::verbose("Unknown Codec UUID({}) received", codec_mode);
177         break;
178     }
179   }
180   return retval;
181 }
182