1 /*
2 * Copyright 2020 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 #define LOG_TAG "btaa"
18
19 #include "btaa/activity_attribution.h"
20 #include "activity_attribution_generated.h"
21
22 #include <aidl/android/system/suspend/BnSuspendCallback.h>
23 #include <aidl/android/system/suspend/BnWakelockCallback.h>
24 #include <aidl/android/system/suspend/ISuspendControlService.h>
25 #include <android/binder_manager.h>
26
27 #include "btaa/attribution_processor.h"
28 #include "btaa/hci_processor.h"
29 #include "btaa/wakelock_processor.h"
30 #include "module.h"
31 #include "os/log.h"
32
33 using aidl::android::system::suspend::BnSuspendCallback;
34 using aidl::android::system::suspend::BnWakelockCallback;
35 using aidl::android::system::suspend::ISuspendCallback;
36 using aidl::android::system::suspend::ISuspendControlService;
37 using Status = ::ndk::ScopedAStatus;
38 using namespace ndk;
39
40 namespace bluetooth {
41 namespace activity_attribution {
42
__anonf1f486fe0102() 43 const ModuleFactory ActivityAttribution::Factory = ModuleFactory([]() { return new ActivityAttribution(); });
44
45 static const std::string kBtWakelockName("hal_bluetooth_lock");
46 static const std::string kBtWakeupReason("hs_uart_wakeup");
47 static const size_t kHciAclHeaderSize = 4;
48
49 struct wakelock_callback : public BnWakelockCallback {
wakelock_callbackbluetooth::activity_attribution::wakelock_callback50 wakelock_callback(ActivityAttribution* module) : module_(module) {}
51
notifyAcquiredbluetooth::activity_attribution::wakelock_callback52 Status notifyAcquired() override {
53 module_->OnWakelockAcquired();
54 return Status::ok();
55 }
notifyReleasedbluetooth::activity_attribution::wakelock_callback56 Status notifyReleased() override {
57 module_->OnWakelockReleased();
58 return Status::ok();
59 }
60
61 ActivityAttribution* module_;
62 };
63
64 struct wakeup_callback : public BnSuspendCallback {
wakeup_callbackbluetooth::activity_attribution::wakeup_callback65 wakeup_callback(ActivityAttribution* module) : module_(module) {}
66
notifyWakeupbluetooth::activity_attribution::wakeup_callback67 Status notifyWakeup(bool success, const std::vector<std::string>& wakeup_reasons) override {
68 for (auto& wakeup_reason : wakeup_reasons) {
69 if (wakeup_reason.find(kBtWakeupReason) != std::string::npos) {
70 module_->OnWakeup();
71 break;
72 }
73 }
74 return Status::ok();
75 }
76
77 ActivityAttribution* module_;
78 };
79
80 struct ActivityAttribution::impl {
implbluetooth::activity_attribution::ActivityAttribution::impl81 impl(ActivityAttribution* module) {
82 bool is_registered = false;
83
84 auto control_service =
85 ISuspendControlService::fromBinder(SpAIBinder(AServiceManager_getService("suspend_control")));
86 if (!control_service) {
87 LOG_ERROR("Fail to obtain suspend_control");
88 return;
89 }
90
91 Status register_callback_status =
92 control_service->registerCallback(SharedRefBase::make<wakeup_callback>(module), &is_registered);
93 if (!is_registered || !register_callback_status.isOk()) {
94 LOG_ERROR("Fail to register wakeup callback");
95 return;
96 }
97
98 register_callback_status = control_service->registerWakelockCallback(
99 SharedRefBase::make<wakelock_callback>(module), kBtWakelockName, &is_registered);
100 if (!is_registered || !register_callback_status.isOk()) {
101 LOG_ERROR("Fail to register wakelock callback");
102 return;
103 }
104 }
105
on_hci_packetbluetooth::activity_attribution::ActivityAttribution::impl106 void on_hci_packet(hal::HciPacket packet, hal::SnoopLogger::PacketType type, uint16_t length) {
107 attribution_processor_.OnBtaaPackets(std::move(hci_processor_.OnHciPacket(std::move(packet), type, length)));
108 }
109
on_wakelock_acquiredbluetooth::activity_attribution::ActivityAttribution::impl110 void on_wakelock_acquired() {
111 wakelock_processor_.OnWakelockAcquired();
112 }
113
on_wakelock_releasedbluetooth::activity_attribution::ActivityAttribution::impl114 void on_wakelock_released() {
115 uint32_t wakelock_duration_ms = 0;
116
117 wakelock_duration_ms = wakelock_processor_.OnWakelockReleased();
118 if (wakelock_duration_ms != 0) {
119 attribution_processor_.OnWakelockReleased(wakelock_duration_ms);
120 }
121 }
122
on_wakeupbluetooth::activity_attribution::ActivityAttribution::impl123 void on_wakeup() {
124 attribution_processor_.OnWakeup();
125 }
126
register_callbackbluetooth::activity_attribution::ActivityAttribution::impl127 void register_callback(ActivityAttributionCallback* callback) {
128 callback_ = callback;
129 }
130
Dumpbluetooth::activity_attribution::ActivityAttribution::impl131 void Dump(
132 std::promise<flatbuffers::Offset<ActivityAttributionData>> promise, flatbuffers::FlatBufferBuilder* fb_builder) {
133 attribution_processor_.Dump(std::move(promise), fb_builder);
134 }
135
136 ActivityAttributionCallback* callback_;
137 AttributionProcessor attribution_processor_;
138 HciProcessor hci_processor_;
139 WakelockProcessor wakelock_processor_;
140 };
141
Capture(const hal::HciPacket & packet,hal::SnoopLogger::PacketType type)142 void ActivityAttribution::Capture(const hal::HciPacket& packet, hal::SnoopLogger::PacketType type) {
143 uint16_t original_length = packet.size();
144 uint16_t truncate_length;
145
146 switch (type) {
147 case hal::SnoopLogger::PacketType::CMD:
148 case hal::SnoopLogger::PacketType::EVT:
149 truncate_length = packet.size();
150 break;
151 case hal::SnoopLogger::PacketType::ACL:
152 case hal::SnoopLogger::PacketType::SCO:
153 case hal::SnoopLogger::PacketType::ISO:
154 truncate_length = kHciAclHeaderSize;
155 break;
156 }
157
158 if (!truncate_length) {
159 return;
160 }
161
162 hal::HciPacket truncate_packet(packet.begin(), packet.begin() + truncate_length);
163 CallOn(pimpl_.get(), &impl::on_hci_packet, truncate_packet, type, original_length);
164 }
165
OnWakelockAcquired()166 void ActivityAttribution::OnWakelockAcquired() {
167 CallOn(pimpl_.get(), &impl::on_wakelock_acquired);
168 }
169
OnWakelockReleased()170 void ActivityAttribution::OnWakelockReleased() {
171 CallOn(pimpl_.get(), &impl::on_wakelock_released);
172 }
173
OnWakeup()174 void ActivityAttribution::OnWakeup() {
175 CallOn(pimpl_.get(), &impl::on_wakeup);
176 }
177
RegisterActivityAttributionCallback(ActivityAttributionCallback * callback)178 void ActivityAttribution::RegisterActivityAttributionCallback(ActivityAttributionCallback* callback) {
179 CallOn(pimpl_.get(), &impl::register_callback, callback);
180 }
181
ToString() const182 std::string ActivityAttribution::ToString() const {
183 return "Btaa Module";
184 }
185
ListDependencies(ModuleList * list)186 void ActivityAttribution::ListDependencies(ModuleList* list) {}
187
Start()188 void ActivityAttribution::Start() {
189 pimpl_ = std::make_unique<impl>(this);
190 }
191
Stop()192 void ActivityAttribution::Stop() {
193 pimpl_.reset();
194 }
195
GetDumpsysData(flatbuffers::FlatBufferBuilder * fb_builder) const196 DumpsysDataFinisher ActivityAttribution::GetDumpsysData(flatbuffers::FlatBufferBuilder* fb_builder) const {
197 ASSERT(fb_builder != nullptr);
198
199 std::promise<flatbuffers::Offset<ActivityAttributionData>> promise;
200 auto future = promise.get_future();
201 pimpl_->Dump(std::move(promise), fb_builder);
202
203 auto dumpsys_data = future.get();
204
205 return [dumpsys_data](DumpsysDataBuilder* dumpsys_builder) {
206 dumpsys_builder->add_activity_attribution_dumpsys_data(dumpsys_data);
207 };
208 }
209
210 } // namespace activity_attribution
211 } // namespace bluetooth
212