diff options
author | Xin Li <delphij@google.com> | 2022-02-14 17:30:14 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2022-02-14 17:30:14 +0000 |
commit | d2adcd79f8e0167226a0fc1f695f233363109292 (patch) | |
tree | acbc5c6aa04030acde873127bd06b53860e291d0 | |
parent | 466b596cc5d79f47357ec0d3d07389cdf4fc92bc (diff) | |
parent | f911d3a70d10886afe4e16a9c4f66e7b7afcfe5d (diff) | |
download | libhardware-d2adcd79f8e0167226a0fc1f695f233363109292.tar.gz |
Merge "Merge sc-v2-dev-plus-aosp-without-vendor@8084891" into stage-aosp-mastersam_222710654
21 files changed, 756 insertions, 103 deletions
diff --git a/modules/gralloc/Android.mk b/modules/gralloc/Android.mk index 439c95dd..4c4899ea 100644 --- a/modules/gralloc/Android.mk +++ b/modules/gralloc/Android.mk @@ -38,5 +38,8 @@ LOCAL_CFLAGS:= -DLOG_TAG=\"gralloc\" -Wno-missing-field-initializers ifeq ($(TARGET_USE_PAN_DISPLAY),true) LOCAL_CFLAGS += -DUSE_PAN_DISPLAY=1 endif +ifneq ($(GRALLOC_FRAMEBUFFER_NUM),) +LOCAL_CFLAGS += -DNUM_BUFFERS=$(GRALLOC_FRAMEBUFFER_NUM) +endif include $(BUILD_SHARED_LIBRARY) diff --git a/modules/gralloc/framebuffer.cpp b/modules/gralloc/framebuffer.cpp index b2ec3e44..fc220dbc 100644 --- a/modules/gralloc/framebuffer.cpp +++ b/modules/gralloc/framebuffer.cpp @@ -45,8 +45,10 @@ #define USE_PAN_DISPLAY 0 #endif -// numbers of buffers for page flipping +// Enabling page flipping by default +#ifndef NUM_BUFFERS #define NUM_BUFFERS 2 +#endif enum { @@ -157,7 +159,8 @@ int mapFrameBufferLocked(struct private_module_t* module, int format) info.activate = FB_ACTIVATE_NOW; /* - * Request NUM_BUFFERS screens (at lest 2 for page flipping) + * Request NUM_BUFFERS screens + * To enable page flipping, NUM_BUFFERS should be at least 2. */ info.yres_virtual = info.yres * NUM_BUFFERS; diff --git a/modules/sensors/dynamic_sensor/Android.bp b/modules/sensors/dynamic_sensor/Android.bp index 1ebc04d2..bad60481 100644 --- a/modules/sensors/dynamic_sensor/Android.bp +++ b/modules/sensors/dynamic_sensor/Android.bp @@ -108,7 +108,23 @@ cc_library_shared { cflags: ["-DLOG_TAG=\"DynamicSensorHal\""], - srcs: ["sensors.cpp"], + srcs: [ + "DynamicSensorsSubHal.cpp", + "sensors.cpp", + ], + shared_libs: [ + "android.hardware.sensors@2.0", + "android.hardware.sensors@2.0-ScopedWakelock", + "android.hardware.sensors@2.1", + "libhidlbase", + ], + static_libs: [ + "android.hardware.sensors@1.0-convert", + ], + header_libs: [ + "android.hardware.sensors@2.X-multihal.header", + "android.hardware.sensors@2.X-shared-utils", + ], } // diff --git a/modules/sensors/dynamic_sensor/BaseSensorObject.cpp b/modules/sensors/dynamic_sensor/BaseSensorObject.cpp index 4ec76b27..69fc7d86 100644 --- a/modules/sensors/dynamic_sensor/BaseSensorObject.cpp +++ b/modules/sensors/dynamic_sensor/BaseSensorObject.cpp @@ -42,6 +42,7 @@ void BaseSensorObject::getUuid(uint8_t* uuid) const { int BaseSensorObject::flush() { static const sensors_event_t event = { .type = SENSOR_TYPE_META_DATA, + .meta_data.what = META_DATA_FLUSH_COMPLETE, .timestamp = TIMESTAMP_AUTO_FILL // timestamp will be filled at dispatcher }; generateEvent(event); diff --git a/modules/sensors/dynamic_sensor/ConnectionDetector.cpp b/modules/sensors/dynamic_sensor/ConnectionDetector.cpp index c51e9125..c009a707 100644 --- a/modules/sensors/dynamic_sensor/ConnectionDetector.cpp +++ b/modules/sensors/dynamic_sensor/ConnectionDetector.cpp @@ -57,8 +57,6 @@ SocketConnectionDetector::SocketConnectionDetector(BaseDynamicSensorDaemon *d, i std::ostringstream s; s << "socket:" << port; mDevice = s.str(); - - run("ddad_socket"); } SocketConnectionDetector::~SocketConnectionDetector() { @@ -67,6 +65,12 @@ SocketConnectionDetector::~SocketConnectionDetector() { } } +void SocketConnectionDetector::Init() { + // run adds a strong reference to this object, so it can't be invoked from + // the constructor. + run("ddad_socket"); +} + int SocketConnectionDetector::waitForConnection() { return ::accept(mListenFd, nullptr, nullptr); } @@ -124,9 +128,6 @@ FileConnectionDetector::FileConnectionDetector ( ALOGE("Cannot setup watch on dir %s", path.c_str()); return; } - - // mLooper != null && mInotifyFd added to looper - run("ddad_file"); } FileConnectionDetector::~FileConnectionDetector() { @@ -138,6 +139,13 @@ FileConnectionDetector::~FileConnectionDetector() { } } +void FileConnectionDetector::Init() { + // mLooper != null && mInotifyFd added to looper + // run adds a strong reference to this object, so it can't be invoked from + // the constructor. + run("ddad_file"); +} + bool FileConnectionDetector::matches(const std::string &name) const { return std::regex_match(name, mRegex); } diff --git a/modules/sensors/dynamic_sensor/ConnectionDetector.h b/modules/sensors/dynamic_sensor/ConnectionDetector.h index 0ee1df29..75fbb0bc 100644 --- a/modules/sensors/dynamic_sensor/ConnectionDetector.h +++ b/modules/sensors/dynamic_sensor/ConnectionDetector.h @@ -34,6 +34,7 @@ class ConnectionDetector : virtual public RefBase { public: ConnectionDetector(BaseDynamicSensorDaemon *d) : mDaemon(d) { } virtual ~ConnectionDetector() = default; + virtual void Init() {} protected: BaseDynamicSensorDaemon* mDaemon; }; @@ -45,6 +46,7 @@ class SocketConnectionDetector : public ConnectionDetector, public Thread { public: SocketConnectionDetector(BaseDynamicSensorDaemon *d, int port); virtual ~SocketConnectionDetector(); + void Init() override; private: // implement virtual of Thread virtual bool threadLoop(); @@ -62,6 +64,7 @@ public: FileConnectionDetector( BaseDynamicSensorDaemon *d, const std::string &path, const std::string ®ex); virtual ~FileConnectionDetector(); + void Init() override; private: static constexpr int POLL_IDENT = 1; // implement virtual of Thread diff --git a/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp index a1a47e81..10771e32 100644 --- a/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp +++ b/modules/sensors/dynamic_sensor/DummyDynamicAccelDaemon.cpp @@ -28,7 +28,7 @@ #include <netinet/in.h> #include <algorithm> //std::max -#define SYSPROP_PREFIX "dynamic_sensor.dummy" +#define SYSPROP_PREFIX "vendor.dynamic_sensor.mock" #define FILE_NAME_BASE "dummy_accel_file" #define FILE_NAME_REGEX ("^" FILE_NAME_BASE "[0-9]$") @@ -43,11 +43,13 @@ DummyDynamicAccelDaemon::DummyDynamicAccelDaemon(DynamicSensorManager& manager) if (strcmp(property, "") != 0) { mFileDetector = new FileConnectionDetector( this, std::string(property), std::string(FILE_NAME_REGEX)); + mFileDetector->Init(); } property_get(SYSPROP_PREFIX ".socket", property, ""); if (strcmp(property, "") != 0) { mSocketDetector = new SocketConnectionDetector(this, atoi(property)); + mSocketDetector->Init(); } } diff --git a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp index 37b43132..be1a0044 100644 --- a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp +++ b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp @@ -76,7 +76,7 @@ bool DynamicSensorManager::owns(int handle) const { int DynamicSensorManager::activate(int handle, bool enable) { if (handle == mHandleRange.first) { - // ignored + mMetaSensorActive = enable; return 0; } @@ -109,13 +109,17 @@ int DynamicSensorManager::setDelay(int handle, nsecs_t sample_period) { int DynamicSensorManager::flush(int handle) { if (handle == mHandleRange.first) { - // submit a flush complete here - static const sensors_event_t event = { - .sensor = mHandleRange.first, - .type = SENSOR_TYPE_META_DATA, - .timestamp = TIMESTAMP_AUTO_FILL, // timestamp will be filled at dispatcher - }; - submitEvent(nullptr, event); + if (mMetaSensorActive) { + static const sensors_event_t event = { + .sensor = mHandleRange.first, + .type = SENSOR_TYPE_META_DATA, + .meta_data.what = META_DATA_FLUSH_COMPLETE, + .timestamp = TIMESTAMP_AUTO_FILL, // timestamp will be filled at dispatcher + }; + submitEvent(nullptr, event); + } else { + return -EINVAL; + } return 0; } return operateSensor(handle, [] (sp<BaseSensorObject> s)->int {return s->flush();}); diff --git a/modules/sensors/dynamic_sensor/DynamicSensorManager.h b/modules/sensors/dynamic_sensor/DynamicSensorManager.h index b6f39da6..264582ec 100644 --- a/modules/sensors/dynamic_sensor/DynamicSensorManager.h +++ b/modules/sensors/dynamic_sensor/DynamicSensorManager.h @@ -95,15 +95,18 @@ private: // TF: int foo(sp<BaseSensorObject> obj); template <typename TF> int operateSensor(int handle, TF f) const { - std::lock_guard<std::mutex> lk(mLock); - const auto i = mMap.find(handle); - if (i == mMap.end()) { - return BAD_VALUE; - } - sp<BaseSensorObject> s = i->second.promote(); - if (s == nullptr) { - // sensor object is already gone - return BAD_VALUE; + sp<BaseSensorObject> s; + { + std::lock_guard<std::mutex> lk(mLock); + const auto i = mMap.find(handle); + if (i == mMap.end()) { + return BAD_VALUE; + } + s = i->second.promote(); + if (s == nullptr) { + // sensor object is already gone + return BAD_VALUE; + } } return f(s); } @@ -111,6 +114,7 @@ private: // available sensor handle space const std::pair<int, int> mHandleRange; sensor_t mMetaSensor; + bool mMetaSensorActive = false; // immutable pointer to event callback, used in extention mode. SensorEventCallback * const mCallback; diff --git a/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp b/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp new file mode 100644 index 00000000..d5a9b3c0 --- /dev/null +++ b/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2021 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 "BaseSensorObject.h" +#include "DynamicSensorsSubHal.h" + +#include <convertV2_1.h> +#include <hardware/sensors-base.h> +#include <log/log.h> + +#include <chrono> +#include <thread> + +using ::android::hardware::sensors::V1_0::Result; +using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock; +using ::android::hardware::sensors::V2_1::implementation::convertFromSensorEvent; +using ::android::hardware::sensors::V2_1::SensorInfo; +using ::android::hardware::sensors::V2_1::SensorType; +template<class T> using Return = ::android::hardware::Return<T>; +using ::android::hardware::Void; + +namespace android { +namespace SensorHalExt { + +static Result ResultFromStatus(status_t err) { + switch (err) { + case ::android::OK: + return Result::OK; + case ::android::PERMISSION_DENIED: + return Result::PERMISSION_DENIED; + case ::android::NO_MEMORY: + return Result::NO_MEMORY; + case ::android::BAD_VALUE: + return Result::BAD_VALUE; + default: + return Result::INVALID_OPERATION; + } +} + +DynamicSensorsSubHal::DynamicSensorsSubHal() { + // initialize dynamic sensor manager + mDynamicSensorManager.reset( + DynamicSensorManager::createInstance(kDynamicHandleBase, + kMaxDynamicHandleCount, + this /* callback */)); +} + +// ISensors. +Return<Result> DynamicSensorsSubHal::setOperationMode(OperationMode mode) { + return (mode == static_cast<OperationMode>(SENSOR_HAL_NORMAL_MODE) ? + Result::OK : Result::BAD_VALUE); +} + +Return<Result> DynamicSensorsSubHal::activate(int32_t sensor_handle, + bool enabled) { + int rc = mDynamicSensorManager->activate(sensor_handle, enabled); + return ResultFromStatus(rc); +} + +Return<Result> DynamicSensorsSubHal::batch( + int32_t sensor_handle, int64_t sampling_period_ns, + int64_t max_report_latency_ns) { + int rc = mDynamicSensorManager->batch(sensor_handle, sampling_period_ns, + max_report_latency_ns); + return ResultFromStatus(rc); +} + +Return<Result> DynamicSensorsSubHal::flush(int32_t sensor_handle) { + int rc = mDynamicSensorManager->flush(sensor_handle); + return ResultFromStatus(rc); +} + +Return<void> DynamicSensorsSubHal::registerDirectChannel( + const SharedMemInfo& mem __unused, + registerDirectChannel_cb callback __unused) { + ALOGE("DynamicSensorsSubHal::registerDirectChannel not supported."); + + return Void(); +} + +Return<Result> DynamicSensorsSubHal::unregisterDirectChannel( + int32_t channel_handle __unused) { + ALOGE("DynamicSensorsSubHal::unregisterDirectChannel not supported."); + + return Result::INVALID_OPERATION; +} + +Return<void> DynamicSensorsSubHal::configDirectReport( + int32_t sensor_handle __unused, int32_t channel_handle __unused, + RateLevel rate __unused, configDirectReport_cb callback __unused) { + ALOGE("DynamicSensorsSubHal::configDirectReport not supported."); + + return Void(); +} + +Return<void> DynamicSensorsSubHal::getSensorsList_2_1( + getSensorsList_2_1_cb callback) { + const sensor_t& sensor_info = mDynamicSensorManager->getDynamicMetaSensor(); + std::vector<SensorInfo> sensors; + + ALOGD("DynamicSensorsSubHal::getSensorsList_2_1 invoked."); + + // get the dynamic sensor info + sensors.resize(1); + sensors[0].sensorHandle = sensor_info.handle; + sensors[0].name = sensor_info.name; + sensors[0].vendor = sensor_info.vendor; + sensors[0].version = 1; + sensors[0].type = static_cast<SensorType>(sensor_info.type); + sensors[0].typeAsString = sensor_info.stringType; + sensors[0].maxRange = sensor_info.maxRange; + sensors[0].resolution = sensor_info.resolution; + sensors[0].power = sensor_info.power; + sensors[0].minDelay = sensor_info.minDelay; + sensors[0].fifoReservedEventCount = sensor_info.fifoReservedEventCount; + sensors[0].fifoMaxEventCount = sensor_info.fifoMaxEventCount; + sensors[0].requiredPermission = sensor_info.requiredPermission; + sensors[0].maxDelay = sensor_info.maxDelay; + sensors[0].flags = sensor_info.flags; + + callback(sensors); + + return Void(); +} + +Return<Result> DynamicSensorsSubHal::injectSensorData_2_1( + const Event& event __unused) { + ALOGE("DynamicSensorsSubHal::injectSensorData_2_1 not supported."); + + return Result::INVALID_OPERATION; +} + +Return<void> DynamicSensorsSubHal::debug( + const hidl_handle& handle __unused, + const hidl_vec<hidl_string>& args __unused) { + return Void(); +} + +// ISensorsSubHal. +Return<Result> DynamicSensorsSubHal::initialize( + const sp<IHalProxyCallback>& hal_proxy_callback) { + ALOGD("DynamicSensorsSubHal::initialize invoked."); + + mHalProxyCallback = hal_proxy_callback; + + return Result::OK; +} + +// SensorEventCallback. +int DynamicSensorsSubHal::submitEvent(SP(BaseSensorObject) sensor, + const sensors_event_t& e) { + std::vector<Event> events; + Event hal_event; + bool wakeup; + + if (e.type == SENSOR_TYPE_DYNAMIC_SENSOR_META) { + const dynamic_sensor_meta_event_t* sensor_meta; + + sensor_meta = static_cast<const dynamic_sensor_meta_event_t*>( + &(e.dynamic_sensor_meta)); + if (sensor_meta->connected != 0) { + // The sensor framework must be notified of the connected sensor + // through the callback before handling the sensor added event. If + // it isn't, it will assert when looking up the sensor handle when + // processing the sensor added event. + // + // TODO (b/201529167): Fix dynamic sensors addition / removal when + // converting to AIDL. + // The sensor framework runs in a separate process from the sensor + // HAL, and it processes events in a dedicated thread, so it's + // possible the event handling can be done before the callback is + // run. Thus, a delay is added after sending notification of the + // connected sensor. + onSensorConnected(sensor_meta->handle, sensor_meta->sensor); + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); + } + } + + convertFromSensorEvent(e, &hal_event); + events.push_back(hal_event); + if (sensor && sensor->getSensor()) { + wakeup = sensor->getSensor()->flags & SENSOR_FLAG_WAKE_UP; + } else { + wakeup = false; + } + ScopedWakelock wakelock = mHalProxyCallback->createScopedWakelock(wakeup); + mHalProxyCallback->postEvents(events, std::move(wakelock)); + + return 0; +} + +void DynamicSensorsSubHal::onSensorConnected( + int handle, const sensor_t* sensor_info) { + hidl_vec<SensorInfo> sensor_list; + + sensor_list.resize(1); + sensor_list[0].sensorHandle = handle; + sensor_list[0].name = sensor_info->name; + sensor_list[0].vendor = sensor_info->vendor; + sensor_list[0].version = 1; + sensor_list[0].type = static_cast<SensorType>(sensor_info->type); + sensor_list[0].typeAsString = sensor_info->stringType; + sensor_list[0].maxRange = sensor_info->maxRange; + sensor_list[0].resolution = sensor_info->resolution; + sensor_list[0].power = sensor_info->power; + sensor_list[0].minDelay = sensor_info->minDelay; + sensor_list[0].fifoReservedEventCount = sensor_info->fifoReservedEventCount; + sensor_list[0].fifoMaxEventCount = sensor_info->fifoMaxEventCount; + sensor_list[0].requiredPermission = sensor_info->requiredPermission; + sensor_list[0].maxDelay = sensor_info->maxDelay; + sensor_list[0].flags = sensor_info->flags; + + mHalProxyCallback->onDynamicSensorsConnected_2_1(sensor_list); +} + +} // namespace SensorHalExt +} // namespace android + +using ::android::hardware::sensors::V2_1::implementation::ISensorsSubHal; +ISensorsSubHal* sensorsHalGetSubHal_2_1(uint32_t* version) { + static android::SensorHalExt::DynamicSensorsSubHal subHal; + + *version = SUB_HAL_2_1_VERSION; + return &subHal; +} + diff --git a/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.h b/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.h new file mode 100644 index 00000000..e9a46d68 --- /dev/null +++ b/modules/sensors/dynamic_sensor/DynamicSensorsSubHal.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 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_SENSORHAL_EXT_DYNAMIC_SENSORS_SUB_HAL_H +#define ANDROID_SENSORHAL_EXT_DYNAMIC_SENSORS_SUB_HAL_H + +#include "DynamicSensorManager.h" + +#include <V2_1/SubHal.h> + +namespace android { +namespace SensorHalExt { + +class DynamicSensorsSubHal : + public SensorEventCallback, + public ::android::hardware::sensors::V2_1::implementation::ISensorsSubHal { + using Event = ::android::hardware::sensors::V2_1::Event; + using hidl_handle = ::android::hardware::hidl_handle; + using hidl_string = ::android::hardware::hidl_string; + template<class T> using hidl_vec = ::android::hardware::hidl_vec<T>; + using IHalProxyCallback = + ::android::hardware::sensors::V2_1::implementation::IHalProxyCallback; + using OperationMode = ::android::hardware::sensors::V1_0::OperationMode; + using RateLevel = ::android::hardware::sensors::V1_0::RateLevel; + using Result = ::android::hardware::sensors::V1_0::Result; + template<class T> using Return = ::android::hardware::Return<T>; + using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo; + +public: + DynamicSensorsSubHal(); + + // ISensors. + Return<Result> setOperationMode(OperationMode mode) override; + Return<Result> activate(int32_t sensor_handle, bool enabled) override; + Return<Result> batch(int32_t sensor_handle, int64_t sampling_period_ns, + int64_t max_report_latency_ns) override; + Return<Result> flush(int32_t sensor_handle) override; + Return<void> registerDirectChannel( + const SharedMemInfo& mem, + registerDirectChannel_cb callback) override; + Return<Result> unregisterDirectChannel(int32_t channel_handle) override; + Return<void> configDirectReport( + int32_t sensor_handle, int32_t channel_handle, RateLevel rate, + configDirectReport_cb callback) override; + Return<void> getSensorsList_2_1(getSensorsList_2_1_cb callback) override; + Return<Result> injectSensorData_2_1(const Event& event) override; + Return<void> debug( + const hidl_handle& handle, + const hidl_vec<hidl_string>& args) override; + + // ISensorsSubHal. + const std::string getName() override { return "Dynamic-SubHAL"; } + Return<Result> initialize( + const sp<IHalProxyCallback>& hal_proxy_callback) override; + + // SensorEventCallback. + int submitEvent(SP(BaseSensorObject) sensor, + const sensors_event_t& e) override; + +private: + static constexpr int32_t kDynamicHandleBase = 0; + static constexpr int32_t kDynamicHandleEnd = 0x1000000; + static constexpr int32_t kMaxDynamicHandleCount = kDynamicHandleEnd - + kDynamicHandleBase; + + void onSensorConnected(int handle, const sensor_t* sensor_info); + + std::unique_ptr<DynamicSensorManager> mDynamicSensorManager; + sp<IHalProxyCallback> mHalProxyCallback; +}; + +} // namespace SensorHalExt +} // namespace android + +#endif // ANDROID_SENSORHAL_EXT_DYNAMIC_SENSORS_SUB_HAL_H + diff --git a/modules/sensors/dynamic_sensor/HidRawSensor.cpp b/modules/sensors/dynamic_sensor/HidRawSensor.cpp index f3c8a27b..8aaf2d4f 100644 --- a/modules/sensors/dynamic_sensor/HidRawSensor.cpp +++ b/modules/sensors/dynamic_sensor/HidRawSensor.cpp @@ -19,6 +19,8 @@ #include <utils/Errors.h> #include "HidLog.h" +#include <HidUtils.h> + #include <algorithm> #include <cfloat> #include <codecvt> @@ -490,13 +492,8 @@ bool HidRawSensor::populateFeatureValueFromFeatureReport( } break; case SENSOR_DESCRIPTION: - if (!r.isByteAligned() || r.bitSize != 16 || r.count < 1 - || (r.bitOffset / 8 + r.count * 2) > buffer.size() ) { - // invalid description - break; - } if (decodeString(r, buffer, &str)) { - mFeatureInfo.isAndroidCustom = detectAndroidCustomSensor(str); + detectSensorFromDescription(str); } break; default: @@ -581,26 +578,34 @@ bool HidRawSensor::validateFeatureValueAndBuildSensor() { bool HidRawSensor::decodeString( const HidParser::ReportItem &report, const std::vector<uint8_t> &buffer, std::string *d) { - if (!report.isByteAligned() || report.bitSize != 16 || report.count < 1) { + if (!report.isByteAligned() || + (report.bitSize != 8 && report.bitSize != 16) || report.count < 1) { return false; } + size_t charSize = report.bitSize / 8; size_t offset = report.bitOffset / 8; - if (offset + report.count * 2 > buffer.size()) { + if (offset + report.count * charSize > buffer.size()) { return false; } - std::vector<uint16_t> data(report.count); - auto i = data.begin(); - auto j = buffer.begin() + offset; - for ( ; i != data.end(); ++i, j += sizeof(uint16_t)) { - // hid specified little endian - *i = *j + (*(j + 1) << 8); + if (charSize == 1) { + *d = std::string(buffer.begin() + offset, + buffer.begin() + offset + report.count); + } else { + std::vector<uint16_t> data(report.count); + auto i = data.begin(); + auto j = buffer.begin() + offset; + for ( ; i != data.end(); ++i, j += sizeof(uint16_t)) { + // hid specified little endian + *i = *j + (*(j + 1) << 8); + } + std::wstring wstr(data.begin(), data.end()); + + std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter; + *d = converter.to_bytes(wstr); } - std::wstring wstr(data.begin(), data.end()); - std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter; - *d = converter.to_bytes(wstr); return true; } @@ -619,6 +624,28 @@ std::vector<std::string> split(const std::string &text, char sep) { return tokens; } +void HidRawSensor::detectSensorFromDescription(const std::string &description) { + if (detectAndroidHeadTrackerSensor(description) || + detectAndroidCustomSensor(description)) { + mFeatureInfo.isAndroidCustom = true; + } +} + +bool HidRawSensor::detectAndroidHeadTrackerSensor( + const std::string &description) { + if (description.find("#AndroidHeadTracker#1.") != 0) { + return false; + } + + mFeatureInfo.type = SENSOR_TYPE_DEVICE_PRIVATE_BASE; + mFeatureInfo.typeString = CUSTOM_TYPE_PREFIX + "headtracker"; + mFeatureInfo.reportModeFlag = SENSOR_FLAG_CONTINUOUS_MODE; + mFeatureInfo.permission = ""; + mFeatureInfo.isWakeUp = false; + + return true; +} + bool HidRawSensor::detectAndroidCustomSensor(const std::string &description) { size_t nullPosition = description.find('\0'); if (nullPosition == std::string::npos) { @@ -784,50 +811,83 @@ bool HidRawSensor::detectAndroidCustomSensor(const std::string &description) { } bool HidRawSensor::findSensorControlUsage(const std::vector<HidParser::ReportPacket> &packets) { + using namespace Hid::Sensor::PowerStateUsage; using namespace Hid::Sensor::PropertyUsage; - using namespace Hid::Sensor::RawMinMax; + using namespace Hid::Sensor::ReportingStateUsage; //REPORTING_STATE const HidParser::ReportItem *reportingState = find(packets, REPORTING_STATE, HidParser::REPORT_TYPE_FEATURE); - if (reportingState == nullptr - || !reportingState->isByteAligned() - || reportingState->bitSize != 8 - || reportingState->minRaw != REPORTING_STATE_MIN - || reportingState->maxRaw != REPORTING_STATE_MAX) { + if (reportingState == nullptr) { LOG_W << "Cannot find valid reporting state feature" << LOG_ENDL; } else { mReportingStateId = reportingState->id; - mReportingStateOffset = reportingState->bitOffset / 8; + mReportingStateBitOffset = reportingState->bitOffset; + mReportingStateBitSize = reportingState->bitSize; + + mReportingStateDisableIndex = -1; + mReportingStateEnableIndex = -1; + for (unsigned i = 0; i < reportingState->usageVector.size(); ++i) { + if (reportingState->usageVector[i] == REPORTING_STATE_NO_EVENTS) { + mReportingStateDisableIndex = i; + } + if (reportingState->usageVector[i] == REPORTING_STATE_ALL_EVENTS) { + mReportingStateEnableIndex = i; + } + } + if (mReportingStateDisableIndex < 0) { + LOG_W << "Cannot find reporting state to disable sensor" + << LOG_ENDL; + mReportingStateId = -1; + } + if (mReportingStateEnableIndex < 0) { + LOG_W << "Cannot find reporting state to enable sensor" << LOG_ENDL; + mReportingStateId = -1; + } } //POWER_STATE const HidParser::ReportItem *powerState = find(packets, POWER_STATE, HidParser::REPORT_TYPE_FEATURE); - if (powerState == nullptr - || !powerState->isByteAligned() - || powerState->bitSize != 8 - || powerState->minRaw != POWER_STATE_MIN - || powerState->maxRaw != POWER_STATE_MAX) { + if (powerState == nullptr) { LOG_W << "Cannot find valid power state feature" << LOG_ENDL; } else { mPowerStateId = powerState->id; - mPowerStateOffset = powerState->bitOffset / 8; + mPowerStateBitOffset = powerState->bitOffset; + mPowerStateBitSize = powerState->bitSize; + + mPowerStateOffIndex = -1; + mPowerStateOnIndex = -1; + for (unsigned i = 0; i < powerState->usageVector.size(); ++i) { + if (powerState->usageVector[i] == POWER_STATE_D4_POWER_OFF) { + mPowerStateOffIndex = i; + } + if (powerState->usageVector[i] == POWER_STATE_D0_FULL_POWER) { + mPowerStateOnIndex = i; + } + } + if (mPowerStateOffIndex < 0) { + LOG_W << "Cannot find power state to power off sensor" + << LOG_ENDL; + mPowerStateId = -1; + } + if (mPowerStateOnIndex < 0) { + LOG_W << "Cannot find power state to power on sensor" << LOG_ENDL; + mPowerStateId = -1; + } } //REPORT_INTERVAL const HidParser::ReportItem *reportInterval = find(packets, REPORT_INTERVAL, HidParser::REPORT_TYPE_FEATURE); if (reportInterval == nullptr - || !reportInterval->isByteAligned() - || reportInterval->minRaw < 0 - || (reportInterval->bitSize != 16 && reportInterval->bitSize != 32)) { + || reportInterval->minRaw < 0) { LOG_W << "Cannot find valid report interval feature" << LOG_ENDL; } else { mReportIntervalId = reportInterval->id; - mReportIntervalOffset = reportInterval->bitOffset / 8; - mReportIntervalSize = reportInterval->bitSize / 8; + mReportIntervalBitOffset = reportInterval->bitOffset; + mReportIntervalBitSize = reportInterval->bitSize; mFeatureInfo.minDelay = std::max(static_cast<int64_t>(1), reportInterval->minRaw) * 1000; mFeatureInfo.maxDelay = std::min(static_cast<int64_t>(1000000), @@ -846,7 +906,6 @@ void HidRawSensor::getUuid(uint8_t* uuid) const { } int HidRawSensor::enable(bool enable) { - using namespace Hid::Sensor::StateValue; SP(HidDevice) device = PROMOTE(mDevice); if (device == nullptr) { @@ -863,8 +922,11 @@ int HidRawSensor::enable(bool enable) { setPowerOk = false; uint8_t id = static_cast<uint8_t>(mPowerStateId); if (device->getFeature(id, &buffer) - && buffer.size() > mPowerStateOffset) { - buffer[mPowerStateOffset] = enable ? POWER_STATE_FULL_POWER : POWER_STATE_POWER_OFF; + && (8 * buffer.size()) >= + (mPowerStateBitOffset + mPowerStateBitSize)) { + uint8_t index = enable ? mPowerStateOnIndex : mPowerStateOffIndex; + HidUtil::copyBits(&index, &(buffer[0]), buffer.size(), + 0, mPowerStateBitOffset, mPowerStateBitSize); setPowerOk = device->setFeature(id, buffer); } else { LOG_E << "enable: changing POWER STATE failed" << LOG_ENDL; @@ -876,9 +938,12 @@ int HidRawSensor::enable(bool enable) { setReportingOk = false; uint8_t id = static_cast<uint8_t>(mReportingStateId); if (device->getFeature(id, &buffer) - && buffer.size() > mReportingStateOffset) { - buffer[mReportingStateOffset] - = enable ? REPORTING_STATE_ALL_EVENT : REPORTING_STATE_NO_EVENT; + && (8 * buffer.size()) > + (mReportingStateBitOffset + mReportingStateBitSize)) { + uint8_t index = enable ? mReportingStateEnableIndex : + mReportingStateDisableIndex; + HidUtil::copyBits(&index, &(buffer[0]), buffer.size(),0, + mReportingStateBitOffset, mReportingStateBitSize); setReportingOk = device->setFeature(id, buffer); } else { LOG_E << "enable: changing REPORTING STATE failed" << LOG_ENDL; @@ -911,22 +976,15 @@ int HidRawSensor::batch(int64_t samplingPeriod, int64_t batchingPeriod) { ok = false; uint8_t id = static_cast<uint8_t>(mReportIntervalId); if (device->getFeature(id, &buffer) - && buffer.size() >= mReportIntervalOffset + mReportIntervalSize) { + && (8 * buffer.size()) >= + (mReportIntervalBitOffset + mReportIntervalBitSize)) { int64_t periodMs = samplingPeriod / 1000000; //ns -> ms - switch (mReportIntervalSize) { - case sizeof(uint16_t): - periodMs = std::min(periodMs, static_cast<int64_t>(UINT16_MAX)); - buffer[mReportIntervalOffset] = periodMs & 0xFF; - buffer[mReportIntervalOffset + 1] = (periodMs >> 8) & 0xFF; - break; - case sizeof(uint32_t): - periodMs = std::min(periodMs, static_cast<int64_t>(UINT32_MAX)); - buffer[mReportIntervalOffset] = periodMs & 0xFF; - buffer[mReportIntervalOffset + 1] = (periodMs >> 8) & 0xFF; - buffer[mReportIntervalOffset + 2] = (periodMs >> 16) & 0xFF; - buffer[mReportIntervalOffset + 3] = (periodMs >> 24) & 0xFF; - break; - } + int64_t maxPeriodMs = + (1LL << std::min(mReportIntervalBitSize, 63U)) - 1; + periodMs = std::min(periodMs, maxPeriodMs); + HidUtil::copyBits(&periodMs, &(buffer[0]), buffer.size(), + 0, mReportIntervalBitOffset, + mReportIntervalBitSize); ok = device->setFeature(id, buffer); } } @@ -1019,7 +1077,11 @@ std::string HidRawSensor::dump() const { ss << " Power state "; if (mPowerStateId >= 0) { ss << "found, id: " << mPowerStateId - << " offset: " << mPowerStateOffset << LOG_ENDL; + << " bit offset: " << mPowerStateBitOffset + << " bit size: " << mPowerStateBitSize + << " power off index: " << mPowerStateOffIndex + << " power on index: " << mPowerStateOnIndex + << LOG_ENDL; } else { ss << "not found" << LOG_ENDL; } @@ -1027,7 +1089,11 @@ std::string HidRawSensor::dump() const { ss << " Reporting state "; if (mReportingStateId >= 0) { ss << "found, id: " << mReportingStateId - << " offset: " << mReportingStateOffset << LOG_ENDL; + << " bit offset: " << mReportingStateBitOffset + << " bit size: " << mReportingStateBitSize + << " disable index: " << mReportingStateDisableIndex + << " enable index: " << mReportingStateEnableIndex + << LOG_ENDL; } else { ss << "not found" << LOG_ENDL; } @@ -1035,8 +1101,8 @@ std::string HidRawSensor::dump() const { ss << " Report interval "; if (mReportIntervalId >= 0) { ss << "found, id: " << mReportIntervalId - << " offset: " << mReportIntervalOffset - << " size: " << mReportIntervalSize << LOG_ENDL; + << " bit offset: " << mReportIntervalBitOffset + << " bit size: " << mReportIntervalBitSize << LOG_ENDL; } else { ss << "not found" << LOG_ENDL; } diff --git a/modules/sensors/dynamic_sensor/HidRawSensor.h b/modules/sensors/dynamic_sensor/HidRawSensor.h index 2dd32b61..0989651f 100644 --- a/modules/sensors/dynamic_sensor/HidRawSensor.h +++ b/modules/sensors/dynamic_sensor/HidRawSensor.h @@ -121,6 +121,14 @@ private: // helper function to find sensor control feature usage from packets bool findSensorControlUsage(const std::vector<HidParser::ReportPacket> &packets); + // try to parse sensor description feature value to see if it matches any + // known sensors + void detectSensorFromDescription(const std::string &description); + + // try to parse sensor description feature value to see if it matches the + // Android header tracker sensor + bool detectAndroidHeadTrackerSensor(const std::string &description); + // try to parse sensor description feature value to see if it matches // android specified custom sensor definition. bool detectAndroidCustomSensor(const std::string &description); @@ -137,14 +145,20 @@ private: // Features for control sensor int mReportingStateId; - unsigned int mReportingStateOffset; + unsigned int mReportingStateBitOffset; + unsigned int mReportingStateBitSize; + int mReportingStateDisableIndex; + int mReportingStateEnableIndex; int mPowerStateId; - unsigned int mPowerStateOffset; + unsigned int mPowerStateBitOffset; + unsigned int mPowerStateBitSize; + int mPowerStateOffIndex; + int mPowerStateOnIndex; int mReportIntervalId; - unsigned int mReportIntervalOffset; - unsigned int mReportIntervalSize; + unsigned int mReportIntervalBitOffset; + unsigned int mReportIntervalBitSize; // Input report translate table std::vector<ReportTranslateRecord> mTranslateTable; diff --git a/modules/sensors/dynamic_sensor/HidRawSensorDaemon.cpp b/modules/sensors/dynamic_sensor/HidRawSensorDaemon.cpp index 6bf34bc8..4b447ac1 100644 --- a/modules/sensors/dynamic_sensor/HidRawSensorDaemon.cpp +++ b/modules/sensors/dynamic_sensor/HidRawSensorDaemon.cpp @@ -39,6 +39,7 @@ HidRawSensorDaemon::HidRawSensorDaemon(DynamicSensorManager& manager) : BaseDynamicSensorDaemon(manager) { mDetector = new FileConnectionDetector( this, std::string(DEV_PATH), std::string(DEV_NAME_REGEX)); + mDetector->Init(); } BaseSensorVector HidRawSensorDaemon::createSensor(const std::string &deviceKey) { diff --git a/modules/sensors/dynamic_sensor/HidSensorDef.h b/modules/sensors/dynamic_sensor/HidSensorDef.h index 2728b28a..8f47a850 100644 --- a/modules/sensors/dynamic_sensor/HidSensorDef.h +++ b/modules/sensors/dynamic_sensor/HidSensorDef.h @@ -77,24 +77,28 @@ enum { }; } // namespace ReportUsage -namespace RawMinMax { +namespace ReportingStateUsage { enum { - REPORTING_STATE_MIN = 0, - REPORTING_STATE_MAX = 5, - POWER_STATE_MIN = 0, - POWER_STATE_MAX = 5, + REPORTING_STATE_NO_EVENTS = 0x0840, + REPORTING_STATE_ALL_EVENTS = 0x0841, + REPORTING_STATE_REPORT_THRESHOLD_EVENTS = 0x0842, + REPORTING_STATE_REPORT_WAKE_ON_NO_EVENTS = 0x0843, + REPORTING_STATE_REPORT_WAKE_ON_ALL_EVENTS = 0x0844, + REPORTING_STATE_REPORT_WAKE_ON_THRESHOLD_EVENTS = 0x0845, }; -} // namespace RawMinMax +} // namespace ReportingStateUsage -namespace StateValue { +namespace PowerStateUsage { enum { - POWER_STATE_FULL_POWER = 1, - POWER_STATE_POWER_OFF = 5, - - REPORTING_STATE_ALL_EVENT = 1, - REPORTING_STATE_NO_EVENT = 0, + POWER_STATE_UNDEFINED = 0x0850, + POWER_STATE_D0_FULL_POWER = 0x0851, + POWER_STATE_D1_LOW_POWER = 0x0852, + POWER_STATE_D2_STANDBY_POWER_WITH_WAKEUP = 0x0853, + POWER_STATE_D3_SLEEP_WITH_WAKEUP = 0x0854, + POWER_STATE_D4_POWER_OFF = 0x0855, }; -} // StateValue +} // namespace PowerStateUsage + } // namespace Sensor } // namespace Hid #endif // HID_SENSOR_DEF_H_ diff --git a/modules/sensors/dynamic_sensor/HidUtils/Android.bp b/modules/sensors/dynamic_sensor/HidUtils/Android.bp index bbed0327..5823c794 100644 --- a/modules/sensors/dynamic_sensor/HidUtils/Android.bp +++ b/modules/sensors/dynamic_sensor/HidUtils/Android.bp @@ -45,6 +45,7 @@ cc_library { "HidParser.cpp", "HidReport.cpp", "HidTree.cpp", + "HidUtils.cpp", ], export_include_dirs: ["."], @@ -99,3 +100,20 @@ cc_test_host { local_include_dirs: ["test"], } + +// +// Test for HidUtils +// +cc_test_host { + name: "hid_utils_test", + defaults: ["hid_defaults"], + + srcs: ["test/CopyBitsTest.cpp"], + + shared_libs: [ + "libhidparser", + ], + + local_include_dirs: ["test"], +} + diff --git a/modules/sensors/dynamic_sensor/HidUtils/HidParser.cpp b/modules/sensors/dynamic_sensor/HidUtils/HidParser.cpp index 264f13c2..28d87d97 100644 --- a/modules/sensors/dynamic_sensor/HidUtils/HidParser.cpp +++ b/modules/sensors/dynamic_sensor/HidUtils/HidParser.cpp @@ -248,6 +248,7 @@ std::vector<HidParser::ReportPacket> HidParser::convertGroupToPacket( ReportItem digest = { .usage = r.getFullUsage(), .id = id, + .usageVector = r.getUsageVector(), .minRaw = logical.first, .maxRaw = logical.second, .a = scale, @@ -316,4 +317,5 @@ std::ostream& operator<<(std::ostream &os, const HidParser::DigestVector &digest os << LOG_ENDL; return os; } + } // namespace HidUtil diff --git a/modules/sensors/dynamic_sensor/HidUtils/HidParser.h b/modules/sensors/dynamic_sensor/HidUtils/HidParser.h index 4ef5ec6c..cb4a92a8 100644 --- a/modules/sensors/dynamic_sensor/HidUtils/HidParser.h +++ b/modules/sensors/dynamic_sensor/HidUtils/HidParser.h @@ -89,6 +89,7 @@ struct HidParser::ReportItem { unsigned int usage; unsigned int id; int type; // feature, input or output + std::vector<unsigned int> usageVector; int64_t minRaw; int64_t maxRaw; @@ -173,6 +174,7 @@ struct HidParser::ReportPacket { }; std::ostream& operator<<(std::ostream &os, const HidParser::DigestVector &digest2); + } // namespace HidUtil #endif // HIDUTIL_HIDPARSER_H_ diff --git a/modules/sensors/dynamic_sensor/HidUtils/HidUtils.cpp b/modules/sensors/dynamic_sensor/HidUtils/HidUtils.cpp new file mode 100644 index 00000000..0cce2a39 --- /dev/null +++ b/modules/sensors/dynamic_sensor/HidUtils/HidUtils.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2021 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 "HidUtils.h" +#include <stdint.h> +#include <algorithm> + +namespace HidUtil { + +void copyBits(const void *src, void *dst, size_t dst_size, + unsigned int src_bit_offset, unsigned int dst_bit_offset, + unsigned int bit_count) { + const uint8_t *p_src; + uint8_t *p_dst; + uint8_t dst_mask; + unsigned int bits_rem; + unsigned int bit_block_count; + + // Do nothing if copying past the end of the destination buffer. + if ((static_cast<size_t>(dst_bit_offset) > (8 * dst_size)) || + (static_cast<size_t>(bit_count) > (8 * dst_size)) || + (static_cast<size_t>(dst_bit_offset + bit_count) > (8 * dst_size))) { + return; + } + + // Copy bits from source to destination buffer. + p_src = static_cast<const uint8_t*>(src) + (src_bit_offset / 8); + src_bit_offset = src_bit_offset % 8; + p_dst = static_cast<uint8_t*>(dst) + (dst_bit_offset / 8); + dst_bit_offset = dst_bit_offset % 8; + bits_rem = bit_count; + while (bits_rem > 0) { + // Determine the size of the next block of bits to copy. The block must + // not cross a source or desintation byte boundary. + bit_block_count = std::min(bits_rem, 8 - src_bit_offset); + bit_block_count = std::min(bit_block_count, 8 - dst_bit_offset); + + // Determine the destination bit block mask. + dst_mask = ((1 << bit_block_count) - 1) << dst_bit_offset; + + // Copy the block of bits. + *p_dst = (*p_dst & ~dst_mask) | + (((*p_src >> src_bit_offset) << dst_bit_offset) & dst_mask); + + // Advance past the block of copied bits in the source. + src_bit_offset += bit_block_count; + p_src += src_bit_offset / 8; + src_bit_offset = src_bit_offset % 8; + + // Advance past the block of copied bits in the destination. + dst_bit_offset += bit_block_count; + p_dst += dst_bit_offset / 8; + dst_bit_offset = dst_bit_offset % 8; + + // Decrement the number of bits remaining. + bits_rem -= bit_block_count; + } +} + +} // namespace HidUtil diff --git a/modules/sensors/dynamic_sensor/HidUtils/HidUtils.h b/modules/sensors/dynamic_sensor/HidUtils/HidUtils.h new file mode 100644 index 00000000..54aa31e9 --- /dev/null +++ b/modules/sensors/dynamic_sensor/HidUtils/HidUtils.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 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 HIDUTIL_HIDUTILS_H_ +#define HIDUTIL_HIDUTILS_H_ + +#include <stddef.h> + +namespace HidUtil { + +void copyBits(const void *src, void *dst, size_t dst_size, + unsigned int src_bit_offset, unsigned int dst_bit_offset, + unsigned int bit_count); + +} // namespace HidUtil + +#endif // HIDUTIL_HIDUTILS_H_ diff --git a/modules/sensors/dynamic_sensor/HidUtils/test/CopyBitsTest.cpp b/modules/sensors/dynamic_sensor/HidUtils/test/CopyBitsTest.cpp new file mode 100644 index 00000000..1b1ca709 --- /dev/null +++ b/modules/sensors/dynamic_sensor/HidUtils/test/CopyBitsTest.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021 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 "HidUtils.h" +#include <gtest/gtest.h> + +using HidUtil::copyBits; + +TEST(CopyBitsTest, CopyBits) { + const struct { + uint32_t src; + uint32_t dst; + int src_bit_offset; + int dst_bit_offset; + int bit_count; + uint32_t expected_dst; + } kTestVectorList[] = { + { 0x00000005, 0x00000000, 0, 0, 8, 0x00000005 }, + { 0x00000005, 0x00000000, 0, 4, 8, 0x00000050 }, + { 0x0000000C, 0x00000020, 0, 4, 8, 0x000000C0 }, + { 0x00000005, 0x0000F02F, 0, 4, 8, 0x0000F05F }, + { 0x12345678, 0x87654321, 5, 11, 17, 0x8D159B21 }, + { 0x12345678, 0x87654321, 11, 5, 17, 0x8748D141 }, + }; + + for (auto test_vector : kTestVectorList) { + uint32_t dst = test_vector.dst; + copyBits(&(test_vector.src), &dst, sizeof(dst), + test_vector.src_bit_offset, test_vector.dst_bit_offset, + test_vector.bit_count); + EXPECT_EQ(test_vector.expected_dst, dst); + } +} + +TEST(CopyBitsTest, Overflow) { + const struct { + uint32_t src; + uint32_t dst; + unsigned int src_bit_offset; + unsigned int dst_bit_offset; + unsigned int bit_count; + uint32_t expected_dst; + } kTestVectorList[] = { + { 0x000000FF, 0x00000000, 0, 0, 8, 0x000000FF }, + { 0x000000FF, 0x00000000, 0, 24, 8, 0xFF000000 }, + { 0x000000FF, 0x00000000, 0, 25, 8, 0x00000000 }, + { 0x000000FF, 0x00000000, 0, 32, 8, 0x00000000 }, + { 0x000000FF, 0x00000000, 0, UINT_MAX, 8, 0x00000000 }, + { 0x000000FF, 0x00000000, 0, 8, UINT_MAX, 0x00000000 }, + }; + + for (auto test_vector : kTestVectorList) { + uint32_t dst = test_vector.dst; + copyBits(&(test_vector.src), &dst, sizeof(dst), + test_vector.src_bit_offset, test_vector.dst_bit_offset, + test_vector.bit_count); + EXPECT_EQ(test_vector.expected_dst, dst); + } +} + |