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

Commit 1d71acc1 authored by Anthony Stange's avatar Anthony Stange
Browse files

Add default impl of Sensors HAL 2.1

Create a default implementation of HAL 2.1 that shares 90% of the
underlying code with HAL 2.0 since the interfaces are very similar.

Bug: 144139857
Test: compile
Change-Id: Ic6b139df98ddb1f92833b1f2d65e1cecc297fd41
parent c002dd9e
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -20,13 +20,17 @@ cc_binary {
    relative_install_path: "hw",
    srcs: [
        "service.cpp",
        "Sensor.cpp",
        "Sensors.cpp",
    ],
    init_rc: ["android.hardware.sensors@2.0-service-mock.rc"],
    header_libs: [
        "android.hardware.sensors@2.X-shared-utils",
    ],
    shared_libs: [
        "android.hardware.sensors@1.0",
        "android.hardware.sensors@2.0",
        // Needed to compile some shared utilities for both 2.0/2.1 impls, but
        // isn't normally needed for a HAL that only supports 2.0.
        "android.hardware.sensors@2.1",
        "libcutils",
        "libfmq",
        "libhidlbase",
@@ -34,5 +38,9 @@ cc_binary {
        "libpower",
        "libutils",
    ],
    static_libs: [
        "android.hardware.sensors@1.0-convert",
        "android.hardware.sensors@2.X-shared-impl",
    ],
    vintf_fragments: ["android.hardware.sensors@2.0.xml"],
}

sensors/2.0/default/Sensors.cpp

deleted100644 → 0
+0 −259
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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 "Sensors.h"

#include <android/hardware/sensors/2.0/types.h>
#include <log/log.h>

namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace implementation {

using ::android::hardware::sensors::V1_0::Event;
using ::android::hardware::sensors::V1_0::OperationMode;
using ::android::hardware::sensors::V1_0::RateLevel;
using ::android::hardware::sensors::V1_0::Result;
using ::android::hardware::sensors::V1_0::SharedMemInfo;
using ::android::hardware::sensors::V2_0::SensorTimeout;
using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;

constexpr const char* kWakeLockName = "SensorsHAL_WAKEUP";

Sensors::Sensors()
    : mEventQueueFlag(nullptr),
      mNextHandle(1),
      mOutstandingWakeUpEvents(0),
      mReadWakeLockQueueRun(false),
      mAutoReleaseWakeLockTime(0),
      mHasWakeLock(false) {
    AddSensor<AccelSensor>();
    AddSensor<GyroSensor>();
    AddSensor<AmbientTempSensor>();
    AddSensor<DeviceTempSensor>();
    AddSensor<PressureSensor>();
    AddSensor<MagnetometerSensor>();
    AddSensor<LightSensor>();
    AddSensor<ProximitySensor>();
    AddSensor<RelativeHumiditySensor>();
}

Sensors::~Sensors() {
    deleteEventFlag();
    mReadWakeLockQueueRun = false;
    mWakeLockThread.join();
}

// Methods from ::android::hardware::sensors::V2_0::ISensors follow.
Return<void> Sensors::getSensorsList(getSensorsList_cb _hidl_cb) {
    std::vector<SensorInfo> sensors;
    for (const auto& sensor : mSensors) {
        sensors.push_back(sensor.second->getSensorInfo());
    }

    // Call the HIDL callback with the SensorInfo
    _hidl_cb(sensors);

    return Void();
}

Return<Result> Sensors::setOperationMode(OperationMode mode) {
    for (auto sensor : mSensors) {
        sensor.second->setOperationMode(mode);
    }
    return Result::OK;
}

Return<Result> Sensors::activate(int32_t sensorHandle, bool enabled) {
    auto sensor = mSensors.find(sensorHandle);
    if (sensor != mSensors.end()) {
        sensor->second->activate(enabled);
        return Result::OK;
    }
    return Result::BAD_VALUE;
}

Return<Result> Sensors::initialize(
    const ::android::hardware::MQDescriptorSync<Event>& eventQueueDescriptor,
    const ::android::hardware::MQDescriptorSync<uint32_t>& wakeLockDescriptor,
    const sp<ISensorsCallback>& sensorsCallback) {
    Result result = Result::OK;

    // Ensure that all sensors are disabled
    for (auto sensor : mSensors) {
        sensor.second->activate(false /* enable */);
    }

    // Stop the Wake Lock thread if it is currently running
    if (mReadWakeLockQueueRun.load()) {
        mReadWakeLockQueueRun = false;
        mWakeLockThread.join();
    }

    // Save a reference to the callback
    mCallback = sensorsCallback;

    // Create the Event FMQ from the eventQueueDescriptor. Reset the read/write positions.
    mEventQueue =
        std::make_unique<EventMessageQueue>(eventQueueDescriptor, true /* resetPointers */);

    // Ensure that any existing EventFlag is properly deleted
    deleteEventFlag();

    // Create the EventFlag that is used to signal to the framework that sensor events have been
    // written to the Event FMQ
    if (EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag) != OK) {
        result = Result::BAD_VALUE;
    }

    // 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<WakeLockMessageQueue>(wakeLockDescriptor, true /* resetPointers */);

    if (!mCallback || !mEventQueue || !mWakeLockQueue || mEventQueueFlag == nullptr) {
        result = Result::BAD_VALUE;
    }

    // Start the thread to read events from the Wake Lock FMQ
    mReadWakeLockQueueRun = true;
    mWakeLockThread = std::thread(startReadWakeLockThread, this);

    return result;
}

Return<Result> Sensors::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
                              int64_t /* maxReportLatencyNs */) {
    auto sensor = mSensors.find(sensorHandle);
    if (sensor != mSensors.end()) {
        sensor->second->batch(samplingPeriodNs);
        return Result::OK;
    }
    return Result::BAD_VALUE;
}

