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 auto cb = [&]() { onWifiExtHalServiceDeath(); };
32 mDeathRecipient = new WifiExtHalDeathRecipient(cb);
33 mCallback = new 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 auto hidlCb = [this, enable](const WifiStatus &status) {
44 bool success = (status.code == WifiStatusCode::SUCCESS) ? true : false;
45 if (!success) {
46 LOGE("wifi ext hal config request for %s failed with code: %d (%s)",
47 (enable == true) ? "Enable" : "Disable", status.code,
48 status.description.c_str());
49 }
50 mCallback->onStatusChanged(success);
51 };
52
53 if (checkWifiExtHalConnected()) {
54 auto result = mService->requestWifiChreNanRtt(enable, hidlCb);
55 if (!result.isOk()) {
56 LOGE("Failed to %s NAN: %s", (enable == true) ? "Enable" : "Disable",
57 result.description().c_str());
58 }
59 }
60 }
61
checkWifiExtHalConnected()62 bool WifiExtHalHandler::checkWifiExtHalConnected() {
63 bool success = false;
64 if (mService == nullptr) {
65 mService = IWifiExt::getService();
66 if (mService != nullptr) {
67 LOGD("Connected to Wifi Ext HAL service");
68 mService->linkToDeath(mDeathRecipient, 0 /*cookie*/);
69
70 auto hidlCb = [&success](const WifiStatus &status) {
71 success = (status.code == WifiStatusCode::SUCCESS);
72 if (!success) {
73 LOGE("Failed to register CHRE callback with WifiExt: %s",
74 status.description.c_str());
75 }
76 };
77 auto result = mService->registerChreCallback(mCallback, hidlCb);
78 if (!result.isOk()) {
79 LOGE("Failed to register CHRE callback with WifiEmDeathRecipientxt: %s",
80 result.description().c_str());
81 } else {
82 success = true;
83 }
84 } else {
85 LOGE("Failed to connect to Wifi Ext HAL service");
86 }
87 }
88 return success;
89 }
90
onWifiExtHalServiceDeath()91 void WifiExtHalHandler::onWifiExtHalServiceDeath() {
92 LOGI("WiFi Ext HAL service died");
93 mService = nullptr;
94 // TODO(b/204226580): Figure out if wifi ext HAL is stateful and if it
95 // isn't, notify CHRE of a NAN disabled status change to enable nanoapps
96 // to not expect NAN data until the service is back up, and expect it to
97 // do a re-enable when needed. Or we could store the current status of
98 // enablement, and do a re-enable/disable when the service is back up.
99 }
100
wifiExtHandlerThreadEntry()101 void WifiExtHalHandler::wifiExtHandlerThreadEntry() {
102 while (mThreadRunning) {
103 std::unique_lock<std::mutex> lock(mMutex);
104 mCondVar.wait(
105 lock, [this] { return mEnableConfig.has_value() || !mThreadRunning; });
106
107 if (mThreadRunning) {
108 dispatchConfigurationRequest(mEnableConfig.value());
109 mEnableConfig.reset();
110 }
111 }
112 }
113
notifyThreadToExit()114 void WifiExtHalHandler::notifyThreadToExit() {
115 std::lock_guard<std::mutex> lock(mMutex);
116 mThreadRunning = false;
117 mCondVar.notify_one();
118 }
119
120 } // namespace chre
121 } // namespace android
122