From c34e6683b1ec0ccd09738f6d8a2206e75dd16e3a Mon Sep 17 00:00:00 2001 From: Anthony Stange Date: Fri, 9 Aug 2019 11:24:17 -0400 Subject: [PATCH] Add a sub-HAL implementation for testing multi-HAL Creates a fake sub-HAL using the default implementation for sensors HAL 2.0 with some small modifications to support the multi-HAL interface. This sub-HAL can be configured to support two different sets of sensors making it easier to build and load two different sub-HAL implementations onto device and verify the multihal implementation works. Bug: 136511617 Test: compile only. Once multihal can load in sub-HALs, then this can be accurately tested. Change-Id: I9b136506bdbc8a3b196fd363748bddfcdd564daf --- sensors/2.0/multihal/Android.bp | 9 + sensors/2.0/multihal/{ => include}/SubHal.h | 2 +- sensors/2.0/multihal/testing/Android.bp | 55 +++ sensors/2.0/multihal/testing/README | 19 + sensors/2.0/multihal/testing/Sensor.cpp | 372 ++++++++++++++++++ sensors/2.0/multihal/testing/Sensor.h | 146 +++++++ .../2.0/multihal/testing/SensorsSubHal.cpp | 179 +++++++++ sensors/2.0/multihal/testing/SensorsSubHal.h | 115 ++++++ 8 files changed, 896 insertions(+), 1 deletion(-) rename sensors/2.0/multihal/{ => include}/SubHal.h (99%) create mode 100644 sensors/2.0/multihal/testing/Android.bp create mode 100644 sensors/2.0/multihal/testing/README create mode 100644 sensors/2.0/multihal/testing/Sensor.cpp create mode 100644 sensors/2.0/multihal/testing/Sensor.h create mode 100644 sensors/2.0/multihal/testing/SensorsSubHal.cpp create mode 100644 sensors/2.0/multihal/testing/SensorsSubHal.h diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp index 4dec768abf..f0b33e42a1 100644 --- a/sensors/2.0/multihal/Android.bp +++ b/sensors/2.0/multihal/Android.bp @@ -23,6 +23,9 @@ cc_binary { "HalProxy.cpp", ], init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"], + header_libs: [ + "android.hardware.sensors@2.0-subhal.header", + ], shared_libs: [ "android.hardware.sensors@1.0", "android.hardware.sensors@2.0", @@ -36,3 +39,9 @@ cc_binary { ], vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"], } + +cc_library_headers { + name: "android.hardware.sensors@2.0-subhal.header", + vendor: true, + export_include_dirs: ["include"], +} \ No newline at end of file diff --git a/sensors/2.0/multihal/SubHal.h b/sensors/2.0/multihal/include/SubHal.h similarity index 99% rename from sensors/2.0/multihal/SubHal.h rename to sensors/2.0/multihal/include/SubHal.h index 152f91d96c..75e93a18b5 100644 --- a/sensors/2.0/multihal/SubHal.h +++ b/sensors/2.0/multihal/include/SubHal.h @@ -163,7 +163,7 @@ class ISensorsSubHal : public ISensors { /** * @return A human-readable name for use in wake locks and logging. */ - virtual const std::string& getName() = 0; + virtual const std::string getName() = 0; /** * First method invoked on the sub-HAL after it's allocated through sensorsHalGetSubHal() by the diff --git a/sensors/2.0/multihal/testing/Android.bp b/sensors/2.0/multihal/testing/Android.bp new file mode 100644 index 0000000000..3dedbd69cf --- /dev/null +++ b/sensors/2.0/multihal/testing/Android.bp @@ -0,0 +1,55 @@ +// +// 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. + +cc_defaults { + name: "android.hardware.sensors@2.0-fakesubhal-defaults", + vendor: true, + srcs: [ + "Sensor.cpp", + "SensorsSubHal.cpp", + ], + header_libs: [ + "android.hardware.sensors@2.0-subhal.header", + ], + shared_libs: [ + "android.hardware.sensors@1.0", + "android.hardware.sensors@2.0", + "libcutils", + "libfmq", + "libhidlbase", + "libhidltransport", + "liblog", + "libpower", + "libutils", + ], +} + +cc_library { + name: "android.hardware.sensors@2.0-fakesubhal-config1", + defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"], + cflags: [ + "-DSUPPORT_CONTINUOUS_SENSORS", + "-DSUB_HAL_NAME=\"FakeSubHal-Continuous\"", + ], +} + +cc_library { + name: "android.hardware.sensors@2.0-fakesubhal-config2", + defaults: ["android.hardware.sensors@2.0-fakesubhal-defaults"], + cflags: [ + "-DSUPPORT_ON_CHANGE_SENSORS", + "-DSUB_HAL_NAME=\"FakeSubHal-OnChange\"", + ], +} \ No newline at end of file diff --git a/sensors/2.0/multihal/testing/README b/sensors/2.0/multihal/testing/README new file mode 100644 index 0000000000..ddcc58452f --- /dev/null +++ b/sensors/2.0/multihal/testing/README @@ -0,0 +1,19 @@ +This directory contains a modified version of the default implementation +provided for sensors HAL 2.0 to support multi-HAL 2.0. It should be used as a +means to verify the multi-HAL 2.0 implementation can successfully load and +interact with sub-HALs. + +This sub-HAL implementation has two macros that can be used to configure support +for different sets of sensors. One "SUPPORT_CONTINUOUS_SENSORS", enables +support for continuous sensors like accel, and gyro whereas the other +"SUPPORT_ON_CHANGE_SENSORS" enables support for on change sensors like the +light and proximity sensor. A build target is defined for each of these macros, +but more targets could be added to support both in one sub-HAL or none at all, +if necessary. + +When built, the library will be written to +out/target/product//vendor/lib64/android.hardware.sensors@2.0-fakesubhal.so + +Take this .so and place it where the multi-HAL config will cause the HalProxy to +look and then restart the system server with adb shell stop / adb shell start +to cause the multi-HAL to restart and attempt to load in the sub-HAL. diff --git a/sensors/2.0/multihal/testing/Sensor.cpp b/sensors/2.0/multihal/testing/Sensor.cpp new file mode 100644 index 0000000000..e095efe0cf --- /dev/null +++ b/sensors/2.0/multihal/testing/Sensor.cpp @@ -0,0 +1,372 @@ +/* + * 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 "Sensor.h" + +#include + +#include + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_0 { +namespace subhal { +namespace implementation { + +using ::android::hardware::sensors::V1_0::MetaDataEventType; +using ::android::hardware::sensors::V1_0::SensorFlagBits; +using ::android::hardware::sensors::V1_0::SensorStatus; + +static constexpr float kDefaultMaxDelayUs = 10 * 1000 * 1000; + +Sensor::Sensor(ISensorsEventCallback* callback) + : mIsEnabled(false), + mSamplingPeriodNs(0), + mLastSampleTimeNs(0), + mCallback(callback), + mMode(OperationMode::NORMAL) { + mRunThread = std::thread(startThread, this); +} + +Sensor::~Sensor() { + std::unique_lock lock(mRunMutex); + mStopThread = true; + mIsEnabled = false; + mWaitCV.notify_all(); + lock.release(); + mRunThread.join(); +} + +const SensorInfo& Sensor::getSensorInfo() const { + return mSensorInfo; +} + +void Sensor::batch(int32_t samplingPeriodNs) { + samplingPeriodNs = + std::clamp(samplingPeriodNs, mSensorInfo.minDelay * 1000, mSensorInfo.maxDelay * 1000); + + if (mSamplingPeriodNs != samplingPeriodNs) { + mSamplingPeriodNs = samplingPeriodNs; + // Wake up the 'run' thread to check if a new event should be generated now + mWaitCV.notify_all(); + } +} + +void Sensor::activate(bool enable) { + if (mIsEnabled != enable) { + std::unique_lock lock(mRunMutex); + mIsEnabled = enable; + mWaitCV.notify_all(); + } +} + +Result Sensor::flush() { + // Only generate a flush complete event if the sensor is enabled and if the sensor is not a + // one-shot sensor. + if (!mIsEnabled || (mSensorInfo.flags & static_cast(SensorFlagBits::ONE_SHOT_MODE))) { + return Result::BAD_VALUE; + } + + // Note: If a sensor supports batching, write all of the currently batched events for the sensor + // to the Event FMQ prior to writing the flush complete event. + Event ev; + ev.sensorHandle = mSensorInfo.sensorHandle; + ev.sensorType = SensorType::META_DATA; + ev.u.meta.what = MetaDataEventType::META_DATA_FLUSH_COMPLETE; + std::vector evs{ev}; + mCallback->postEvents(evs, isWakeUpSensor()); + + return Result::OK; +} + +void Sensor::startThread(Sensor* sensor) { + sensor->run(); +} + +void Sensor::run() { + std::unique_lock runLock(mRunMutex); + constexpr int64_t kNanosecondsInSeconds = 1000 * 1000 * 1000; + + while (!mStopThread) { + if (!mIsEnabled || mMode == OperationMode::DATA_INJECTION) { + mWaitCV.wait(runLock, [&] { + return ((mIsEnabled && mMode == OperationMode::NORMAL) || mStopThread); + }); + } else { + timespec curTime; + clock_gettime(CLOCK_REALTIME, &curTime); + int64_t now = (curTime.tv_sec * kNanosecondsInSeconds) + curTime.tv_nsec; + int64_t nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; + + if (now >= nextSampleTime) { + mLastSampleTimeNs = now; + nextSampleTime = mLastSampleTimeNs + mSamplingPeriodNs; + mCallback->postEvents(readEvents(), isWakeUpSensor()); + } + + mWaitCV.wait_for(runLock, std::chrono::nanoseconds(nextSampleTime - now)); + } + } +} + +bool Sensor::isWakeUpSensor() { + return mSensorInfo.flags & static_cast(SensorFlagBits::WAKE_UP); +} + +std::vector Sensor::readEvents() { + std::vector events; + Event event; + event.sensorHandle = mSensorInfo.sensorHandle; + event.sensorType = mSensorInfo.type; + event.timestamp = ::android::elapsedRealtimeNano(); + event.u.vec3.x = 0; + event.u.vec3.y = 0; + event.u.vec3.z = 0; + event.u.vec3.status = SensorStatus::ACCURACY_HIGH; + events.push_back(event); + return events; +} + +void Sensor::setOperationMode(OperationMode mode) { + if (mMode != mode) { + std::unique_lock lock(mRunMutex); + mMode = mode; + mWaitCV.notify_all(); + } +} + +bool Sensor::supportsDataInjection() const { + return mSensorInfo.flags & static_cast(SensorFlagBits::DATA_INJECTION); +} + +Result Sensor::injectEvent(const Event& event) { + Result result = Result::OK; + if (event.sensorType == SensorType::ADDITIONAL_INFO) { + // When in OperationMode::NORMAL, SensorType::ADDITIONAL_INFO is used to push operation + // environment data into the device. + } else if (!supportsDataInjection()) { + result = Result::INVALID_OPERATION; + } else if (mMode == OperationMode::DATA_INJECTION) { + mCallback->postEvents(std::vector{event}, isWakeUpSensor()); + } else { + result = Result::BAD_VALUE; + } + return result; +} + +OnChangeSensor::OnChangeSensor(ISensorsEventCallback* callback) + : Sensor(callback), mPreviousEventSet(false) {} + +void OnChangeSensor::activate(bool enable) { + Sensor::activate(enable); + if (!enable) { + mPreviousEventSet = false; + } +} + +std::vector OnChangeSensor::readEvents() { + std::vector events = Sensor::readEvents(); + std::vector outputEvents; + + for (auto iter = events.begin(); iter != events.end(); ++iter) { + Event ev = *iter; + if (ev.u.vec3 != mPreviousEvent.u.vec3 || !mPreviousEventSet) { + outputEvents.push_back(ev); + mPreviousEvent = ev; + mPreviousEventSet = true; + } + } + return outputEvents; +} + +AccelSensor::AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Accel Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::ACCELEROMETER; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 78.4f; // +/- 8g + mSensorInfo.resolution = 1.52e-5; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 20 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::DATA_INJECTION); +}; + +PressureSensor::PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Pressure Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PRESSURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1100.0f; // hPa + mSensorInfo.resolution = 0.005f; // hPa + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 100 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +MagnetometerSensor::MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Magnetic Field Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::MAGNETIC_FIELD; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1300.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 20 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +LightSensor::LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Light Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::LIGHT; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 43000.0f; + mSensorInfo.resolution = 10.0f; + mSensorInfo.power = 0.001f; // mA + mSensorInfo.minDelay = 200 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +}; + +ProximitySensor::ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Proximity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::PROXIMITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 5.0f; + mSensorInfo.resolution = 1.0f; + mSensorInfo.power = 0.012f; // mA + mSensorInfo.minDelay = 200 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = + static_cast(SensorFlagBits::ON_CHANGE_MODE | SensorFlagBits::WAKE_UP); +}; + +GyroSensor::GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback) : Sensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Gyro Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::GYROSCOPE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 1000.0f * M_PI / 180.0f; + mSensorInfo.resolution = 1000.0f * M_PI / (180.0f * 32768.0f); + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 2.5f * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = 0; +}; + +AmbientTempSensor::AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Ambient Temp Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::AMBIENT_TEMPERATURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 80.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 40 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +}; + +DeviceTempSensor::DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Device Temp Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::TEMPERATURE; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 80.0f; + mSensorInfo.resolution = 0.01f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 40 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +} + +RelativeHumiditySensor::RelativeHumiditySensor(int32_t sensorHandle, + ISensorsEventCallback* callback) + : OnChangeSensor(callback) { + mSensorInfo.sensorHandle = sensorHandle; + mSensorInfo.name = "Relative Humidity Sensor"; + mSensorInfo.vendor = "Vendor String"; + mSensorInfo.version = 1; + mSensorInfo.type = SensorType::RELATIVE_HUMIDITY; + mSensorInfo.typeAsString = ""; + mSensorInfo.maxRange = 100.0f; + mSensorInfo.resolution = 0.1f; + mSensorInfo.power = 0.001f; + mSensorInfo.minDelay = 40 * 1000; // microseconds + mSensorInfo.maxDelay = kDefaultMaxDelayUs; + mSensorInfo.fifoReservedEventCount = 0; + mSensorInfo.fifoMaxEventCount = 0; + mSensorInfo.requiredPermission = ""; + mSensorInfo.flags = static_cast(SensorFlagBits::ON_CHANGE_MODE); +} + +} // namespace implementation +} // namespace subhal +} // namespace V2_0 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/2.0/multihal/testing/Sensor.h b/sensors/2.0/multihal/testing/Sensor.h new file mode 100644 index 0000000000..980ea54559 --- /dev/null +++ b/sensors/2.0/multihal/testing/Sensor.h @@ -0,0 +1,146 @@ +/* + * 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. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + +using ::android::hardware::sensors::V1_0::Event; +using ::android::hardware::sensors::V1_0::OperationMode; +using ::android::hardware::sensors::V1_0::Result; +using ::android::hardware::sensors::V1_0::SensorInfo; +using ::android::hardware::sensors::V1_0::SensorType; + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_0 { +namespace subhal { +namespace implementation { + +class ISensorsEventCallback { + public: + virtual ~ISensorsEventCallback(){}; + virtual void postEvents(const std::vector& events, bool wakeup) = 0; +}; + +class Sensor { + public: + Sensor(ISensorsEventCallback* callback); + virtual ~Sensor(); + + const SensorInfo& getSensorInfo() const; + void batch(int32_t samplingPeriodNs); + virtual void activate(bool enable); + Result flush(); + + void setOperationMode(OperationMode mode); + bool supportsDataInjection() const; + Result injectEvent(const Event& event); + + protected: + void run(); + virtual std::vector readEvents(); + static void startThread(Sensor* sensor); + + bool isWakeUpSensor(); + + bool mIsEnabled; + int64_t mSamplingPeriodNs; + int64_t mLastSampleTimeNs; + SensorInfo mSensorInfo; + + std::atomic_bool mStopThread; + std::condition_variable mWaitCV; + std::mutex mRunMutex; + std::thread mRunThread; + + ISensorsEventCallback* mCallback; + + OperationMode mMode; +}; + +class OnChangeSensor : public Sensor { + public: + OnChangeSensor(ISensorsEventCallback* callback); + + virtual void activate(bool enable) override; + + protected: + virtual std::vector readEvents() override; + + protected: + Event mPreviousEvent; + bool mPreviousEventSet; +}; + +class AccelSensor : public Sensor { + public: + AccelSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class GyroSensor : public Sensor { + public: + GyroSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class AmbientTempSensor : public OnChangeSensor { + public: + AmbientTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class DeviceTempSensor : public OnChangeSensor { + public: + DeviceTempSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class PressureSensor : public Sensor { + public: + PressureSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class MagnetometerSensor : public Sensor { + public: + MagnetometerSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class LightSensor : public OnChangeSensor { + public: + LightSensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class ProximitySensor : public OnChangeSensor { + public: + ProximitySensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +class RelativeHumiditySensor : public OnChangeSensor { + public: + RelativeHumiditySensor(int32_t sensorHandle, ISensorsEventCallback* callback); +}; + +} // namespace implementation +} // namespace subhal +} // namespace V2_0 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/2.0/multihal/testing/SensorsSubHal.cpp b/sensors/2.0/multihal/testing/SensorsSubHal.cpp new file mode 100644 index 0000000000..8d459824dc --- /dev/null +++ b/sensors/2.0/multihal/testing/SensorsSubHal.cpp @@ -0,0 +1,179 @@ +/* + * 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 "SensorsSubHal.h" + +#include +#include + +ISensorsSubHal* sensorsHalGetSubHal(uint32_t* version) { + static ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal subHal; + *version = SUB_HAL_2_0_VERSION; + return &subHal; +} + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_0 { +namespace subhal { +namespace implementation { + +using ::android::hardware::Void; +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; +using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock; + +SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) { +#ifdef SUPPORT_CONTINUOUS_SENSORS + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); +#endif // SUPPORT_CONTINUOUS_SENSORS + +#ifdef SUPPORT_ON_CHANGE_SENSORS + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); + AddSensor(); +#endif // SUPPORT_ON_CHANGE_SENSORS +} + +// Methods from ::android::hardware::sensors::V2_0::ISensors follow. +Return SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) { + std::vector sensors; + for (const auto& sensor : mSensors) { + sensors.push_back(sensor.second->getSensorInfo()); + } + + _hidl_cb(sensors); + return Void(); +} + +Return SensorsSubHal::setOperationMode(OperationMode mode) { + for (auto sensor : mSensors) { + sensor.second->setOperationMode(mode); + } + return Result::OK; +} + +Return SensorsSubHal::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 SensorsSubHal::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 SensorsSubHal::flush(int32_t sensorHandle) { + auto sensor = mSensors.find(sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->flush(); + } + return Result::BAD_VALUE; +} + +Return SensorsSubHal::injectSensorData(const Event& event) { + auto sensor = mSensors.find(event.sensorHandle); + if (sensor != mSensors.end()) { + return sensor->second->injectEvent(event); + } + + return Result::BAD_VALUE; +} + +Return SensorsSubHal::registerDirectChannel(const SharedMemInfo& /* mem */, + registerDirectChannel_cb _hidl_cb) { + _hidl_cb(Result::INVALID_OPERATION, -1 /* channelHandle */); + return Return(); +} + +Return SensorsSubHal::unregisterDirectChannel(int32_t /* channelHandle */) { + return Result::INVALID_OPERATION; +} + +Return SensorsSubHal::configDirectReport(int32_t /* sensorHandle */, + int32_t /* channelHandle */, RateLevel /* rate */, + configDirectReport_cb _hidl_cb) { + _hidl_cb(Result::INVALID_OPERATION, 0 /* reportToken */); + return Return(); +} + +Return SensorsSubHal::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(); + } + + FILE* out = fdopen(dup(fd->data[0]), "w"); + + if (args.size() != 0) { + fprintf(out, + "Note: sub-HAL %s currently does not support args. Input arguments are " + "ignored.\n", + getName().c_str()); + } + + std::ostringstream stream; + stream << "Available sensors:" << std::endl; + for (auto sensor : mSensors) { + SensorInfo info = sensor.second->getSensorInfo(); + stream << "Name: " << info.name << std::endl; + stream << "Min delay: " << info.minDelay << std::endl; + stream << "Flags: " << info.flags << std::endl; + } + stream << std::endl; + + fprintf(out, "%s", stream.str().c_str()); + + fclose(out); + return Return(); +} + +Return SensorsSubHal::initialize(const sp& halProxyCallback) { + mCallback = halProxyCallback; + return Result::OK; +} + +void SensorsSubHal::postEvents(const std::vector& events, bool wakeup) { + ScopedWakelock wakelock = mCallback->createScopedWakelock(wakeup); + mCallback->postEvents(events, std::move(wakelock)); +} + +} // namespace implementation +} // namespace subhal +} // namespace V2_0 +} // namespace sensors +} // namespace hardware +} // namespace android diff --git a/sensors/2.0/multihal/testing/SensorsSubHal.h b/sensors/2.0/multihal/testing/SensorsSubHal.h new file mode 100644 index 0000000000..93009d5833 --- /dev/null +++ b/sensors/2.0/multihal/testing/SensorsSubHal.h @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#pragma once + +#include "SubHal.h" + +#include "Sensor.h" + +namespace android { +namespace hardware { +namespace sensors { +namespace V2_0 { +namespace subhal { +namespace implementation { + +using ::android::hardware::sensors::V2_0::implementation::IHalProxyCallback; + +/** + * Implementation of a ISensorsSubHal that can be used to test the implementation of multihal 2.0. + * See the README file for more details on how this class can be used for testing. + */ +class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback { + using Event = ::android::hardware::sensors::V1_0::Event; + using OperationMode = ::android::hardware::sensors::V1_0::OperationMode; + using RateLevel = ::android::hardware::sensors::V1_0::RateLevel; + using Result = ::android::hardware::sensors::V1_0::Result; + using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo; + + public: + SensorsSubHal(); + + // Methods from ::android::hardware::sensors::V2_0::ISensors follow. + Return getSensorsList(getSensorsList_cb _hidl_cb) override; + + Return setOperationMode(OperationMode mode) override; + + Return activate(int32_t sensorHandle, bool enabled) override; + + Return batch(int32_t sensorHandle, int64_t samplingPeriodNs, + int64_t maxReportLatencyNs) override; + + Return flush(int32_t sensorHandle) override; + + Return injectSensorData(const Event& event) override; + + Return registerDirectChannel(const SharedMemInfo& mem, + registerDirectChannel_cb _hidl_cb) override; + + Return unregisterDirectChannel(int32_t channelHandle) override; + + Return configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate, + configDirectReport_cb _hidl_cb) override; + + Return debug(const hidl_handle& fd, const hidl_vec& args) override; + + // Methods from ::android::hardware::sensors::V2_0::implementation::ISensorsSubHal follow. + const std::string getName() override { +#ifdef SUB_HAL_NAME + return SUB_HAL_NAME; +#else // SUB_HAL_NAME + return "FakeSubHal"; +#endif // SUB_HAL_NAME + } + + Return initialize(const sp& halProxyCallback) override; + + // Method from ISensorsEventCallback. + void postEvents(const std::vector& events, bool wakeup) override; + + private: + template + void AddSensor() { + std::shared_ptr sensor = + std::make_shared(mNextHandle++ /* sensorHandle */, this /* callback */); + mSensors[sensor->getSensorInfo().sensorHandle] = sensor; + } + + /** + * Callback used to communicate to the HalProxy when dynamic sensors are connected / + * disconnected, sensor events need to be sent to the framework, and when a wakelock should be + * acquired. + */ + sp mCallback; + + /** + * A map of the available sensors + */ + std::map> mSensors; + + /** + * The next available sensor handle + */ + int32_t mNextHandle; +}; + +} // namespace implementation +} // namespace subhal +} // namespace V2_0 +} // namespace sensors +} // namespace hardware +} // namespace android