Return<Result> Sensors::flush(int32_t sensorHandle) {
    auto sensor = mSensors.find(sensorHandle);
    if (sensor != mSensors.end()) {
        return sensor->second->flush();
    }
    return Result::BAD_VALUE;
}

Return<Result> Sensors::injectSensorData(const Event& event) {
    auto sensor = mSensors.find(event.sensorHandle);
    if (sensor != mSensors.end()) {
        return sensor->second->injectEvent(event);
    }

    return Result::BAD_VALUE;
}

Return<void> Sensors::registerDirectChannel(const SharedMemInfo& /* mem */,
                                            registerDirectChannel_cb _hidl_cb) {
    _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */);
    return Return<void>();
}

Return<Result> Sensors::unregisterDirectChannel(int32_t /* channelHandle */) {
    return Result::INVALID_OPERATION;
}

Return<void> Sensors::configDirectReport(int32_t /* sensorHandle */, int32_t /* channelHandle */,
                                         RateLevel /* rate */, configDirectReport_cb _hidl_cb) {
    _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */);
    return Return<void>();
}

void Sensors::postEvents(const std::vector<Event>& events, bool wakeup) {
    std::lock_guard<std::mutex> lock(mWriteLock);
    if (mEventQueue->write(events.data(), events.size())) {
        mEventQueueFlag->wake(static_cast<uint32_t>(EventQueueFlagBits::READ_AND_PROCESS));

        if (wakeup) {
            // Keep track of the number of outstanding WAKE_UP events in order to properly hold
            // a wake lock until the framework has secured a wake lock
            updateWakeLock(events.size(), 0 /* eventsHandled */);
        }
    }
}

void Sensors::updateWakeLock(int32_t eventsWritten, int32_t eventsHandled) {
    std::lock_guard<std::mutex> lock(mWakeLockLock);
    int32_t newVal = mOutstandingWakeUpEvents + eventsWritten - eventsHandled;
    if (newVal < 0) {
        mOutstandingWakeUpEvents = 0;
    } else {
        mOutstandingWakeUpEvents = newVal;
    }

    if (eventsWritten > 0) {
        // Update the time at which the last WAKE_UP event was sent
        mAutoReleaseWakeLockTime = ::android::uptimeMillis() +
                                   static_cast<uint32_t>(SensorTimeout::WAKE_LOCK_SECONDS) * 1000;
    }

    if (!mHasWakeLock && mOutstandingWakeUpEvents > 0 &&
        acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLockName) == 0) {
        mHasWakeLock = true;
    } else if (mHasWakeLock) {
        // Check if the wake lock should be released automatically if
        // SensorTimeout::WAKE_LOCK_SECONDS has elapsed since the last WAKE_UP event was written to
        // the Wake Lock FMQ.
        if (::android::uptimeMillis() > mAutoReleaseWakeLockTime) {
            ALOGD("No events read from wake lock FMQ for %d seconds, auto releasing wake lock",
                  SensorTimeout::WAKE_LOCK_SECONDS);
            mOutstandingWakeUpEvents = 0;
        }

        if (mOutstandingWakeUpEvents == 0 && release_wake_lock(kWakeLockName) == 0) {
            mHasWakeLock = false;
        }
    }
}

