Merge "Specify NNAPI Burst FMQ read/write requirements"
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index d3d7387..a4e95ed 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -64,7 +64,7 @@
     // The error passed to the last onError() callback.
     FaceError error;
 
-    // The userId passed to the last onRemoved() callback.
+    // The userId passed to the last callback.
     int32_t userId;
 };
 
@@ -74,24 +74,32 @@
 class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
                      public IBiometricsFaceClientCallback {
   public:
-    Return<void> onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override {
-        NotifyFromCallback(kCallbackNameOnEnrollResult);
+    Return<void> onEnrollResult(uint64_t, uint32_t, int32_t userId, uint32_t) override {
+        FaceCallbackArgs args = {};
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnEnrollResult, args);
         return Void();
     }
 
-    Return<void> onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec<uint8_t>&) override {
-        NotifyFromCallback(kCallbackNameOnAuthenticated);
+    Return<void> onAuthenticated(uint64_t, uint32_t, int32_t userId,
+                                 const hidl_vec<uint8_t>&) override {
+        FaceCallbackArgs args = {};
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnAuthenticated, args);
         return Void();
     }
 
-    Return<void> onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override {
-        NotifyFromCallback(kCallbackNameOnAcquired);
+    Return<void> onAcquired(uint64_t, int32_t userId, FaceAcquiredInfo, int32_t) override {
+        FaceCallbackArgs args = {};
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnAcquired, args);
         return Void();
     }
 
-    Return<void> onError(uint64_t, int32_t, FaceError error, int32_t) override {
+    Return<void> onError(uint64_t, int32_t userId, FaceError error, int32_t) override {
         FaceCallbackArgs args = {};
         args.error = error;
+        args.userId = userId;
         NotifyFromCallback(kCallbackNameOnError, args);
         return Void();
     }
@@ -103,8 +111,10 @@
         return Void();
     }
 
-    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
-        NotifyFromCallback(kCallbackNameOnEnumerate);
+    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t userId) override {
+        FaceCallbackArgs args = {};
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnEnumerate, args);
         return Void();
     }
 
@@ -185,6 +195,7 @@
     // onError should be called with a meaningful (nonzero) error.
     auto res = mCallback->WaitForCallback(kCallbackNameOnError);
     EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
     EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
 }
 
@@ -205,6 +216,7 @@
     // onError should be called with a meaningful (nonzero) error.
     auto res = mCallback->WaitForCallback(kCallbackNameOnError);
     EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
     EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
 }
 
@@ -271,6 +283,7 @@
     Return<Status> ret = mService->enumerate();
     ASSERT_EQ(Status::OK, static_cast<Status>(ret));
     auto res = mCallback->WaitForCallback(kCallbackNameOnEnumerate);
+    EXPECT_EQ(kUserId, res.args->userId);
     EXPECT_TRUE(res.no_timeout);
 }
 
@@ -330,6 +343,7 @@
     auto res = mCallback->WaitForCallback(kCallbackNameOnError);
     // make sure callback was invoked within kRevokeChallengeTimeout
     EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
     EXPECT_EQ(FaceError::CANCELED, res.args->error);
 }
 
diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
index 14b8bbd..f0bba57 100644
--- a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
+++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
@@ -325,7 +325,7 @@
         return ::testing::AssertionFailure();
     }
 
-    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->pointer()));
+    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->unsecurePointer()));
     memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
 
     // hidlMemory is not to be passed out of scope!
@@ -568,7 +568,7 @@
     EXPECT_EQ(Status::OK, descrambleStatus);
 
     ASSERT_NE(nullptr, dataMemory.get());
-    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->pointer()));
+    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
 
     int compareResult =
         memcmp(static_cast<const void*>(opBuffer), static_cast<const void*>(kOutRefBinaryBuffer),
diff --git a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp
index 88f1fb0..0264bdd 100644
--- a/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp
+++ b/cas/1.1/vts/functional/VtsHalCasV1_1TargetTest.cpp
@@ -366,7 +366,7 @@
         return ::testing::AssertionFailure();
     }
 
-    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->pointer()));
+    uint8_t* ipBuffer = static_cast<uint8_t*>(static_cast<void*>(mem->unsecurePointer()));
     memcpy(ipBuffer, kInBinaryBuffer, sizeof(kInBinaryBuffer));
 
     // hidlMemory is not to be passed out of scope!
@@ -543,7 +543,7 @@
     EXPECT_EQ(Status::OK, descrambleStatus);
 
     ASSERT_NE(nullptr, dataMemory.get());
-    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->pointer()));
+    uint8_t* opBuffer = static_cast<uint8_t*>(static_cast<void*>(dataMemory->unsecurePointer()));
 
     int compareResult =
             memcmp(static_cast<const void*>(opBuffer),
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
index 62a163c..4b8c6bb 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/Composer.h
@@ -67,6 +67,14 @@
             }
         }
 
