From 7c06a601e65bab073f5eb8b3c260b8c2ddd809e7 Mon Sep 17 00:00:00 2001 From: Cosmin Tanislav Date: Tue, 21 Sep 2021 01:54:58 +0300 Subject: [PATCH] sm8350-common: import 2.X sensors hal proxy --- sensors/Android.bp | 2 + sensors/HalProxy.cpp | 754 +++++++++++++++++++++++++++++++++++ sensors/HalProxyCallback.cpp | 84 ++++ 3 files changed, 840 insertions(+) create mode 100644 sensors/HalProxy.cpp create mode 100644 sensors/HalProxyCallback.cpp diff --git a/sensors/Android.bp b/sensors/Android.bp index 6a7cac9..a3b462d 100644 --- a/sensors/Android.bp +++ b/sensors/Android.bp @@ -22,6 +22,8 @@ cc_binary { relative_install_path: "hw", srcs: [ "service.cpp", + "HalProxy.cpp", + "HalProxyCallback.cpp", ], init_rc: ["android.hardware.sensors@2.1-service-multihal.rc"], vintf_fragments: ["android.hardware.sensors@2.1-multihal.xml"], diff --git a/sensors/HalProxy.cpp b/sensors/HalProxy.cpp new file mode 100644 index 0000000..fe3fc84 --- /dev/null +++ b/sensors/HalProxy.cpp @@ -0,0 +1,754 @@ +/* + * Copyright (C) 2019 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 "HalProxy.h" + +#include + +#include +#include "hardware_legacy/power.h" + +#include + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_1 { +namespace implementation { + +using ::android::hardware::sensors::V1_0::Result; +using ::android::hardware::sensors::V2_0::EventQueueFlagBits; +using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits; +using ::android::hardware::sensors::V2_0::implementation::getTimeNow; +using ::android::hardware::sensors::V2_0::implementation::kWakelockTimeoutNs; + +typedef V2_0::implementation::ISensorsSubHal*(SensorsHalGetSubHalFunc)(uint32_t*); +typedef V2_1::implementation::ISensorsSubHal*(SensorsHalGetSubHalV2_1Func)(uint32_t*); + +static constexpr int32_t kBitsAfterSubHalIndex = 24; + +/** + * Set the subhal index as first byte of sensor handle and return this modified version. + * + * @param sensorHandle The sensor handle to modify. + * @param subHalIndex The index in the hal proxy of the sub hal this sensor belongs to. + * + * @return The modified sensor handle. + */ +int32_t setSubHalIndex(int32_t sensorHandle, size_t subHalIndex) { + return sensorHandle | (static_cast(subHalIndex) << kBitsAfterSubHalIndex); +} + +/** + * Extract the subHalIndex from sensorHandle. + * + * @param sensorHandle The sensorHandle to extract from. + * + * @return The subhal index. + */ +size_t extractSubHalIndex(int32_t sensorHandle) { + return static_cast(sensorHandle >> kBitsAfterSubHalIndex); +} + +/** + * Convert nanoseconds to milliseconds. + * + * @param nanos The nanoseconds input. + * + * @return The milliseconds count. + */ +int64_t msFromNs(int64_t nanos) { + constexpr int64_t nanosecondsInAMillsecond = 1000000; + return nanos / nanosecondsInAMillsecond; +} + +HalProxy::HalProxy() { + const char* kMultiHalConfigFile = "/vendor/etc/sensors/hals.conf"; + initializeSubHalListFromConfigFile(kMultiHalConfigFile); + init(); +} + +HalProxy::HalProxy(std::vector& subHalList) { + for (ISensorsSubHalV2_0* subHal : subHalList) { + mSubHalList.push_back(std::make_unique(subHal)); + } + + init(); +} + +HalProxy::HalProxy(std::vector& subHalList, + std::vector& subHalListV2_1) { + for (ISensorsSubHalV2_0* subHal : subHalList) { + mSubHalList.push_back(std::make_unique(subHal)); + } + + for (ISensorsSubHalV2_1* subHal : subHalListV2_1) { + mSubHalList.push_back(std::make_unique(subHal)); + } + + init(); +} + +HalProxy::~HalProxy() { + stopThreads(); +} + +Return HalProxy::getSensorsList_2_1(ISensorsV2_1::getSensorsList_2_1_cb _hidl_cb) { + std::vector sensors; + for (const auto& iter : mSensors) { + sensors.push_back(iter.second); + } + _hidl_cb(sensors); + return Void(); +} + +Return HalProxy::getSensorsList(ISensorsV2_0::getSensorsList_cb _hidl_cb) { + std::vector sensors; + for (const auto& iter : mSensors) { + sensors.push_back(convertToOldSensorInfo(iter.second)); + } + _hidl_cb(sensors); + return Void(); +} + +Return HalProxy::setOperationMode(OperationMode mode) { + Result result = Result::OK; + size_t subHalIndex; + for (subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) { + result = mSubHalList[subHalIndex]->setOperationMode(mode); + if (result != Result::OK) { + ALOGE("setOperationMode failed for SubHal: %s", + mSubHalList[subHalIndex]->getName().c_str()); + break; + } + } + + if (result != Result::OK) { + // Reset the subhal operation modes that have been flipped + for (size_t i = 0; i < subHalIndex; i++) { + mSubHalList[i]->setOperationMode(mCurrentOperationMode); + } + } else { + mCurrentOperationMode = mode; + } + return result; +} + +Return HalProxy::activate(int32_t sensorHandle, bool enabled) { + if (!isSubHalIndexValid(sensorHandle)) { + return Result::BAD_VALUE; + } + return getSubHalForSensorHandle(sensorHandle) + ->activate(clearSubHalIndex(sensorHandle), enabled); +} + +Return HalProxy::initialize_2_1( + const ::android::hardware::MQDescriptorSync& eventQueueDescriptor, + const ::android::hardware::MQDescriptorSync& wakeLockDescriptor, + const sp& sensorsCallback) { + sp dynamicCallback = + new ISensorsCallbackWrapperV2_1(sensorsCallback); + + // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions. + auto eventQueue = + std::make_unique(eventQueueDescriptor, true /* resetPointers */); + std::unique_ptr queue = + std::make_unique(eventQueue); + + return initializeCommon(queue, wakeLockDescriptor, dynamicCallback); +} + +Return HalProxy::initialize( + const ::android::hardware::MQDescriptorSync& eventQueueDescriptor, + const ::android::hardware::MQDescriptorSync& wakeLockDescriptor, + const sp& sensorsCallback) { + sp dynamicCallback = + new ISensorsCallbackWrapperV2_0(sensorsCallback); + + // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions. + auto eventQueue = + std::make_unique(eventQueueDescriptor, true /* resetPointers */); + std::unique_ptr queue = + std::make_unique(eventQueue); + + return initializeCommon(queue, wakeLockDescriptor, dynamicCallback); +} + +Return HalProxy::initializeCommon( + std::unique_ptr& eventQueue, + const ::android::hardware::MQDescriptorSync& wakeLockDescriptor, + const sp& sensorsCallback) { + Result result = Result::OK; + + stopThreads(); + resetSharedWakelock(); + + // So that the pending write events queue can be cleared safely and when we start threads + // again we do not get new events until after initialize resets the subhals. + disableAllSensors(); + + // Clears the queue if any events were pending write before. + mPendingWriteEventsQueue = std::queue, size_t>>(); + mSizePendingWriteEventsQueue = 0; + + // Clears previously connected dynamic sensors + mDynamicSensors.clear(); + + mDynamicSensorsCallback = sensorsCallback; + + // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions. + mEventQueue = std::move(eventQueue); + + // Create the Wake Lock FMQ that is used by the framework to communicate whenever WAKE_UP + // events have been successfully read and handled by the framework. + mWakeLockQueue = + std::make_unique(wakeLockDescriptor, true /* resetPointers */); + + if (mEventQueueFlag != nullptr) { + EventFlag::deleteEventFlag(&mEventQueueFlag); + } + if (mWakelockQueueFlag != nullptr) { + EventFlag::deleteEventFlag(&mWakelockQueueFlag); + } + if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) { + result = Result::BAD_VALUE; + } + if (EventFlag::createEventFlag(mWakeLockQueue->getEventFlagWord(), &mWakelockQueueFlag) != OK) { + result = Result::BAD_VALUE; + } + if (!mDynamicSensorsCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) { + result = Result::BAD_VALUE; + } + + mThreadsRun.store(true); + + mPendingWritesThread = std::thread(startPendingWritesThread, this); + mWakelockThread = std::thread(startWakelockThread, this); + + for (size_t i = 0; i < mSubHalList.size(); i++) { + Result currRes = mSubHalList[i]->initialize(this, this, i); + if (currRes != Result::OK) { + result = currRes; + ALOGE("Subhal '%s' failed to initialize.", mSubHalList[i]->getName().c_str()); + break; + } + } + + mCurrentOperationMode = OperationMode::NORMAL; + + return result; +} + +Return HalProxy::batch(int32_t sensorHandle, int64_t samplingPeriodNs, + int64_t maxReportLatencyNs) { + if (!isSubHalIndexValid(sensorHandle)) { + return Result::BAD_VALUE; + } + return getSubHalForSensorHandle(sensorHandle) + ->batch(clearSubHalIndex(sensorHandle), samplingPeriodNs, maxReportLatencyNs); +} + +Return HalProxy::flush(int32_t sensorHandle) { + if (!isSubHalIndexValid(sensorHandle)) { + return Result::BAD_VALUE; + } + return getSubHalForSensorHandle(sensorHandle)->flush(clearSubHalIndex(sensorHandle)); +} + +Return HalProxy::injectSensorData_2_1(const V2_1::Event& event) { + return injectSensorData(convertToOldEvent(event)); +} + +Return HalProxy::injectSensorData(const V1_0::Event& event) { + Result result = Result::OK; + if (mCurrentOperationMode == OperationMode::NORMAL && + event.sensorType != V1_0::SensorType::ADDITIONAL_INFO) { + ALOGE("An event with type != ADDITIONAL_INFO passed to injectSensorData while operation" + " mode was NORMAL."); + result = Result::BAD_VALUE; + } + if (result == Result::OK) { + V1_0::Event subHalEvent = event; + if (!isSubHalIndexValid(event.sensorHandle)) { + return Result::BAD_VALUE; + } + subHalEvent.sensorHandle = clearSubHalIndex(event.sensorHandle); + result = getSubHalForSensorHandle(event.sensorHandle) + ->injectSensorData(convertToNewEvent(subHalEvent)); + } + return result; +} + +Return HalProxy::registerDirectChannel(const SharedMemInfo& mem, + ISensorsV2_0::registerDirectChannel_cb _hidl_cb) { + if (mDirectChannelSubHal == nullptr) { + _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */); + } else { + mDirectChannelSubHal->registerDirectChannel(mem, _hidl_cb); + } + return Return(); +} + +Return HalProxy::unregisterDirectChannel(int32_t channelHandle) { + Result result; + if (mDirectChannelSubHal == nullptr) { + result = Result::INVALID_OPERATION; + } else { + result = mDirectChannelSubHal->unregisterDirectChannel(channelHandle); + } + return result; +} + +Return HalProxy::configDirectReport(int32_t sensorHandle, int32_t channelHandle, + RateLevel rate, + ISensorsV2_0::configDirectReport_cb _hidl_cb) { + if (mDirectChannelSubHal == nullptr) { + _hidl_cb(Result::INVALID_OPERATION, -1 /* reportToken */); + } else if (sensorHandle == -1 && rate != RateLevel::STOP) { + _hidl_cb(Result::BAD_VALUE, -1 /* reportToken */); + } else { + // -1 denotes all sensors should be disabled + if (sensorHandle != -1) { + sensorHandle = clearSubHalIndex(sensorHandle); + } + mDirectChannelSubHal->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb); + } + return Return(); +} + +Return HalProxy::debug(const hidl_handle& fd, const hidl_vec& /*args*/) { + if (fd.getNativeHandle() == nullptr || fd->numFds < 1) { + ALOGE("%s: missing fd for writing", __FUNCTION__); + return Void(); + } + + android::base::borrowed_fd writeFd = dup(fd->data[0]); + + std::ostringstream stream; + stream << "===HalProxy===" << std::endl; + stream << "Internal values:" << std::endl; + stream << " Threads are running: " << (mThreadsRun.load() ? "true" : "false") << std::endl; + int64_t now = getTimeNow(); + stream << " Wakelock timeout start time: " << msFromNs(now - mWakelockTimeoutStartTime) + << " ms ago" << std::endl; + stream << " Wakelock timeout reset time: " << msFromNs(now - mWakelockTimeoutResetTime) + << " ms ago" << std::endl; + // TODO(b/142969448): Add logging for history of wakelock acquisition per subhal. + stream << " Wakelock ref count: " << mWakelockRefCount << std::endl; + stream << " # of events on pending write writes queue: " << mSizePendingWriteEventsQueue + << std::endl; + stream << " Most events seen on pending write events queue: " + << mMostEventsObservedPendingWriteEventsQueue << std::endl; + if (!mPendingWriteEventsQueue.empty()) { + stream << " Size of events list on front of pending writes queue: " + << mPendingWriteEventsQueue.front().first.size() << std::endl; + } + stream << " # of non-dynamic sensors across all subhals: " << mSensors.size() << std::endl; + stream << " # of dynamic sensors across all subhals: " << mDynamicSensors.size() << std::endl; + stream << "SubHals (" << mSubHalList.size() << "):" << std::endl; + for (auto& subHal : mSubHalList) { + stream << " Name: " << subHal->getName() << std::endl; + stream << " Debug dump: " << std::endl; + android::base::WriteStringToFd(stream.str(), writeFd); + subHal->debug(fd, {}); + stream.str(""); + stream << std::endl; + } + android::base::WriteStringToFd(stream.str(), writeFd); + return Return(); +} + +Return HalProxy::onDynamicSensorsConnected(const hidl_vec& dynamicSensorsAdded, + int32_t subHalIndex) { + std::vector sensors; + { + std::lock_guard lock(mDynamicSensorsMutex); + for (SensorInfo sensor : dynamicSensorsAdded) { + if (!subHalIndexIsClear(sensor.sensorHandle)) { + ALOGE("Dynamic sensor added %s had sensorHandle with first byte not 0.", + sensor.name.c_str()); + } else { + sensor.sensorHandle = setSubHalIndex(sensor.sensorHandle, subHalIndex); + mDynamicSensors[sensor.sensorHandle] = sensor; + sensors.push_back(sensor); + } + } + } + mDynamicSensorsCallback->onDynamicSensorsConnected(sensors); + return Return(); +} + +Return HalProxy::onDynamicSensorsDisconnected( + const hidl_vec& dynamicSensorHandlesRemoved, int32_t subHalIndex) { + // TODO(b/143302327): Block this call until all pending events are flushed from queue + std::vector sensorHandles; + { + std::lock_guard lock(mDynamicSensorsMutex); + for (int32_t sensorHandle : dynamicSensorHandlesRemoved) { + if (!subHalIndexIsClear(sensorHandle)) { + ALOGE("Dynamic sensorHandle removed had first byte not 0."); + } else { + sensorHandle = setSubHalIndex(sensorHandle, subHalIndex); + if (mDynamicSensors.find(sensorHandle) != mDynamicSensors.end()) { + mDynamicSensors.erase(sensorHandle); + sensorHandles.push_back(sensorHandle); + } + } + } + } + mDynamicSensorsCallback->onDynamicSensorsDisconnected(sensorHandles); + return Return(); +} + +void HalProxy::initializeSubHalListFromConfigFile(const char* configFileName) { + std::ifstream subHalConfigStream(configFileName); + if (!subHalConfigStream) { + ALOGE("Failed to load subHal config file: %s", configFileName); + } else { + std::string subHalLibraryFile; + while (subHalConfigStream >> subHalLibraryFile) { + void* handle = getHandleForSubHalSharedObject(subHalLibraryFile); + if (handle == nullptr) { + ALOGE("dlopen failed for library: %s", subHalLibraryFile.c_str()); + } else { + SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr = + (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal"); + if (sensorsHalGetSubHalPtr != nullptr) { + std::function sensorsHalGetSubHal = + *sensorsHalGetSubHalPtr; + uint32_t version; + ISensorsSubHalV2_0* subHal = sensorsHalGetSubHal(&version); + if (version != SUB_HAL_2_0_VERSION) { + ALOGE("SubHal version was not 2.0 for library: %s", + subHalLibraryFile.c_str()); + } else { + ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str()); + mSubHalList.push_back(std::make_unique(subHal)); + } + } else { + SensorsHalGetSubHalV2_1Func* getSubHalV2_1Ptr = + (SensorsHalGetSubHalV2_1Func*)dlsym(handle, "sensorsHalGetSubHal_2_1"); + + if (getSubHalV2_1Ptr == nullptr) { + ALOGE("Failed to locate sensorsHalGetSubHal function for library: %s", + subHalLibraryFile.c_str()); + } else { + std::function sensorsHalGetSubHal_2_1 = + *getSubHalV2_1Ptr; + uint32_t version; + ISensorsSubHalV2_1* subHal = sensorsHalGetSubHal_2_1(&version); + if (version != SUB_HAL_2_1_VERSION) { + ALOGE("SubHal version was not 2.1 for library: %s", + subHalLibraryFile.c_str()); + } else { + ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str()); + mSubHalList.push_back(std::make_unique(subHal)); + } + } + } + } + } + } +} + +void HalProxy::initializeSensorList() { + for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) { + auto result = mSubHalList[subHalIndex]->getSensorsList([&](const auto& list) { + for (SensorInfo sensor : list) { + if (!subHalIndexIsClear(sensor.sensorHandle)) { + ALOGE("SubHal sensorHandle's first byte was not 0"); + } else { + ALOGV("Loaded sensor: %s", sensor.name.c_str()); + sensor.sensorHandle = setSubHalIndex(sensor.sensorHandle, subHalIndex); + setDirectChannelFlags(&sensor, mSubHalList[subHalIndex]); + mSensors[sensor.sensorHandle] = sensor; + } + } + }); + if (!result.isOk()) { + ALOGE("getSensorsList call failed for SubHal: %s", + mSubHalList[subHalIndex]->getName().c_str()); + } + } +} + +void* HalProxy::getHandleForSubHalSharedObject(const std::string& filename) { + static const std::string kSubHalShareObjectLocations[] = { + "", // Default locations will be searched +#ifdef __LP64__ + "/vendor/lib64/hw/", "/odm/lib64/hw/" +#else + "/vendor/lib/hw/", "/odm/lib/hw/" +#endif + }; + + for (const std::string& dir : kSubHalShareObjectLocations) { + void* handle = dlopen((dir + filename).c_str(), RTLD_NOW); + if (handle != nullptr) { + return handle; + } + } + return nullptr; +} + +void HalProxy::init() { + initializeSensorList(); +} + +void HalProxy::stopThreads() { + mThreadsRun.store(false); + if (mEventQueueFlag != nullptr && mEventQueue != nullptr) { + size_t numToRead = mEventQueue->availableToRead(); + std::vector events(numToRead); + mEventQueue->read(events.data(), numToRead); + mEventQueueFlag->wake(static_cast(EventQueueFlagBits::EVENTS_READ)); + } + if (mWakelockQueueFlag != nullptr && mWakeLockQueue != nullptr) { + uint32_t kZero = 0; + mWakeLockQueue->write(&kZero); + mWakelockQueueFlag->wake(static_cast(WakeLockQueueFlagBits::DATA_WRITTEN)); + } + mWakelockCV.notify_one(); + mEventQueueWriteCV.notify_one(); + if (mPendingWritesThread.joinable()) { + mPendingWritesThread.join(); + } + if (mWakelockThread.joinable()) { + mWakelockThread.join(); + } +} + +void HalProxy::disableAllSensors() { + for (const auto& sensorEntry : mSensors) { + int32_t sensorHandle = sensorEntry.first; + activate(sensorHandle, false /* enabled */); + } + std::lock_guard dynamicSensorsLock(mDynamicSensorsMutex); + for (const auto& sensorEntry : mDynamicSensors) { + int32_t sensorHandle = sensorEntry.first; + activate(sensorHandle, false /* enabled */); + } +} + +void HalProxy::startPendingWritesThread(HalProxy* halProxy) { + halProxy->handlePendingWrites(); +} + +void HalProxy::handlePendingWrites() { + // TODO(b/143302327): Find a way to optimize locking strategy maybe using two mutexes instead of + // one. + std::unique_lock lock(mEventQueueWriteMutex); + while (mThreadsRun.load()) { + mEventQueueWriteCV.wait( + lock, [&] { return !mPendingWriteEventsQueue.empty() || !mThreadsRun.load(); }); + if (mThreadsRun.load()) { + std::vector& pendingWriteEvents = mPendingWriteEventsQueue.front().first; + size_t numWakeupEvents = mPendingWriteEventsQueue.front().second; + size_t eventQueueSize = mEventQueue->getQuantumCount(); + size_t numToWrite = std::min(pendingWriteEvents.size(), eventQueueSize); + lock.unlock(); + if (!mEventQueue->writeBlocking( + pendingWriteEvents.data(), numToWrite, + static_cast(EventQueueFlagBits::EVENTS_READ), + static_cast(EventQueueFlagBits::READ_AND_PROCESS), + kPendingWriteTimeoutNs, mEventQueueFlag)) { + ALOGE("Dropping %zu events after blockingWrite failed.", numToWrite); + if (numWakeupEvents > 0) { + if (pendingWriteEvents.size() > eventQueueSize) { + decrementRefCountAndMaybeReleaseWakelock( + countNumWakeupEvents(pendingWriteEvents, eventQueueSize)); + } else { + decrementRefCountAndMaybeReleaseWakelock(numWakeupEvents); + } + } + } + lock.lock(); + mSizePendingWriteEventsQueue -= numToWrite; + if (pendingWriteEvents.size() > eventQueueSize) { + // TODO(b/143302327): Check if this erase operation is too inefficient. It will copy + // all the events ahead of it down to fill gap off array at front after the erase. + pendingWriteEvents.erase(pendingWriteEvents.begin(), + pendingWriteEvents.begin() + eventQueueSize); + } else { + mPendingWriteEventsQueue.pop(); + } + } + } +} + +void HalProxy::startWakelockThread(HalProxy* halProxy) { + halProxy->handleWakelocks(); +} + +void HalProxy::handleWakelocks() { + std::unique_lock lock(mWakelockMutex); + while (mThreadsRun.load()) { + mWakelockCV.wait(lock, [&] { return mWakelockRefCount > 0 || !mThreadsRun.load(); }); + if (mThreadsRun.load()) { + int64_t timeLeft; + if (sharedWakelockDidTimeout(&timeLeft)) { + resetSharedWakelock(); + } else { + uint32_t numWakeLocksProcessed; + lock.unlock(); + bool success = mWakeLockQueue->readBlocking( + &numWakeLocksProcessed, 1, 0, + static_cast(WakeLockQueueFlagBits::DATA_WRITTEN), timeLeft); + lock.lock(); + if (success) { + decrementRefCountAndMaybeReleaseWakelock( + static_cast(numWakeLocksProcessed)); + } + } + } + } + resetSharedWakelock(); +} + +bool HalProxy::sharedWakelockDidTimeout(int64_t* timeLeft) { + bool didTimeout; + int64_t duration = getTimeNow() - mWakelockTimeoutStartTime; + if (duration > kWakelockTimeoutNs) { + didTimeout = true; + } else { + didTimeout = false; + *timeLeft = kWakelockTimeoutNs - duration; + } + return didTimeout; +} + +void HalProxy::resetSharedWakelock() { + std::lock_guard lockGuard(mWakelockMutex); + decrementRefCountAndMaybeReleaseWakelock(mWakelockRefCount); + mWakelockTimeoutResetTime = getTimeNow(); +} + +void HalProxy::postEventsToMessageQueue(const std::vector& events, size_t numWakeupEvents, + V2_0::implementation::ScopedWakelock wakelock) { + size_t numToWrite = 0; + std::lock_guard lock(mEventQueueWriteMutex); + if (wakelock.isLocked()) { + incrementRefCountAndMaybeAcquireWakelock(numWakeupEvents); + } + if (mPendingWriteEventsQueue.empty()) { + numToWrite = std::min(events.size(), mEventQueue->availableToWrite()); + if (numToWrite > 0) { + if (mEventQueue->write(events.data(), numToWrite)) { + // TODO(b/143302327): While loop if mEventQueue->avaiableToWrite > 0 to possibly fit + // in more writes immediately + mEventQueueFlag->wake(static_cast(EventQueueFlagBits::READ_AND_PROCESS)); + } else { + numToWrite = 0; + } + } + } + size_t numLeft = events.size() - numToWrite; + if (numToWrite < events.size() && + mSizePendingWriteEventsQueue + numLeft <= kMaxSizePendingWriteEventsQueue) { + std::vector eventsLeft(events.begin() + numToWrite, events.end()); + mPendingWriteEventsQueue.push({eventsLeft, numWakeupEvents}); + mSizePendingWriteEventsQueue += numLeft; + mMostEventsObservedPendingWriteEventsQueue = + std::max(mMostEventsObservedPendingWriteEventsQueue, mSizePendingWriteEventsQueue); + mEventQueueWriteCV.notify_one(); + } +} + +bool HalProxy::incrementRefCountAndMaybeAcquireWakelock(size_t delta, + int64_t* timeoutStart /* = nullptr */) { + if (!mThreadsRun.load()) return false; + std::lock_guard lockGuard(mWakelockMutex); + if (mWakelockRefCount == 0) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakelockName); + mWakelockCV.notify_one(); + } + mWakelockTimeoutStartTime = getTimeNow(); + mWakelockRefCount += delta; + if (timeoutStart != nullptr) { + *timeoutStart = mWakelockTimeoutStartTime; + } + return true; +} + +void HalProxy::decrementRefCountAndMaybeReleaseWakelock(size_t delta, + int64_t timeoutStart /* = -1 */) { + if (!mThreadsRun.load()) return; + std::lock_guard lockGuard(mWakelockMutex); + if (delta > mWakelockRefCount) { + ALOGE("Decrementing wakelock ref count by %zu when count is %zu", + delta, mWakelockRefCount); + } + if (timeoutStart == -1) timeoutStart = mWakelockTimeoutResetTime; + if (mWakelockRefCount == 0 || timeoutStart < mWakelockTimeoutResetTime) return; + mWakelockRefCount -= std::min(mWakelockRefCount, delta); + if (mWakelockRefCount == 0) { + release_wake_lock(kWakelockName); + } +} + +void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo, + std::shared_ptr subHal) { + bool sensorSupportsDirectChannel = + (sensorInfo->flags & (V1_0::SensorFlagBits::MASK_DIRECT_REPORT | + V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL)) != 0; + if (mDirectChannelSubHal == nullptr && sensorSupportsDirectChannel) { + mDirectChannelSubHal = subHal; + } else if (mDirectChannelSubHal != nullptr && subHal != mDirectChannelSubHal) { + // disable direct channel capability for sensors in subHals that are not + // the only one we will enable + sensorInfo->flags &= ~(V1_0::SensorFlagBits::MASK_DIRECT_REPORT | + V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL); + } +} + +std::shared_ptr HalProxy::getSubHalForSensorHandle(int32_t sensorHandle) { + return mSubHalList[extractSubHalIndex(sensorHandle)]; +} + +bool HalProxy::isSubHalIndexValid(int32_t sensorHandle) { + return extractSubHalIndex(sensorHandle) < mSubHalList.size(); +} + +size_t HalProxy::countNumWakeupEvents(const std::vector& events, size_t n) { + size_t numWakeupEvents = 0; + for (size_t i = 0; i < n; i++) { + int32_t sensorHandle = events[i].sensorHandle; + if (mSensors[sensorHandle].flags & static_cast(V1_0::SensorFlagBits::WAKE_UP)) { + numWakeupEvents++; + } + } + return numWakeupEvents; +} + +int32_t HalProxy::clearSubHalIndex(int32_t sensorHandle) { + return sensorHandle & (~kSensorHandleSubHalIndexMask); +} + +bool HalProxy::subHalIndexIsClear(int32_t sensorHandle) { + return (sensorHandle & kSensorHandleSubHalIndexMask) == 0; +} + +} // namespace implementation +} // namespace V2_1 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/HalProxyCallback.cpp b/sensors/HalProxyCallback.cpp new file mode 100644 index 0000000..3c1b17c --- /dev/null +++ b/sensors/HalProxyCallback.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2019 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 "HalProxyCallback.h" + +#include + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_0 { +namespace implementation { + +static constexpr int32_t kBitsAfterSubHalIndex = 24; + +/** + * Set the subhal index as first byte of sensor handle and return this modified version. + * + * @param sensorHandle The sensor handle to modify. + * @param subHalIndex The index in the hal proxy of the sub hal this sensor belongs to. + * + * @return The modified sensor handle. + */ +int32_t setSubHalIndex(int32_t sensorHandle, size_t subHalIndex) { + return sensorHandle | (static_cast(subHalIndex) << kBitsAfterSubHalIndex); +} + +void HalProxyCallbackBase::postEvents(const std::vector& events, + ScopedWakelock wakelock) { + if (events.empty() || !mCallback->areThreadsRunning()) return; + size_t numWakeupEvents; + std::vector processedEvents = processEvents(events, &numWakeupEvents); + if (numWakeupEvents > 0) { + ALOG_ASSERT(wakelock.isLocked(), + "Wakeup events posted while wakelock unlocked for subhal" + " w/ index %" PRId32 ".", + mSubHalIndex); + } else { + ALOG_ASSERT(!wakelock.isLocked(), + "No Wakeup events posted but wakelock locked for subhal" + " w/ index %" PRId32 ".", + mSubHalIndex); + } + mCallback->postEventsToMessageQueue(processedEvents, numWakeupEvents, std::move(wakelock)); +} + +ScopedWakelock HalProxyCallbackBase::createScopedWakelock(bool lock) { + ScopedWakelock wakelock(mRefCounter, lock); + return wakelock; +} + +std::vector HalProxyCallbackBase::processEvents(const std::vector& events, + size_t* numWakeupEvents) const { + *numWakeupEvents = 0; + std::vector eventsOut; + for (V2_1::Event event : events) { + event.sensorHandle = setSubHalIndex(event.sensorHandle, mSubHalIndex); + eventsOut.push_back(event); + const V2_1::SensorInfo& sensor = mCallback->getSensorInfo(event.sensorHandle); + if ((sensor.flags & V1_0::SensorFlagBits::WAKE_UP) != 0) { + (*numWakeupEvents)++; + } + } + return eventsOut; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace sensors +} // namespace hardware +} // namespace android