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