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 #pragma once 18 19 #include <base/functional/callback.h> 20 21 #include <ostream> 22 23 #include "device_groups.h" 24 #include "devices.h" 25 #include "hardware/bt_le_audio.h" 26 #include "types/raw_address.h" 27 28 using bluetooth::le_audio::LeAudioHealthBasedAction; 29 30 namespace bluetooth::le_audio { 31 using LeAudioRecommendationActionCb = base::RepeatingCallback<void( 32 const RawAddress& address, int group_id, LeAudioHealthBasedAction action)>; 33 34 /* This should be set by the client of this module to provide information about 35 * basic LeAudio support of the device which is exposing ASCS UUIDs. Should be 36 * used with AddStatisticForDevice API 37 */ 38 enum class LeAudioHealthDeviceStatType { 39 /* Should be used whenever LeAudio device has invalid GATT Database structure. 40 * e.g. missing mandatory services or characteristics. */ 41 INVALID_DB = 0, 42 /* Should be used when LeAudio devie GATT DB contains at least mandatory 43 * services and characteristics. */ 44 VALID_DB, 45 /* Should be used when device expose CSIS support but service is not valid. */ 46 INVALID_CSIS, 47 /* Should be used when device expose CSIS and Group ID has been 48 * successfully assigned to device. */ 49 VALID_CSIS, 50 }; 51 52 /* When LeAudio device (s) are ready to use, we look at those as a group. 53 * Using Group stats we measure how good we are in creating streams. 54 * Should be used with AddStatisticForGroup API 55 */ 56 enum class LeAudioHealthGroupStatType { 57 /* Whenever stream is successfully established. */ 58 STREAM_CREATE_SUCCESS, 59 /* Whenever stream creation failes due to CIS failures */ 60 STREAM_CREATE_CIS_FAILED, 61 /* Whenever stream creation failes due to ASCS signaling failures 62 * e.g. ASE does not go to the proper State on time 63 */ 64 STREAM_CREATE_SIGNALING_FAILED, 65 /* Context stream not available */ 66 STREAM_CONTEXT_NOT_AVAILABLE, 67 }; 68 69 class LeAudioHealthStatus { 70 public: 71 virtual ~LeAudioHealthStatus(void) = default; 72 static LeAudioHealthStatus* Get(void); 73 static void Cleanup(void); 74 static void DebugDump(int fd); 75 76 virtual void RegisterCallback(LeAudioRecommendationActionCb cb) = 0; 77 virtual void AddStatisticForDevice(const LeAudioDevice* device, 78 LeAudioHealthDeviceStatType type) = 0; 79 virtual void AddStatisticForGroup(const LeAudioDeviceGroup* group, 80 LeAudioHealthGroupStatType type) = 0; 81 virtual void RemoveStatistics(const RawAddress& address, int group) = 0; 82 83 struct group_stats { group_statsgroup_stats84 group_stats(int group_id) 85 : group_id_(group_id), 86 latest_recommendation_(LeAudioHealthBasedAction::NONE), 87 stream_success_cnt_(0), 88 stream_failures_cnt_(0), 89 stream_cis_failures_cnt_(0), 90 stream_signaling_failures_cnt_(0), 91 stream_context_not_avail_cnt_(0){}; 92 93 int group_id_; 94 LeAudioHealthBasedAction latest_recommendation_; 95 96 int stream_success_cnt_; 97 int stream_failures_cnt_; 98 int stream_cis_failures_cnt_; 99 int stream_signaling_failures_cnt_; 100 int stream_context_not_avail_cnt_; 101 }; 102 103 struct device_stats { device_statsdevice_stats104 device_stats(RawAddress address) 105 : address_(address), 106 latest_recommendation_(LeAudioHealthBasedAction::NONE), 107 is_valid_service_(true), 108 is_valid_group_member_(true){}; 109 RawAddress address_; 110 LeAudioHealthBasedAction latest_recommendation_; 111 112 bool is_valid_service_; 113 bool is_valid_group_member_; 114 }; 115 }; 116 117 inline std::ostream& operator<<( 118 std::ostream& os, 119 const bluetooth::le_audio::LeAudioHealthGroupStatType& stat) { 120 switch (stat) { 121 case bluetooth::le_audio::LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS: 122 os << "STREAM_CREATE_SUCCESS"; 123 break; 124 case bluetooth::le_audio::LeAudioHealthGroupStatType:: 125 STREAM_CREATE_CIS_FAILED: 126 os << "STREAM_CREATE_CIS_FAILED"; 127 break; 128 case bluetooth::le_audio::LeAudioHealthGroupStatType:: 129 STREAM_CREATE_SIGNALING_FAILED: 130 os << "STREAM_CREATE_SIGNALING_FAILED"; 131 break; 132 case bluetooth::le_audio::LeAudioHealthGroupStatType:: 133 STREAM_CONTEXT_NOT_AVAILABLE: 134 os << "STREAM_CONTEXT_NOT_AVAILABLE"; 135 break; 136 default: 137 os << "UNKNOWN"; 138 break; 139 } 140 return os; 141 } 142 143 inline std::ostream& operator<<( 144 std::ostream& os, 145 const bluetooth::le_audio::LeAudioHealthDeviceStatType& stat) { 146 switch (stat) { 147 case bluetooth::le_audio::LeAudioHealthDeviceStatType::INVALID_DB: 148 os << "INVALID_DB"; 149 break; 150 case bluetooth::le_audio::LeAudioHealthDeviceStatType::VALID_DB: 151 os << "VALID_DB"; 152 break; 153 case bluetooth::le_audio::LeAudioHealthDeviceStatType::INVALID_CSIS: 154 os << "INVALID_CSIS"; 155 break; 156 case bluetooth::le_audio::LeAudioHealthDeviceStatType::VALID_CSIS: 157 os << "VALID_CSIS"; 158 break; 159 default: 160 os << "UNKNOWN"; 161 break; 162 } 163 return os; 164 } 165 } // namespace bluetooth::le_audio 166 167 namespace fmt { 168 template <> 169 struct formatter<bluetooth::le_audio::LeAudioHealthDeviceStatType> 170 : enum_formatter<bluetooth::le_audio::LeAudioHealthDeviceStatType> {}; 171 template <> 172 struct formatter<bluetooth::le_audio::LeAudioHealthGroupStatType> 173 : enum_formatter<bluetooth::le_audio::LeAudioHealthGroupStatType> {}; 174 } // namespace fmt 175