void Sensors::readWakeLockFMQ() {
    while (mReadWakeLockQueueRun.load()) {
        constexpr int64_t kReadTimeoutNs = 500 * 1000 * 1000;  // 500 ms
        uint32_t eventsHandled = 0;

        // Read events from the Wake Lock FMQ. Timeout after a reasonable amount of time to ensure
        // that any held wake lock is able to be released if it is held for too long.
        mWakeLockQueue->readBlocking(&eventsHandled, 1 /* count */, 0 /* readNotification */,
                                     static_cast<uint32_t>(WakeLockQueueFlagBits::DATA_WRITTEN),
                                     kReadTimeoutNs);
        updateWakeLock(0 /* eventsWritten */, eventsHandled);
    }
}

void Sensors::startReadWakeLockThread(Sensors* sensors) {
    sensors->readWakeLockFMQ();
}

void Sensors::deleteEventFlag() {
    status_t status = EventFlag::deleteEventFlag(&mEventQueueFlag);
    if (status != OK) {
        ALOGI("Failed to delete event flag: %d", status);
    }
}

}  // namespace implementation
}  // namespace V2_0
}  // namespace sensors
}  // namespace hardware
}  // namespace android
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 ANDROID_HARDWARE_SENSORS_V2_0_H
#define ANDROID_HARDWARE_SENSORS_V2_0_H

#include "Sensors.h"

#include <android/hardware/sensors/2.0/ISensors.h>

namespace android {
namespace hardware {
namespace sensors {
namespace V2_0 {
namespace implementation {

struct SensorsV2_0 : public ::android::hardware::sensors::V2_X::implementation::Sensors<ISensors> {
};

}  // namespace implementation
}  // namespace V2_0
}  // namespace sensors
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_SENSORS_V2_0_H
 No newline at end of file
+3 −3
Original line number Diff line number Diff line
@@ -20,17 +20,17 @@
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <utils/StrongPointer.h>
#include "Sensors.h"
#include "SensorsV2_0.h"

using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using android::hardware::sensors::V2_0::ISensors;
using android::hardware::sensors::V2_0::implementation::Sensors;
using android::hardware::sensors::V2_0::implementation::SensorsV2_0;

int main(int /* argc */, char** /* argv */) {
    configureRpcThreadpool(1, true);

    android::sp<ISensors> sensors = new Sensors();
    android::sp<ISensors> sensors = new SensorsV2_0();
    if (sensors->registerAsService() != ::android::OK) {
        ALOGE("Failed to register Sensors HAL instance");
        return -1;
+45 −0
Original line number Diff line number Diff line
//
// Copyright (C) 2018 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.

cc_binary {
    name: "android.hardware.sensors@2.1-service.mock",
    defaults: ["hidl_defaults"],
    vendor: true,
    relative_install_path: "hw",
    srcs: [
        "SensorsV2_1.cpp",
        "service.cpp",
    ],
    init_rc: ["android.hardware.sensors@2.1-service-mock.rc"],
    header_libs: [
        "android.hardware.sensors@2.X-shared-utils",
    ],
    shared_libs: [
        "android.hardware.sensors@1.0",
        "android.hardware.sensors@2.0",
        "android.hardware.sensors@2.1",
        "libcutils",
        "libfmq",
        "libhidlbase",
        "liblog",
        "libpower",
        "libutils",
    ],
    static_libs: [
        "android.hardware.sensors@1.0-convert",
        "android.hardware.sensors@2.X-shared-impl",
    ],
    vintf_fragments: ["android.hardware.sensors@2.1.xml"],
}
Loading