+        // we do not have HWC2_CAPABILITY_SKIP_VALIDATE defined in
+        // IComposer::Capability.  However, this is defined in hwcomposer2.h,
+        // so if the device returns it, add it manually to be returned to the
+        // client
+        if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+            caps.push_back(static_cast<IComposer::Capability>(HWC2_CAPABILITY_SKIP_VALIDATE));
+        }
+
         hidl_vec<IComposer::Capability> caps_reply;
         caps_reply.setToExternal(caps.data(), caps.size());
         hidl_cb(caps_reply);
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 5d2f65d..9477ee6 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -20,6 +20,7 @@
 #include <composer-vts/2.1/ComposerVts.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
 #include <composer-vts/2.1/TestCommandReader.h>
+#include <hardware/hwcomposer2.h>
 #include <mapper-vts/2.0/MapperVts.h>
 #include <mapper-vts/3.0/MapperVts.h>
 #include <mapper-vts/4.0/MapperVts.h>
@@ -789,6 +790,12 @@
  * surface damage have been set
  */
 TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) {
+    if (!mComposer->hasCapability(
+                static_cast<IComposer::Capability>(HWC2_CAPABILITY_SKIP_VALIDATE))) {
+        std::cout << "Device does not have skip validate capability, skipping" << std::endl;
+        GTEST_SUCCEED();
+        return;
+    }
     mWriter->selectDisplay(mPrimaryDisplay);
     mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON);
     mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE);
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 44dddfd..697bf9e 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -45,6 +45,7 @@
     ],
     init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
     vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
