Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f4044876 authored by Roshan Pius's avatar Roshan Pius Committed by android-build-merger
Browse files

Merge changes Ieee26013,I275bba11,I7e7258e7,I88111181 am: 3646298a

am: b853615e

Change-Id: Id42bcb5657613884386b1b978d6931511425c49e
parents 832e7bd8 b853615e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_CPPFLAGS := -Wall -Werror -Wextra
LOCAL_SRC_FILES := \
    hidl_struct_util.cpp \
    hidl_sync_util.cpp \
    service.cpp \
    wifi.cpp \
    wifi_ap_iface.cpp \
+35 −0
Original line number Diff line number Diff line
Vendor HAL Threading Model
==========================
The vendor HAL service has two threads:
1. HIDL thread: This is the main thread which processes all the incoming HIDL
RPC's.
2. Legacy HAL event loop thread: This is the thread forked off for processing
the legacy HAL event loop (wifi_event_loop()). This thread is used to process
any asynchronous netlink events posted by the driver. Any asynchronous
callbacks passed to the legacy HAL API's are invoked on this thread.

Synchronization Concerns
========================
wifi_legacy_hal.cpp has a bunch of global "C" style functions to handle the
legacy callbacks. Each of these "C" style function invokes a corresponding
"std::function" version of the callback which does the actual processing.
The variables holding these "std::function" callbacks are reset from the HIDL
thread when they are no longer used. For example: stopGscan() will reset the
corresponding "on_gscan_*" callback variables which were set when startGscan()
was invoked. This is not thread safe since these callback variables are
accesed from the legacy hal event loop thread as well.

Synchronization Solution
========================
Adding a global lock seems to be the most trivial solution to the problem.
a) All of the asynchronous "C" style callbacks will acquire the global lock
before invoking the corresponding "std::function" callback variables.
b) All of the HIDL methods will also acquire the global lock before processing
(in hidl_return_util::validateAndCall()).

Note: It's important that we only acquire the global lock for asynchronous
callbacks, because there is no guarantee (or documentation to clarify) that the
synchronous callbacks are invoked on the same invocation thread. If that is not
the case in some implementation, we will end up deadlocking the system since the
HIDL thread would have acquired the global lock which is needed by the
synchronous callback executed on the legacy hal event loop thread.
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef HIDL_RETURN_UTIL_H_
#define HIDL_RETURN_UTIL_H_

#include "hidl_sync_util.h"
#include "wifi_status_util.h"

namespace android {
@@ -44,6 +45,7 @@ Return<void> validateAndCall(
    WorkFuncT&& work,
    const std::function<void(const WifiStatus&)>& hidl_cb,
    Args&&... args) {
  const auto lock = hidl_sync_util::acquireGlobalLock();
  if (obj->isValid()) {
    hidl_cb((obj->*work)(std::forward<Args>(args)...));
  } else {
@@ -61,6 +63,7 @@ Return<void> validateAndCall(
    WorkFuncT&& work,
    const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
    Args&&... args) {
  const auto lock = hidl_sync_util::acquireGlobalLock();
  if (obj->isValid()) {
    const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
    const WifiStatus& status = std::get<0>(ret_pair);
@@ -86,6 +89,7 @@ Return<void> validateAndCall(
    WorkFuncT&& work,
    const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb,
    Args&&... args) {
  const auto lock = hidl_sync_util::acquireGlobalLock();
  if (obj->isValid()) {
    const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...);
    const WifiStatus& status = std::get<0>(ret_tuple);
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "hidl_sync_util.h"

namespace {
std::recursive_mutex g_mutex;
}  // namespace

namespace android {
namespace hardware {
namespace wifi {
namespace V1_0 {
namespace implementation {
namespace hidl_sync_util {

std::unique_lock<std::recursive_mutex> acquireGlobalLock() {
  return std::unique_lock<std::recursive_mutex>{g_mutex};
}

}  // namespace hidl_sync_util
}  // namespace implementation
}  // namespace V1_0
}  // namespace wifi
}  // namespace hardware
}  // namespace android
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef HIDL_SYNC_UTIL_H_
#define HIDL_SYNC_UTIL_H_

#include <mutex>

// Utility that provides a global lock to synchronize access between
// the HIDL thread and the legacy HAL's event loop.
namespace android {
namespace hardware {
namespace wifi {
namespace V1_0 {
namespace implementation {
namespace hidl_sync_util {
std::unique_lock<std::recursive_mutex> acquireGlobalLock();
}  // namespace hidl_sync_util
}  // namespace implementation
}  // namespace V1_0
}  // namespace wifi
}  // namespace hardware
}  // namespace android
#endif  // HIDL_SYNC_UTIL_H_
Loading