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<<(std::ostream& os, 118 const bluetooth::le_audio::LeAudioHealthGroupStatType& stat) { 119 switch (stat) { 120 case bluetooth::le_audio::LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS: 121 os << "STREAM_CREATE_SUCCESS"; 122 break; 123 case bluetooth::le_audio::LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED: 124 os << "STREAM_CREATE_CIS_FAILED"; 125 break; 126 case bluetooth::le_audio::LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED: 127 os << "STREAM_CREATE_SIGNALING_FAILED"; 128 break; 129 case bluetooth::le_audio::LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE: 130 os << "STREAM_CONTEXT_NOT_AVAILABLE"; 131 break; 132 default: 133 os << "UNKNOWN"; 134 break; 135 } 136 return os; 137 } 138 139 inline std::ostream& operator<<(std::ostream& os, 140 const bluetooth::le_audio::LeAudioHealthDeviceStatType& stat) { 141 switch (stat) { 142 case bluetooth::le_audio::LeAudioHealthDeviceStatType::INVALID_DB: 143 os << "INVALID_DB"; 144 break; 145 case bluetooth::le_audio::LeAudioHealthDeviceStatType::VALID_DB: 146 os << "VALID_DB"; 147 break; 148 case bluetooth::le_audio::LeAudioHealthDeviceStatType::INVALID_CSIS: 149 os << "INVALID_CSIS"; 150 break; 151 case bluetooth::le_audio::LeAudioHealthDeviceStatType::VALID_CSIS: 152 os << "VALID_CSIS"; 153 break; 154 default: 155 os << "UNKNOWN"; 156 break; 157 } 158 return os; 159 } 160 } // namespace bluetooth::le_audio 161 162 namespace std { 163 template <> 164 struct formatter<bluetooth::le_audio::LeAudioHealthDeviceStatType> 165 : enum_formatter<bluetooth::le_audio::LeAudioHealthDeviceStatType> {}; 166 template <> 167 struct formatter<bluetooth::le_audio::LeAudioHealthGroupStatType> 168 : enum_formatter<bluetooth::le_audio::LeAudioHealthGroupStatType> {}; 169 } // namespace std 170