+    cflags: ["-DLOG_TAG=\"SensorsMultiHal\""],
 }
 
 cc_library_headers {
diff --git a/sensors/2.0/multihal/HalProxy.cpp b/sensors/2.0/multihal/HalProxy.cpp
index dcdccac..b4d2466 100644
--- a/sensors/2.0/multihal/HalProxy.cpp
+++ b/sensors/2.0/multihal/HalProxy.cpp
@@ -69,43 +69,13 @@
 };
 
 HalProxy::HalProxy() {
-    const char* kMultiHalConfigFilePath = "/vendor/etc/sensors/hals.conf";
-    std::ifstream subHalConfigStream(kMultiHalConfigFilePath);
-    if (!subHalConfigStream) {
-        LOG_FATAL("Failed to load subHal config file: %s", kMultiHalConfigFilePath);
-    } else {
-        std::string subHalLibraryFile;
-        while (subHalConfigStream >> subHalLibraryFile) {
-            void* handle = dlopen(subHalLibraryFile.c_str(), RTLD_NOW);
-            if (handle == nullptr) {
-                LOG_FATAL("dlopen failed for library: %s", subHalLibraryFile.c_str());
-            } else {
-                SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr =
-                        (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal");
-                if (sensorsHalGetSubHalPtr == nullptr) {
-                    LOG_FATAL("Failed to locate sensorsHalGetSubHal function for library: %s",
-                              subHalLibraryFile.c_str());
-                } else {
-                    std::function<SensorsHalGetSubHalFunc> sensorsHalGetSubHal =
-                            *sensorsHalGetSubHalPtr;
-                    uint32_t version;
-                    ISensorsSubHal* subHal = sensorsHalGetSubHal(&version);
-                    if (version != SUB_HAL_2_0_VERSION) {
-                        LOG_FATAL("SubHal version was not 2.0 for library: %s",
-                                  subHalLibraryFile.c_str());
-                    } else {
-                        ALOGI("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
-                        mSubHalList.push_back(subHal);
-                    }
-                }
-            }
-        }
-    }
-    // TODO: Discover sensors
+    const char* kMultiHalConfigFile = "/vendor/etc/sensors/hals.conf";
+    initializeSubHalListFromConfigFile(kMultiHalConfigFile);
+    initializeSensorList();
 }
 
 HalProxy::HalProxy(std::vector<ISensorsSubHal*>& subHalList) : mSubHalList(subHalList) {
-    // TODO: Perform the same steps as the empty constructor.
+    initializeSensorList();
 }
 
 HalProxy::~HalProxy() {
@@ -113,19 +83,37 @@
     // state.
 }
 
-Return<void> HalProxy::getSensorsList(getSensorsList_cb /* _hidl_cb */) {
-    // TODO: Output sensors list created as part of HalProxy().
+Return<void> HalProxy::getSensorsList(getSensorsList_cb _hidl_cb) {
+    _hidl_cb(mSensorList);
     return Void();
 }
 
-Return<Result> HalProxy::setOperationMode(OperationMode /* mode */) {
-    // TODO: Proxy API call to all sub-HALs and return appropriate result.
-    return Result::INVALID_OPERATION;
+Return<Result> HalProxy::setOperationMode(OperationMode mode) {
+    Result result = Result::OK;
+    size_t subHalIndex;
+    for (subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
+        ISensorsSubHal* subHal = mSubHalList[subHalIndex];
+        result = subHal->setOperationMode(mode);
+        if (result != Result::OK) {
+            ALOGE("setOperationMode failed for SubHal: %s", subHal->getName().c_str());
+            break;
+        }
+    }
+    if (result != Result::OK) {
+        // Reset the subhal operation modes that have been flipped
+        for (size_t i = 0; i < subHalIndex; i++) {
+            ISensorsSubHal* subHal = mSubHalList[i];
+            subHal->setOperationMode(mCurrentOperationMode);
+        }
+    } else {
+        mCurrentOperationMode = mode;
+    }
+    return result;
 }
 
 Return<Result> HalProxy::activate(int32_t sensorHandle, bool enabled) {
     return getSubHalForSensorHandle(sensorHandle)
-            ->activate(zeroOutFirstByte(sensorHandle), enabled);
+            ->activate(clearSubHalIndex(sensorHandle), enabled);
 }
 
 Return<Result> HalProxy::initialize(
@@ -166,11 +154,11 @@
 Return<Result> HalProxy::batch(int32_t sensorHandle, int64_t samplingPeriodNs,
                                int64_t maxReportLatencyNs) {
     return getSubHalForSensorHandle(sensorHandle)
-            ->batch(zeroOutFirstByte(sensorHandle), samplingPeriodNs, maxReportLatencyNs);
+            ->batch(clearSubHalIndex(sensorHandle), samplingPeriodNs, maxReportLatencyNs);
 }
 
 Return<Result> HalProxy::flush(int32_t sensorHandle) {
-    return getSubHalForSensorHandle(sensorHandle)->flush(zeroOutFirstByte(sensorHandle));
+    return getSubHalForSensorHandle(sensorHandle)->flush(clearSubHalIndex(sensorHandle));
 }
 
 Return<Result> HalProxy::injectSensorData(const Event& /* event */) {
@@ -217,12 +205,81 @@
     return Return<void>();
 }
 
+void HalProxy::initializeSubHalListFromConfigFile(const char* configFileName) {
+    std::ifstream subHalConfigStream(configFileName);
+    if (!subHalConfigStream) {
+        ALOGE("Failed to load subHal config file: %s", configFileName);
+    } else {
+        std::string subHalLibraryFile;
+        while (subHalConfigStream >> subHalLibraryFile) {
+            void* handle = dlopen(subHalLibraryFile.c_str(), RTLD_NOW);
+            if (handle == nullptr) {
+                ALOGE("dlopen failed for library: %s", subHalLibraryFile.c_str());
+            } else {
+                SensorsHalGetSubHalFunc* sensorsHalGetSubHalPtr =
+                        (SensorsHalGetSubHalFunc*)dlsym(handle, "sensorsHalGetSubHal");
+                if (sensorsHalGetSubHalPtr == nullptr) {
+                    ALOGE("Failed to locate sensorsHalGetSubHal function for library: %s",
+                          subHalLibraryFile.c_str());
+                } else {
+                    std::function<SensorsHalGetSubHalFunc> sensorsHalGetSubHal =
+                            *sensorsHalGetSubHalPtr;
+                    uint32_t version;
+                    ISensorsSubHal* subHal = sensorsHalGetSubHal(&version);
+                    if (version != SUB_HAL_2_0_VERSION) {
+                        ALOGE("SubHal version was not 2.0 for library: %s",
+                              subHalLibraryFile.c_str());
+                    } else {
+                        ALOGV("Loaded SubHal from library: %s", subHalLibraryFile.c_str());
+                        mSubHalList.push_back(subHal);
+                    }
+                }
+            }
+        }
+    }
+}
+
+void HalProxy::initializeSensorList() {
+    for (size_t subHalIndex = 0; subHalIndex < mSubHalList.size(); subHalIndex++) {
+        ISensorsSubHal* subHal = mSubHalList[subHalIndex];
+        auto result = subHal->getSensorsList([&](const auto& list) {
+            for (SensorInfo sensor : list) {
+                if ((sensor.sensorHandle & kSensorHandleSubHalIndexMask) != 0) {
+                    ALOGE("SubHal sensorHandle's first byte was not 0");
+                } else {
+                    ALOGV("Loaded sensor: %s", sensor.name.c_str());
+                    sensor.sensorHandle |= (subHalIndex << 24);
+                    setDirectChannelFlags(&sensor, subHal);
+                    mSensorList.push_back(sensor);
+                }
+            }
+        });
+        if (!result.isOk()) {
+            ALOGE("getSensorsList call failed for SubHal: %s", subHal->getName().c_str());
+        }
+    }
+}
+
+void HalProxy::setDirectChannelFlags(SensorInfo* sensorInfo, ISensorsSubHal* subHal) {
+    bool sensorSupportsDirectChannel =
+            (sensorInfo->flags & (V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
+                                  V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL)) != 0;
+    if (mDirectChannelSubHal == nullptr && sensorSupportsDirectChannel) {
+        mDirectChannelSubHal = subHal;
+    } else if (mDirectChannelSubHal != nullptr && subHal != mDirectChannelSubHal) {
+        // disable direct channel capability for sensors in subHals that are not
+        // the only one we will enable
+        sensorInfo->flags &= ~(V1_0::SensorFlagBits::MASK_DIRECT_REPORT |
+                               V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL);
+    }
+}
+
 ISensorsSubHal* HalProxy::getSubHalForSensorHandle(uint32_t sensorHandle) {
     return mSubHalList[static_cast<size_t>(sensorHandle >> 24)];
 }
 
-uint32_t HalProxy::zeroOutFirstByte(uint32_t num) {
-    return num & 0x00FFFFFF;
+uint32_t HalProxy::clearSubHalIndex(uint32_t sensorHandle) {
+    return sensorHandle & (~kSensorHandleSubHalIndexMask);
 }
 
 }  // namespace implementation
diff --git a/sensors/2.0/multihal/include/HalProxy.h b/sensors/2.0/multihal/include/HalProxy.h
index 809d07e..4ecb58b 100644
--- a/sensors/2.0/multihal/include/HalProxy.h
+++ b/sensors/2.0/multihal/include/HalProxy.h
@@ -39,7 +39,8 @@
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
-struct HalProxy : public ISensors {
+class HalProxy : public ISensors {
+  public:
     using Event = ::android::hardware::sensors::V1_0::Event;
     using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
     using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
@@ -119,6 +120,47 @@
      */
     std::vector<ISensorsSubHal*> mSubHalList;
 
+    /**
+     * List of SensorInfo objects that contains the sensor info from subhals as
+     * well as the modified sensor handle for the framework.
+     *
+     * The subhal index is encoded in the first byte of the sensor handle and
+     * the remaining bytes are generated by the subhal to identify the sensor.
+     */
+    std::vector<SensorInfo> mSensorList;
+
+    //! The current operation mode for all subhals.
+    OperationMode mCurrentOperationMode = OperationMode::NORMAL;
+
+    //! The single subHal that supports directChannel reporting.
+    ISensorsSubHal* mDirectChannelSubHal = nullptr;
+
+    //! The bit mask used to get the subhal index from a sensor handle.
+    static constexpr uint32_t kSensorHandleSubHalIndexMask = 0xFF000000;
+
+    /**
+     * Initialize the list of SubHal objects in mSubHalList by reading from dynamic libraries
+     * listed in a config file.
+     */
+    void initializeSubHalListFromConfigFile(const char* configFileName);
+
+    /**
+     * Initialize the list of SensorInfo objects in mSensorList by getting sensors from each
+     * subhal.
+     */
+    void initializeSensorList();
+
+    /**
+     * Clear direct channel flags if the HalProxy has already chosen a subhal as its direct channel
+     * subhal. Set the directChannelSubHal pointer to the subHal passed in if this is the first
+     * direct channel enabled sensor seen.
+     *
+     * @param sensorInfo The SensorInfo object that may be altered to have direct channel support
+     *    disabled.
+     * @param subHal The subhal pointer that the current sensorInfo object came from.
+     */
+    void setDirectChannelFlags(SensorInfo* sensorInfo, ISensorsSubHal* subHal);
+
     /*
      * Get the subhal pointer which can be found by indexing into the mSubHalList vector
      * using the index from the first byte of sensorHandle.
@@ -128,14 +170,13 @@
     ISensorsSubHal* getSubHalForSensorHandle(uint32_t sensorHandle);
 
     /*
-     * Zero out the first (most significant) byte in a number. Used in modifying the sensor handles
-     * before passing them to subhals.
+     * Clear out the subhal index bytes from a sensorHandle.
      *
-     * @param num The uint32_t number to work with.
+     * @param sensorHandle The sensor handle to modify.
      *
-     * @return The modified version of num param.
+     * @return The modified version of the sensor handle.
      */
-    static uint32_t zeroOutFirstByte(uint32_t num);
+    static uint32_t clearSubHalIndex(uint32_t sensorHandle);
 };
 
 }  // namespace implementation
diff --git a/sensors/2.0/multihal/include/SubHal.h b/sensors/2.0/multihal/include/SubHal.h
index 75e93a1..e84cba5 100644
--- a/sensors/2.0/multihal/include/SubHal.h
+++ b/sensors/2.0/multihal/include/SubHal.h
@@ -137,6 +137,7 @@
  * sub-HALs can continue to use the lower 3 bytes of the handle.
  */
 class ISensorsSubHal : public ISensors {
+  public:
     // The ISensors version of initialize isn't used for multihal. Instead, sub-HALs must implement
     // the version below to allow communciation logic to centralized in the HalProxy
     Return<Result> initialize(
diff --git a/sensors/2.0/multihal/service.cpp b/sensors/2.0/multihal/service.cpp
index 995cf3c..ef77048 100644
--- a/sensors/2.0/multihal/service.cpp
+++ b/sensors/2.0/multihal/service.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "android.hardware.sensors@2.0-service"
-
 #include <android/hardware/sensors/2.0/ISensors.h>
 #include <hidl/HidlTransportSupport.h>
 #include <log/log.h>
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp
index 13d80f7..21ceb0c 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/2.0/multihal/tests/Android.bp
@@ -86,4 +86,4 @@
         "libutils",
     ],
     test_suites: ["device-tests"],
-}
\ No newline at end of file
+}
diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/2.0/multihal/tests/HalProxy_test.cpp
index 9edc88a..1e1f9e9 100644
--- a/sensors/2.0/multihal/tests/HalProxy_test.cpp
+++ b/sensors/2.0/multihal/tests/HalProxy_test.cpp
@@ -15,25 +15,176 @@
 
 #include <gtest/gtest.h>
 
+#include <android/hardware/sensors/2.0/types.h>
+
 #include "HalProxy.h"
 #include "SensorsSubHal.h"
 
+#include <vector>
+
+namespace {
+
+using ::android::hardware::sensors::V1_0::SensorFlagBits;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::sensors::V1_0::SensorType;
 using ::android::hardware::sensors::V2_0::implementation::HalProxy;
+using ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal;
+using ::android::hardware::sensors::V2_0::subhal::implementation::
+        AllSupportDirectChannelSensorsSubHal;
+using ::android::hardware::sensors::V2_0::subhal::implementation::ContinuousSensorsSubHal;
+using ::android::hardware::sensors::V2_0::subhal::implementation::
+        DoesNotSupportDirectChannelSensorsSubHal;
+using ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal;
 using ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal;
 
-// TODO: Add more interesting tests such as
-//     - verify setOperationMode invokes all subhals
-//     - verify if a subhal fails to change operation mode, that state is reset properly
-//     - Available sensors are obtained during initialization
-//
-// You can run this suite using "atest android.hardware.sensors@2.0-halproxy-unit-tests".
-//
-// See https://source.android.com/compatibility/tests/development/native-func-e2e.md for more info
-// on how tests are set up and for information on the gtest framework itself.
-TEST(HalProxyTest, ExampleTest) {
-    SensorsSubHal subHal;
-    std::vector<ISensorsSubHal*> fakeSubHals;
-    fakeSubHals.push_back(&subHal);
+using ::android::hardware::sensors::V2_0::subhal::implementation::
+        SetOperationModeFailingSensorsSubHal;
 
+// Helper declarations follow
+
+/**
+ * Tests that for each SensorInfo object from a proxy getSensorsList call each corresponding
+ * object from a subhal getSensorsList call has the same type and its last 3 bytes are the
+ * same for sensorHandle field.
+ *
+ * @param proxySensorsList The list of SensorInfo objects from the proxy.getSensorsList callback.
+ * @param subHalSenosrsList The list of SensorInfo objects from the subHal.getSensorsList callback.
+ */
+void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
+                                       const std::vector<SensorInfo>& subHalSensorsList);
+
+/**
+ * Tests that there is exactly one subhal that allows its sensors to have direct channel enabled.
+ * Therefore, all SensorInfo objects that are not from the enabled subhal should be disabled for
+ * direct channel.
+ *
+ * @param sensorsList The SensorInfo object list from proxy.getSensorsList call.
+ * @param enabledSubHalIndex The index of the subhal in the halproxy that is expected to be
+ *     enabled.
+ */
+void testSensorsListForOneDirectChannelEnabledSubHal(const std::vector<SensorInfo>& sensorsList,
+                                                     size_t enabledSubHalIndex);
+
+// Tests follow
+TEST(HalProxyTest, GetSensorsListOneSubHalTest) {
+    AllSensorsSubHal subHal;
+    std::vector<ISensorsSubHal*> fakeSubHals{&subHal};
     HalProxy proxy(fakeSubHals);
-}
\ No newline at end of file
+
+    proxy.getSensorsList([&](const auto& proxySensorsList) {
+        subHal.getSensorsList([&](const auto& subHalSensorsList) {
+            testSensorsListFromProxyAndSubHal(proxySensorsList, subHalSensorsList);
+        });
+    });
+}
+
+TEST(HalProxyTest, GetSensorsListTwoSubHalTest) {
+    ContinuousSensorsSubHal continuousSubHal;
+    OnChangeSensorsSubHal onChangeSubHal;
+    std::vector<ISensorsSubHal*> fakeSubHals;
+    fakeSubHals.push_back(&continuousSubHal);
+    fakeSubHals.push_back(&onChangeSubHal);
+    HalProxy proxy(fakeSubHals);
+
+    std::vector<SensorInfo> proxySensorsList, combinedSubHalSensorsList;
+
+    proxy.getSensorsList([&](const auto& list) { proxySensorsList = list; });
+    continuousSubHal.getSensorsList([&](const auto& list) {
+        combinedSubHalSensorsList.insert(combinedSubHalSensorsList.end(), list.begin(), list.end());
+    });
+    onChangeSubHal.getSensorsList([&](const auto& list) {
+        combinedSubHalSensorsList.insert(combinedSubHalSensorsList.end(), list.begin(), list.end());
+    });
+
+    testSensorsListFromProxyAndSubHal(proxySensorsList, combinedSubHalSensorsList);
+}
+
+TEST(HalProxyTest, SetOperationModeTwoSubHalSuccessTest) {
+    ContinuousSensorsSubHal subHal1;
+    OnChangeSensorsSubHal subHal2;
+
+    std::vector<ISensorsSubHal*> fakeSubHals{&subHal1, &subHal2};
+    HalProxy proxy(fakeSubHals);
+
+    EXPECT_EQ(subHal1.getOperationMode(), OperationMode::NORMAL);
+    EXPECT_EQ(subHal2.getOperationMode(), OperationMode::NORMAL);
+
+    Result result = proxy.setOperationMode(OperationMode::DATA_INJECTION);
+
+    EXPECT_EQ(result, Result::OK);
+    EXPECT_EQ(subHal1.getOperationMode(), OperationMode::DATA_INJECTION);
+    EXPECT_EQ(subHal2.getOperationMode(), OperationMode::DATA_INJECTION);
+}
+
+TEST(HalProxyTest, SetOperationModeTwoSubHalFailTest) {
+    AllSensorsSubHal subHal1;
+    SetOperationModeFailingSensorsSubHal subHal2;
+
+    std::vector<ISensorsSubHal*> fakeSubHals{&subHal1, &subHal2};
+    HalProxy proxy(fakeSubHals);
+
+    EXPECT_EQ(subHal1.getOperationMode(), OperationMode::NORMAL);
+    EXPECT_EQ(subHal2.getOperationMode(), OperationMode::NORMAL);
+
+    Result result = proxy.setOperationMode(OperationMode::DATA_INJECTION);
+
+    EXPECT_NE(result, Result::OK);
+    EXPECT_EQ(subHal1.getOperationMode(), OperationMode::NORMAL);
+    EXPECT_EQ(subHal2.getOperationMode(), OperationMode::NORMAL);
+}
+
+TEST(HalProxyTest, InitDirectChannelTwoSubHalsUnitTest) {
+    AllSupportDirectChannelSensorsSubHal subHal1;
+    AllSupportDirectChannelSensorsSubHal subHal2;
+
+    std::vector<ISensorsSubHal*> fakeSubHals{&subHal1, &subHal2};
+    HalProxy proxy(fakeSubHals);
+
+    proxy.getSensorsList([&](const auto& sensorsList) {
+        testSensorsListForOneDirectChannelEnabledSubHal(sensorsList, 0);
+    });
+}
+
+TEST(HalProxyTest, InitDirectChannelThreeSubHalsUnitTest) {
+    DoesNotSupportDirectChannelSensorsSubHal subHal1;
+    AllSupportDirectChannelSensorsSubHal subHal2, subHal3;
+    std::vector<ISensorsSubHal*> fakeSubHals{&subHal1, &subHal2, &subHal3};
+    HalProxy proxy(fakeSubHals);
+
+    proxy.getSensorsList([&](const auto& sensorsList) {
+        testSensorsListForOneDirectChannelEnabledSubHal(sensorsList, 1);
+    });
+}
+
+// Helper implementations follow
+void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
+                                       const std::vector<SensorInfo>& subHalSensorsList) {
+    EXPECT_EQ(proxySensorsList.size(), subHalSensorsList.size());
+
+    for (size_t i = 0; i < proxySensorsList.size(); i++) {
+        const SensorInfo& proxySensor = proxySensorsList[i];
+        const SensorInfo& subHalSensor = subHalSensorsList[i];
+
+        EXPECT_EQ(proxySensor.type, subHalSensor.type);
+        EXPECT_EQ(proxySensor.sensorHandle & 0x00FFFFFF, subHalSensor.sensorHandle);
+    }
+}
+
+void testSensorsListForOneDirectChannelEnabledSubHal(const std::vector<SensorInfo>& sensorsList,
+                                                     size_t enabledSubHalIndex) {
+    for (const SensorInfo& sensor : sensorsList) {
+        size_t subHalIndex = static_cast<size_t>(sensor.sensorHandle >> 24);
+        if (subHalIndex == enabledSubHalIndex) {
+            // First subhal should have been picked as the direct channel subhal
+            // and so have direct channel enabled on all of its sensors
+            EXPECT_NE(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT, 0);
+            EXPECT_NE(sensor.flags & SensorFlagBits::MASK_DIRECT_CHANNEL, 0);
+        } else {
+            // All other subhals should have direct channel disabled for all sensors
+            EXPECT_EQ(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT, 0);
+            EXPECT_EQ(sensor.flags & SensorFlagBits::MASK_DIRECT_CHANNEL, 0);
+        }
+    }
+}
+
+}  // namespace
diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp
index 8d45982..d581c49 100644
--- a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp
+++ b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.cpp
@@ -20,7 +20,16 @@
 #include <log/log.h>
 
 ISensorsSubHal* sensorsHalGetSubHal(uint32_t* version) {
+#if defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS
+    static ::android::hardware::sensors::V2_0::subhal::implementation::AllSensorsSubHal subHal;
+#elif defined SUPPORT_CONTINUOUS_SENSORS
+    static ::android::hardware::sensors::V2_0::subhal::implementation::ContinuousSensorsSubHal
+            subHal;
+#elif defined SUPPORT_ON_CHANGE_SENSORS
+    static ::android::hardware::sensors::V2_0::subhal::implementation::OnChangeSensorsSubHal subHal;
+#else
     static ::android::hardware::sensors::V2_0::subhal::implementation::SensorsSubHal subHal;
+#endif  // defined SUPPORT_CONTINUOUS_SENSORS && defined SUPPORT_ON_CHANGE_SENSORS
     *version = SUB_HAL_2_0_VERSION;
     return &subHal;
 }
@@ -42,22 +51,7 @@
 using ::android::hardware::sensors::V2_0::WakeLockQueueFlagBits;
 using ::android::hardware::sensors::V2_0::implementation::ScopedWakelock;
 
-SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {
-#ifdef SUPPORT_CONTINUOUS_SENSORS
-    AddSensor<AccelSensor>();
-    AddSensor<GyroSensor>();
-    AddSensor<MagnetometerSensor>();
-    AddSensor<PressureSensor>();
-#endif  // SUPPORT_CONTINUOUS_SENSORS
-
-#ifdef SUPPORT_ON_CHANGE_SENSORS
-    AddSensor<AmbientTempSensor>();
-    AddSensor<DeviceTempSensor>();
-    AddSensor<LightSensor>();
-    AddSensor<ProximitySensor>();
-    AddSensor<RelativeHumiditySensor>();
-#endif  // SUPPORT_ON_CHANGE_SENSORS
-}
+SensorsSubHal::SensorsSubHal() : mCallback(nullptr), mNextHandle(1) {}
 
 // Methods from ::android::hardware::sensors::V2_0::ISensors follow.
 Return<void> SensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
@@ -74,6 +68,7 @@
     for (auto sensor : mSensors) {
         sensor.second->setOperationMode(mode);
     }
+    mCurrentOperationMode = mode;
     return Result::OK;
 }
 
@@ -171,6 +166,61 @@
     mCallback->postEvents(events, std::move(wakelock));
 }
 
