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
__anon4754abf90102() 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 std::string kSuspendService("suspend_control");
48 static const size_t kHciAclHeaderSize = 4;
49
50 static std::mutex g_module_mutex;
51 static ActivityAttribution* g_module = nullptr;
52 static bool is_wakeup_callback_registered = false;
53 static bool is_wakelock_callback_registered = false;
54
55 struct wakelock_callback : public BnWakelockCallback {
wakelock_callbackbluetooth::activity_attribution::wakelock_callback56 wakelock_callback() {}
57
notifyAcquiredbluetooth::activity_attribution::wakelock_callback58 Status notifyAcquired() override {
59 std::lock_guard<std::mutex> guard(g_module_mutex);
60 if (g_module != nullptr) {
61 g_module->OnWakelockAcquired();
62 }
63 return Status::ok();
64 }
notifyReleasedbluetooth::activity_attribution::wakelock_callback65 Status notifyReleased() override {
66 std::lock_guard<std::mutex> guard(g_module_mutex);
67 if (g_module != nullptr) {
68 g_module->OnWakelockReleased();
69 }
70 return Status::ok();
71 }
72 };
73
74 static std::shared_ptr<wakelock_callback> g_wakelock_callback = nullptr;
75
76 struct wakeup_callback : public BnSuspendCallback {
wakeup_callbackbluetooth::activity_attribution::wakeup_callback77 wakeup_callback() {}
78
notifyWakeupbluetooth::activity_attribution::wakeup_callback79 Status notifyWakeup(bool success, const std::vector<std::string>& wakeup_reasons) override {
80 for (auto& wakeup_reason : wakeup_reasons) {
81 if (wakeup_reason.find(kBtWakeupReason) != std::string::npos) {
82 std::lock_guard<std::mutex> guard(g_module_mutex);
83 if (g_module != nullptr) {
84 g_module->OnWakeup();
85 }
86 break;
87 }
88 }
89 return Status::ok();
90 }
91 };
92
93 static std::shared_ptr<wakeup_callback> g_wakeup_callback = nullptr;
94
95 struct ActivityAttribution::impl {
implbluetooth::activity_attribution::ActivityAttribution::impl96 impl(ActivityAttribution* module) {
97 std::lock_guard<std::mutex> guard(g_module_mutex);
98 g_module = module;
99 if (is_wakeup_callback_registered && is_wakelock_callback_registered) {
100 LOG_ERROR("Wakeup and wakelock callbacks are already registered");
101 return;
102 }
103
104 Status register_callback_status;
105 bool is_register_successful = false;
106 if (!AServiceManager_isDeclared(kSuspendService.c_str())) {
107 LOG_ERROR("No suspend control service available.");
108 return;
109 }
110 auto control_service = ISuspendControlService::fromBinder(
111 SpAIBinder(AServiceManager_waitForService(kSuspendService.c_str())));
112
113 if (!is_wakeup_callback_registered) {
114 g_wakeup_callback = SharedRefBase::make<wakeup_callback>();
115 register_callback_status = control_service->registerCallback(g_wakeup_callback, &is_register_successful);
116 if (!is_register_successful || !register_callback_status.isOk()) {
117 LOG_ERROR("Fail to register wakeup callback");
118 return;
119 }
120 is_wakeup_callback_registered = true;
121 }
122
123 if (!is_wakelock_callback_registered) {
124 g_wakelock_callback = SharedRefBase::make<wakelock_callback>();
125 register_callback_status =
126 control_service->registerWakelockCallback(g_wakelock_callback, kBtWakelockName, &is_register_successful);
127 if (!is_register_successful || !register_callback_status.isOk()) {
128 LOG_ERROR("Fail to register wakelock callback");
129 return;
130 }
131 is_wakelock_callback_registered = true;
132 }
133 }
134
~implbluetooth::activity_attribution::ActivityAttribution::impl135 ~impl() {
136 std::lock_guard<std::mutex> guard(g_module_mutex);
137 g_module = nullptr;
138 }
139
on_hci_packetbluetooth::activity_attribution::ActivityAttribution::impl140 void on_hci_packet(hal::HciPacket packet, hal::SnoopLogger::PacketType type, uint16_t length) {
141 attribution_processor_.OnBtaaPackets(std::move(hci_processor_.OnHciPacket(std::move(packet), type, length)));
142 }
143
on_wakelock_acquiredbluetooth::activity_attribution::ActivityAttribution::impl144 void on_wakelock_acquired() {
145 wakelock_processor_.OnWakelockAcquired();
146 }
147
on_wakelock_releasedbluetooth::activity_attribution::ActivityAttribution::impl148 void on_wakelock_released() {
149 uint32_t wakelock_duration_ms = 0;
150
151 wakelock_duration_ms = wakelock_processor_.OnWakelockReleased();
152 if (wakelock_duration_ms != 0) {
153 attribution_processor_.OnWakelockReleased(wakelock_duration_ms);
154 }
155 }
156
on_wakeupbluetooth::activity_attribution::ActivityAttribution::impl157 void on_wakeup() {
158 attribution_processor_.OnWakeup();
159 }
160
register_callbackbluetooth::activity_attribution::ActivityAttribution::impl161 void register_callback(ActivityAttributionCallback* callback) {
162 callback_ = callback;
163 }
164
notify_activity_attribution_infobluetooth::activity_attribution::ActivityAttribution::impl165 void notify_activity_attribution_info(int uid, const std::string& package_name, const std::string& device_address) {
166 attribution_processor_.NotifyActivityAttributionInfo(uid, package_name, device_address);
167 }
168
Dumpbluetooth::activity_attribution::ActivityAttribution::impl169 void Dump(
170 std::promise<flatbuffers::Offset<ActivityAttributionData>> promise, flatbuffers::FlatBufferBuilder* fb_builder) {
171 attribution_processor_.Dump(std::move(promise), fb_builder);
172 }
173
174 ActivityAttributionCallback* callback_;
175 AttributionProcessor attribution_processor_;
176 HciProcessor hci_processor_;
177 WakelockProcessor wakelock_processor_;
178 };
179
Capture(const hal::HciPacket & packet,hal::SnoopLogger::PacketType type)180 void ActivityAttribution::Capture(const hal::HciPacket& packet, hal::SnoopLogger::PacketType type) {
181 uint16_t original_length = packet.size();
182 uint16_t truncate_length;
183
184 switch (type) {
185 case hal::SnoopLogger::PacketType::CMD:
186 case hal::SnoopLogger::PacketType::EVT:
187 truncate_length = packet.size();
188 break;
189 case hal::SnoopLogger::PacketType::ACL:
190 case hal::SnoopLogger::PacketType::SCO:
191 case hal::SnoopLogger::PacketType::ISO:
192 truncate_length = kHciAclHeaderSize;
193 break;
194 }
195
196 if (!truncate_length) {
197 return;
198 }
199
200 hal::HciPacket truncate_packet(packet.begin(), packet.begin() + truncate_length);
201 CallOn(pimpl_.get(), &impl::on_hci_packet, truncate_packet, type, original_length);
202 }
203
OnWakelockAcquired()204 void ActivityAttribution::OnWakelockAcquired() {
205 CallOn(pimpl_.get(), &impl::on_wakelock_acquired);
206 }
207
OnWakelockReleased()208 void ActivityAttribution::OnWakelockReleased() {
209 CallOn(pimpl_.get(), &impl::on_wakelock_released);
210 }
211
OnWakeup()212 void ActivityAttribution::OnWakeup() {
213 CallOn(pimpl_.get(), &impl::on_wakeup);
214 }
215
RegisterActivityAttributionCallback(ActivityAttributionCallback * callback)216 void ActivityAttribution::RegisterActivityAttributionCallback(ActivityAttributionCallback* callback) {
217 CallOn(pimpl_.get(), &impl::register_callback, callback);
218 }
219
NotifyActivityAttributionInfo(int uid,const std::string & package_name,const std::string & device_address)220 void ActivityAttribution::NotifyActivityAttributionInfo(
221 int uid, const std::string& package_name, const std::string& device_address) {
222 CallOn(pimpl_.get(), &impl::notify_activity_attribution_info, uid, package_name, device_address);
223 }
224
ToString() const225 std::string ActivityAttribution::ToString() const {
226 return "Btaa Module";
227 }
228
ListDependencies(ModuleList * list) const229 void ActivityAttribution::ListDependencies(ModuleList* list) const {}
230
Start()231 void ActivityAttribution::Start() {
232 pimpl_ = std::make_unique<impl>(this);
233 }
234
Stop()235 void ActivityAttribution::Stop() {
236 pimpl_.reset();
237 }
238
GetDumpsysData(flatbuffers::FlatBufferBuilder * fb_builder) const239 DumpsysDataFinisher ActivityAttribution::GetDumpsysData(flatbuffers::FlatBufferBuilder* fb_builder) const {
240 ASSERT(fb_builder != nullptr);
241
242 std::promise<flatbuffers::Offset<ActivityAttributionData>> promise;
243 auto future = promise.get_future();
244 pimpl_->Dump(std::move(promise), fb_builder);
245
246 auto dumpsys_data = future.get();
247
248 return [dumpsys_data](DumpsysDataBuilder* dumpsys_builder) {
249 dumpsys_builder->add_activity_attribution_dumpsys_data(dumpsys_data);
250 };
251 }
252
253 } // namespace activity_attribution
254 } // namespace bluetooth
255