• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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