+ContinuousSensorsSubHal::ContinuousSensorsSubHal() {
+    AddSensor<AccelSensor>();
+    AddSensor<GyroSensor>();
+    AddSensor<MagnetometerSensor>();
+    AddSensor<PressureSensor>();
+}
+
+OnChangeSensorsSubHal::OnChangeSensorsSubHal() {
+    AddSensor<AmbientTempSensor>();
+    AddSensor<DeviceTempSensor>();
+    AddSensor<LightSensor>();
+    AddSensor<ProximitySensor>();
+    AddSensor<RelativeHumiditySensor>();
+}
+
+AllSensorsSubHal::AllSensorsSubHal() {
+    AddSensor<AccelSensor>();
+    AddSensor<GyroSensor>();
+    AddSensor<MagnetometerSensor>();
+    AddSensor<PressureSensor>();
+    AddSensor<AmbientTempSensor>();
+    AddSensor<DeviceTempSensor>();
+    AddSensor<LightSensor>();
+    AddSensor<ProximitySensor>();
+    AddSensor<RelativeHumiditySensor>();
+}
+
+Return<Result> SetOperationModeFailingSensorsSubHal::setOperationMode(OperationMode /*mode*/) {
+    return Result::BAD_VALUE;
+}
+
+Return<void> AllSupportDirectChannelSensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
+    std::vector<SensorInfo> sensors;
+    for (const auto& sensor : mSensors) {
+        SensorInfo sensorInfo = sensor.second->getSensorInfo();
+        sensorInfo.flags |= V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL;
+        sensorInfo.flags |= V1_0::SensorFlagBits::MASK_DIRECT_REPORT;
+        sensors.push_back(sensorInfo);
+    }
+    _hidl_cb(sensors);
+    return Void();
+}
+
+Return<void> DoesNotSupportDirectChannelSensorsSubHal::getSensorsList(getSensorsList_cb _hidl_cb) {
+    std::vector<SensorInfo> sensors;
+    for (const auto& sensor : mSensors) {
+        SensorInfo sensorInfo = sensor.second->getSensorInfo();
+        sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_CHANNEL);
+        sensorInfo.flags &= ~static_cast<uint32_t>(V1_0::SensorFlagBits::MASK_DIRECT_REPORT);
+        sensors.push_back(sensorInfo);
+    }
+    _hidl_cb(sensors);
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace subhal
 }  // namespace V2_0
