Merge "Merge Android 12L"
diff --git a/modules/gralloc/Android.mk b/modules/gralloc/Android.mk
index 439c95d..4c4899e 100644
--- a/modules/gralloc/Android.mk
+++ b/modules/gralloc/Android.mk
@@ -38,5 +38,8 @@
 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 b2ec3e4..fc220db 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 @@
     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 1ebc04d..bad6048 100644
--- a/modules/sensors/dynamic_sensor/Android.bp
+++ b/modules/sensors/dynamic_sensor/Android.bp
@@ -108,7 +108,23 @@
 
     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 4ec76b2..69fc7d8 100644
--- a/modules/sensors/dynamic_sensor/BaseSensorObject.cpp
+++ b/modules/sensors/dynamic_sensor/BaseSensorObject.cpp
@@ -42,6 +42,7 @@
 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 c51e912..c009a70 100644
--- a/modules/sensors/dynamic_sensor/ConnectionDetector.cpp
+++ b/modules/sensors/dynamic_sensor/ConnectionDetector.cpp
@@ -57,8 +57,6 @@
     std::ostringstream s;
     s << "socket:" << port;
     mDevice = s.str();
-
-    run("ddad_socket");
 }
 
 SocketConnectionDetector::~SocketConnectionDetector() {
@@ -67,6 +65,12 @@
     }
 }
 
+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 @@
         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 @@
     }
 }
 
+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 0ee1df2..75fbb0b 100644
--- a/modules/sensors/dynamic_sensor/ConnectionDetector.h
+++ b/modules/sensors/dynamic_sensor/ConnectionDetector.h
@@ -34,6 +34,7 @@
 public:
     ConnectionDetector(BaseDynamicSensorDaemon *d) : mDaemon(d) { }
     virtual ~ConnectionDetector() = default;
+    virtual void Init() {}
 protected:
     BaseDynamicSensorDaemon* mDaemon;
 };
@@ -45,6 +46,7 @@
 public:
     SocketConnectionDetector(BaseDynamicSensorDaemon *d, int port);
     virtual ~SocketConnectionDetector();
+    void Init() override;
 private:
     // implement virtual of Thread
     virtual bool threadLoop();
@@ -62,6 +64,7 @@
     FileConnectionDetector(
             BaseDynamicSensorDaemon *d, const std::string &path, const std::string &regex);
     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 a1a47e8..10771e3 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 @@
     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 37b4313..be1a004 100644
--- a/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp
+++ b/modules/sensors/dynamic_sensor/DynamicSensorManager.cpp
@@ -76,7 +76,7 @@
 
 int DynamicSensorManager::activate(int handle, bool enable) {
     if (handle == mHandleRange.first) {
-        // ignored
+        mMetaSensorActive = enable;
         return 0;
     }
 
@@ -109,13 +109,17 @@
 
 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 b6f39da..264582e 100644
--- a/modules/sensors/dynamic_sensor/DynamicSensorManager.h
+++ b/modules/sensors/dynamic_sensor/DynamicSensorManager.h
@@ -95,15 +95,18 @@
     // 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 @@
     // 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 0000000..d5a9b3c
--- /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 0000000..e9a46d6
--- /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 f3c8a27..8aaf2d4 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 @@
                     }
                     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::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);
-    }
-    std::wstring wstr(data.begin(), data.end());
+    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_convert<std::codecvt_utf8<wchar_t>, wchar_t> converter;
+        *d = converter.to_bytes(wstr);
+    }
+
     return true;
 }
 
@@ -619,6 +624,28 @@
     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::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 @@
 }
 
 int HidRawSensor::enable(bool enable) {
-    using namespace Hid::Sensor::StateValue;
     SP(HidDevice) device = PROMOTE(mDevice);
 
     if (device == nullptr) {
@@ -863,8 +922,11 @@
         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 @@
         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 @@
         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 @@
     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 @@
     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 @@
     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 2dd32b6..0989651 100644
--- a/modules/sensors/dynamic_sensor/HidRawSensor.h
+++ b/modules/sensors/dynamic_sensor/HidRawSensor.h
@@ -121,6 +121,14 @@
     // 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 @@
 
     // 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 6bf34bc..4b447ac 100644
--- a/modules/sensors/dynamic_sensor/HidRawSensorDaemon.cpp
+++ b/modules/sensors/dynamic_sensor/HidRawSensorDaemon.cpp
@@ -39,6 +39,7 @@
         : 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 2728b28..8f47a85 100644
--- a/modules/sensors/dynamic_sensor/HidSensorDef.h
+++ b/modules/sensors/dynamic_sensor/HidSensorDef.h
@@ -77,24 +77,28 @@
 };
 } // 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 bbed032..5823c79 100644
--- a/modules/sensors/dynamic_sensor/HidUtils/Android.bp
+++ b/modules/sensors/dynamic_sensor/HidUtils/Android.bp
@@ -45,6 +45,7 @@
         "HidParser.cpp",
         "HidReport.cpp",
         "HidTree.cpp",
+        "HidUtils.cpp",
     ],
     export_include_dirs: ["."],
 
@@ -99,3 +100,20 @@
 
     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 264f13c..28d87d9 100644
--- a/modules/sensors/dynamic_sensor/HidUtils/HidParser.cpp
+++ b/modules/sensors/dynamic_sensor/HidUtils/HidParser.cpp
@@ -248,6 +248,7 @@
                 ReportItem digest = {
                     .usage = r.getFullUsage(),
                     .id = id,
+                    .usageVector = r.getUsageVector(),
                     .minRaw = logical.first,
                     .maxRaw = logical.second,
                     .a = scale,
@@ -316,4 +317,5 @@
     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 4ef5ec6..cb4a92a 100644
--- a/modules/sensors/dynamic_sensor/HidUtils/HidParser.h
+++ b/modules/sensors/dynamic_sensor/HidUtils/HidParser.h
@@ -89,6 +89,7 @@
     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 @@
 };
 
 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 0000000..0cce2a3
--- /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 0000000..54aa31e
--- /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 0000000..1b1ca70
--- /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);
+    }
+}
+