1 /*
2 * Copyright (C) 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 "chre_host/wifi_ext_hal_handler.h"
18
19 namespace android {
20 namespace chre {
21
~WifiExtHalHandler()22 WifiExtHalHandler::~WifiExtHalHandler() {
23 notifyThreadToExit();
24 mThread.join();
25 }
26
WifiExtHalHandler(const std::function<void (bool)> & statusChangeCallback)27 WifiExtHalHandler::WifiExtHalHandler(
28 const std::function<void(bool)> &statusChangeCallback) {
29 mEnableConfig.reset();
30 mThread = std::thread(&WifiExtHalHandler::wifiExtHandlerThreadEntry, this);
31 mDeathRecipient =
32 AIBinder_DeathRecipient_new(WifiExtHalHandler::onWifiExtHalServiceDeath);
33 mCallback = ndk::SharedRefBase::make<WifiExtCallback>(statusChangeCallback);
34 }
35
handleConfigurationRequest(bool enable)36 void WifiExtHalHandler::handleConfigurationRequest(bool enable) {
37 std::lock_guard<std::mutex> lock(mMutex);
38 mEnableConfig = enable;
39 mCondVar.notify_one();
40 }
41
dispatchConfigurationRequest(bool enable)42 void WifiExtHalHandler::dispatchConfigurationRequest(bool enable) {
43 if (checkWifiExtHalConnected()) {
44 auto result = mService->requestWifiChreNanRtt(enable);
45 if (!result.isOk()) {
46 LOGE("wifi ext hal config request for %s failed with code: %d",
47 (enable == true) ? "Enable" : "Disable",
48 result.getServiceSpecificError());
49 }
50 mCallback->onStatusChanged(result.isOk());
51 }
52 }
53
checkWifiExtHalConnected()54 bool WifiExtHalHandler::checkWifiExtHalConnected() {
55 bool success = false;
56 if (mService == nullptr) {
57 auto serviceName = std::string() + IWifiExt::descriptor + "/default";
58 mService = IWifiExt::fromBinder(
59 ndk::SpAIBinder(AServiceManager_waitForService(serviceName.c_str())));
60 if (mService != nullptr) {
61 LOGD("Connected to Wifi Ext HAL service");
62 AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient,
63 reinterpret_cast<void *>(&mService) /* cookie */);
64 auto result = mService->registerChreCallback(mCallback);
65 if (!result.isOk()) {
66 LOGE("Failed to register CHRE callback with WifiExt, code: %d",
67 result.getServiceSpecificError());
68 } else {
69 success = true;
70 }
71 } else {
72 LOGE("Failed to connect to Wifi Ext HAL service");
73 }
74 }
75 return success;
76 }
77
onWifiExtHalServiceDeath(void * cookie)78 void WifiExtHalHandler::onWifiExtHalServiceDeath(void *cookie) {
79 LOGI("WiFi Ext HAL service died");
80 // Cookie is expected to be a pointer to mService.
81 *((std::shared_ptr<IWifiExt> *)cookie) = nullptr;
82 // TODO(b/204226580): Figure out if wifi ext HAL is stateful and if it
83 // isn't, notify CHRE of a NAN disabled status change to enable nanoapps
84 // to not expect NAN data until the service is back up, and expect it to
85 // do a re-enable when needed. Or we could store the current status of
86 // enablement, and do a re-enable/disable when the service is back up.
87 }
88
wifiExtHandlerThreadEntry()89 void WifiExtHalHandler::wifiExtHandlerThreadEntry() {
90 while (mThreadRunning) {
91 std::unique_lock<std::mutex> lock(mMutex);
92 mCondVar.wait(
93 lock, [this] { return mEnableConfig.has_value() || !mThreadRunning; });
94
95 if (mThreadRunning) {
96 dispatchConfigurationRequest(mEnableConfig.value());
97 mEnableConfig.reset();
98 }
99 }
100 }
101
notifyThreadToExit()102 void WifiExtHalHandler::notifyThreadToExit() {
103 std::lock_guard<std::mutex> lock(mMutex);
104 mThreadRunning = false;
105 mCondVar.notify_one();
106 }
107
108 } // namespace chre
109 } // namespace android
110