diff --git a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h
index 93009d5..61caa2c 100644
--- a/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h
+++ b/sensors/2.0/multihal/tests/fake_subhal/SensorsSubHal.h
@@ -20,6 +20,8 @@
 
 #include "Sensor.h"
 
+#include <vector>
+
 namespace android {
 namespace hardware {
 namespace sensors {
@@ -27,6 +29,8 @@
 namespace subhal {
 namespace implementation {
 
+using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::Result;
 using ::android::hardware::sensors::V2_0::implementation::IHalProxyCallback;
 
 /**
@@ -35,18 +39,18 @@
  */
 class SensorsSubHal : public ISensorsSubHal, public ISensorsEventCallback {
     using Event = ::android::hardware::sensors::V1_0::Event;
-    using OperationMode = ::android::hardware::sensors::V1_0::OperationMode;
     using RateLevel = ::android::hardware::sensors::V1_0::RateLevel;
-    using Result = ::android::hardware::sensors::V1_0::Result;
     using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
 
   public:
     SensorsSubHal();
 
     // Methods from ::android::hardware::sensors::V2_0::ISensors follow.
-    Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+    virtual Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
 
-    Return<Result> setOperationMode(OperationMode mode) override;
+    virtual Return<Result> setOperationMode(OperationMode mode) override;
+
+    OperationMode getOperationMode() const { return mCurrentOperationMode; }
 
     Return<Result> activate(int32_t sensorHandle, bool enabled) override;
 
@@ -81,7 +85,7 @@
     // Method from ISensorsEventCallback.
     void postEvents(const std::vector<Event>& events, bool wakeup) override;
 
-  private:
+  protected:
     template <class SensorType>
     void AddSensor() {
         std::shared_ptr<SensorType> sensor =
@@ -90,6 +94,18 @@
     }
 
     /**
+     * A map of the available sensors
+     */
+    std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
+
+  private:
+    /**
+     * The current operation mode of the multihal framework. Ensures that all subhals are set to
+     * the same operation mode.
+     */
+    OperationMode mCurrentOperationMode = OperationMode::NORMAL;
+
+    /**
      * Callback used to communicate to the HalProxy when dynamic sensors are connected /
      * disconnected, sensor events need to be sent to the framework, and when a wakelock should be
      * acquired.
@@ -97,16 +113,44 @@
     sp<IHalProxyCallback> mCallback;
 
     /**
-     * A map of the available sensors
-     */
-    std::map<int32_t, std::shared_ptr<Sensor>> mSensors;
-
-    /**
      * The next available sensor handle
      */
     int32_t mNextHandle;
 };
 
+// SubHal that has continuous sensors for testing purposes.
+class ContinuousSensorsSubHal : public SensorsSubHal {
+  public:
+    ContinuousSensorsSubHal();
+};
+
+// SubHal that has on-change sensors for testing purposes.
+class OnChangeSensorsSubHal : public SensorsSubHal {
+  public:
+    OnChangeSensorsSubHal();
+};
+
+// SubHal that has both continuous and on-change sensors for testing purposes.
+class AllSensorsSubHal : public SensorsSubHal {
+  public:
+    AllSensorsSubHal();
+};
+
+class SetOperationModeFailingSensorsSubHal : public AllSensorsSubHal {
+  public:
+    Return<Result> setOperationMode(OperationMode mode) override;
+};
+
+class AllSupportDirectChannelSensorsSubHal : public AllSensorsSubHal {
+  public:
+    Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+};
+
+class DoesNotSupportDirectChannelSensorsSubHal : public AllSensorsSubHal {
+  public:
+    Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+};
+
 }  // namespace implementation
 }  // namespace subhal
 }  // namespace V2_0
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 91ed1f2..7855446 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -29,6 +29,11 @@
         VALL = V0 | V1 | V2 | V3,
     };
 
+    struct BitFieldTester {
+      bitfield<BitField> scalar;
+      vec<bitfield<BitField>> vector;
+     };
+
     enum SomeOtherEnum : uint8_t {
         bar = 66
     };
@@ -108,6 +113,7 @@
 
     haveSomeStrings(string[3] array) generates (string[2] result);
     haveAStringVec(vec<string> vector) generates (vec<string> result);
+    repeatBitfieldVec(vec<bitfield<BitField>> vector) generates (vec<bitfield<BitField>> result);
 
     returnABunchOfStrings() generates (string a, string b, string c);
 
diff --git a/tests/baz/1.0/default/Baz.cpp b/tests/baz/1.0/default/Baz.cpp
index e118122..2ce096c 100644
--- a/tests/baz/1.0/default/Baz.cpp
+++ b/tests/baz/1.0/default/Baz.cpp
@@ -364,6 +364,12 @@
     return Void();
 }
 
