• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 "metrics_state.h"
18 
19 #include <frameworks/proto_logging/stats/enums/bluetooth/hci/enums.pb.h>
20 #include <frameworks/proto_logging/stats/enums/bluetooth/le/enums.pb.h>
21 
22 #include <chrono>
23 #include <climits>
24 #include <memory>
25 #include <unordered_map>
26 #include <utility>
27 
28 #include "common/strings.h"
29 #include "hci/address.h"
30 #include "metrics/utils.h"
31 #include "os/log.h"
32 #include "os/metrics.h"
33 
34 namespace bluetooth {
35 namespace metrics {
36 
37 using android::bluetooth::le::LeConnectionOriginType;
38 using android::bluetooth::le::LeConnectionState;
39 using android::bluetooth::le::LeConnectionType;
40 
41 // const static ClockTimePoint kInvalidTimePoint{};
42 
43 /*
44  * This is the device level metrics state, which will be modified based on
45  * incoming state events.
46  *
47  */
AddStateChangedEvent(LeConnectionOriginType origin_type,LeConnectionType connection_type,LeConnectionState transaction_state,std::vector<std::pair<os::ArgumentType,int>> argument_list)48 void LEConnectionMetricState::AddStateChangedEvent(
49     LeConnectionOriginType origin_type,
50     LeConnectionType connection_type,
51     LeConnectionState transaction_state,
52     std::vector<std::pair<os::ArgumentType, int>> argument_list) {
53   LOG_INFO(
54       "LEConnectionMetricState:  Origin Type: %s, Connection Type: %s, Transaction State: "
55       "%s",
56       common::ToHexString(origin_type).c_str(),
57       common::ToHexString(connection_type).c_str(),
58       common::ToHexString(transaction_state).c_str());
59 
60   ClockTimePoint current_timestamp = std::chrono::high_resolution_clock::now();
61   state = transaction_state;
62 
63   // Assign the origin of the connection
64   if (connection_origin_type == LeConnectionOriginType::ORIGIN_UNSPECIFIED) {
65     connection_origin_type = origin_type;
66   }
67 
68   if (input_connection_type == LeConnectionType::CONNECTION_TYPE_UNSPECIFIED) {
69     input_connection_type = connection_type;
70   }
71 
72   if (start_timepoint == kInvalidTimePoint) {
73     start_timepoint = current_timestamp;
74   }
75   end_timepoint = current_timestamp;
76 
77   switch (state) {
78     case LeConnectionState::STATE_LE_ACL_START: {
79       int connection_type_cid = GetArgumentTypeFromList(argument_list, os::ArgumentType::L2CAP_CID);
80       if (connection_type_cid != -1) {
81         LeConnectionType connection_type = GetLeConnectionTypeFromCID(connection_type_cid);
82         if (connection_type != LeConnectionType::CONNECTION_TYPE_UNSPECIFIED) {
83           LOG_INFO("LEConnectionMetricsRemoteDevice: Populating the connection type\n");
84           input_connection_type = connection_type;
85         }
86       }
87       break;
88     }
89     case LeConnectionState::STATE_LE_ACL_END: {
90       int acl_status_code_from_args =
91           GetArgumentTypeFromList(argument_list, os::ArgumentType::ACL_STATUS_CODE);
92       acl_status_code = static_cast<android::bluetooth::hci::StatusEnum>(acl_status_code_from_args);
93       acl_state = LeAclConnectionState::LE_ACL_SUCCESS;
94 
95       if (acl_status_code != android::bluetooth::hci::StatusEnum::STATUS_SUCCESS) {
96         acl_state = LeAclConnectionState::LE_ACL_FAILED;
97       }
98       break;
99     }
100     case LeConnectionState::STATE_LE_ACL_TIMEOUT: {
101       int acl_status_code_from_args =
102           GetArgumentTypeFromList(argument_list, os::ArgumentType::ACL_STATUS_CODE);
103       acl_status_code = static_cast<android::bluetooth::hci::StatusEnum>(acl_status_code_from_args);
104       acl_state = LeAclConnectionState::LE_ACL_FAILED;
105       break;
106     }
107     case LeConnectionState::STATE_LE_ACL_CANCEL: {
108       acl_state = LeAclConnectionState::LE_ACL_FAILED;
109       is_cancelled = true;
110       break;
111     }
112       [[fallthrough]];
113     default: {
114       // do nothing
115     }
116   }
117 }
118 
IsEnded()119 bool LEConnectionMetricState::IsEnded() {
120   return acl_state == LeAclConnectionState::LE_ACL_SUCCESS ||
121          acl_state == LeAclConnectionState::LE_ACL_FAILED;
122 }
123 
IsStarted()124 bool LEConnectionMetricState::IsStarted() {
125   return state == LeConnectionState::STATE_LE_ACL_START;
126 }
127 
IsCancelled()128 bool LEConnectionMetricState::IsCancelled() {
129   return is_cancelled;
130 }
131 
132 // Initialize the LEConnectionMetricsRemoteDevice
LEConnectionMetricsRemoteDevice()133 LEConnectionMetricsRemoteDevice::LEConnectionMetricsRemoteDevice() {
134   metrics_logger_module = new MetricsLoggerModule();
135 }
136 
LEConnectionMetricsRemoteDevice(BaseMetricsLoggerModule * baseMetricsLoggerModule)137 LEConnectionMetricsRemoteDevice::LEConnectionMetricsRemoteDevice(
138     BaseMetricsLoggerModule* baseMetricsLoggerModule) {
139   metrics_logger_module = baseMetricsLoggerModule;
140 }
141 
142 // Uploading the session
UploadLEConnectionSession(const hci::Address & address)143 void LEConnectionMetricsRemoteDevice::UploadLEConnectionSession(const hci::Address& address) {
144   auto it = opened_devices.find(address);
145   if (it != opened_devices.end()) {
146     os::LEConnectionSessionOptions session_options;
147     session_options.acl_connection_state = it->second->acl_state;
148     session_options.origin_type = it->second->connection_origin_type;
149     session_options.transaction_type = it->second->input_connection_type;
150     session_options.latency = bluetooth::metrics::get_timedelta_nanos(
151         it->second->start_timepoint, it->second->end_timepoint);
152     session_options.remote_address = address;
153     session_options.status = it->second->acl_status_code;
154     // TODO: keep the acl latency the same as the overall latency for now
155     // When more events are added, we will an overall latency
156     session_options.acl_latency = session_options.latency;
157     session_options.is_cancelled = it->second->is_cancelled;
158     metrics_logger_module->LogMetricBluetoothLESession(session_options);
159     opened_devices.erase(it);
160   }
161 }
162 
163 // Implementation of metrics per remote device
AddStateChangedEvent(const hci::Address & address,LeConnectionOriginType origin_type,LeConnectionType connection_type,LeConnectionState transaction_state,std::vector<std::pair<os::ArgumentType,int>> argument_list)164 void LEConnectionMetricsRemoteDevice::AddStateChangedEvent(
165     const hci::Address& address,
166     LeConnectionOriginType origin_type,
167     LeConnectionType connection_type,
168     LeConnectionState transaction_state,
169     std::vector<std::pair<os::ArgumentType, int>> argument_list) {
170   LOG_INFO(
171         "LEConnectionMetricsRemoteDevice: Transaction State %s, Connection Type %s, Origin Type %s\n",
172         common::ToHexString(transaction_state).c_str(),
173         common::ToHexString(connection_type).c_str(),
174         common::ToHexString(origin_type).c_str());
175   if (address.IsEmpty()) {
176     LOG_INFO(
177         "LEConnectionMetricsRemoteDevice: Empty Address Cancellation %s, %s, %s\n",
178         common::ToHexString(transaction_state).c_str(),
179         common::ToHexString(connection_type).c_str(),
180         common::ToHexString(transaction_state).c_str());
181     for (auto& device_metric : device_metrics) {
182       if (device_metric->IsStarted() &&
183           transaction_state == LeConnectionState::STATE_LE_ACL_CANCEL) {
184         LOG_INFO("LEConnectionMetricsRemoteDevice: Cancellation Begin");
185         // cancel the connection
186         device_metric->AddStateChangedEvent(
187             origin_type, connection_type, transaction_state, argument_list);
188         continue;
189       }
190 
191       if (device_metric->IsCancelled() &&
192           transaction_state == LeConnectionState::STATE_LE_ACL_END) {
193         LOG_INFO("LEConnectionMetricsRemoteDevice: Session is now complete after cancellation");
194         // complete the connection
195         device_metric->AddStateChangedEvent(
196             origin_type, connection_type, transaction_state, argument_list);
197         UploadLEConnectionSession(address);
198         continue;
199       }
200     }
201     return;
202   }
203 
204   auto it = opened_devices.find(address);
205   if (it == opened_devices.end()) {
206     device_metrics.push_back(std::make_unique<LEConnectionMetricState>(address));
207     it = opened_devices.insert(std::begin(opened_devices), {address, device_metrics.back().get()});
208   }
209 
210   it->second->AddStateChangedEvent(origin_type, connection_type, transaction_state, argument_list);
211 
212   // Connection is finished
213   if (it->second->IsEnded()) {
214     UploadLEConnectionSession(address);
215   }
216 }
217 
218 
219 // MetricsLoggerModule class
LogMetricBluetoothLESession(os::LEConnectionSessionOptions session_options)220 void MetricsLoggerModule::LogMetricBluetoothLESession(
221     os::LEConnectionSessionOptions session_options) {
222   os::LogMetricBluetoothLEConnection(session_options);
223 }
224 
225 // Instance of Metrics Collector for LEConnectionMetricsRemoteDeviceImpl
226 LEConnectionMetricsRemoteDevice* MetricsCollector::le_connection_metrics_remote_device =
227     new LEConnectionMetricsRemoteDevice();
228 
GetLEConnectionMetricsCollector()229 LEConnectionMetricsRemoteDevice* MetricsCollector::GetLEConnectionMetricsCollector() {
230   return MetricsCollector::le_connection_metrics_remote_device;
231 }
232 
233 }  // namespace metrics
234 
235 }  // namespace bluetooth
236