+Return<void> Baz::repeatBitfieldVec(const hidl_vec<uint8_t>& vector,
+                                    repeatBitfieldVec_cb _hidl_cb) {
+    _hidl_cb(vector);
+    return Void();
+}
+
 Return<void> Baz::returnABunchOfStrings(returnABunchOfStrings_cb _hidl_cb) {
     hidl_string eins; eins = "Eins";
     hidl_string zwei; zwei = "Zwei";
diff --git a/tests/baz/1.0/default/Baz.h b/tests/baz/1.0/default/Baz.h
index c264f47..1e24d52 100644
--- a/tests/baz/1.0/default/Baz.h
+++ b/tests/baz/1.0/default/Baz.h
@@ -86,6 +86,8 @@
                                  haveSomeStrings_cb _hidl_cb) override;
     Return<void> haveAStringVec(const hidl_vec<hidl_string>& vector,
                                 haveAStringVec_cb _hidl_cb) override;
+    Return<void> repeatBitfieldVec(const hidl_vec<uint8_t>& vector,
+                                   repeatBitfieldVec_cb _hidl_cb) override;
     Return<void> returnABunchOfStrings(returnABunchOfStrings_cb _hidl_cb) override;
     Return<uint8_t> returnABitField() override;
     Return<uint32_t> size(uint32_t size) override;