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

Commit 6ee35f9f authored by Kathan Shukla's avatar Kathan Shukla Committed by Android (Google) Code Review
Browse files

Merge "Mock hal for Occupant Awareness interface."

parents 479ee338 56c98e4c
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

cc_binary {
    name: "android.hardware.automotive.occupant_awareness@1.0-service_mock",
    relative_install_path: "hw",
    vendor: true,
    srcs: [
        "service.cpp",
        "OccupantAwareness.cpp",
        "DetectionGenerator.cpp",
    ],
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "libutils",
        "android.hardware.automotive.occupant_awareness-ndk_platform",
    ],
}
+71 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <utils/SystemClock.h>

#include "DetectionGenerator.h"

namespace android {
namespace hardware {
namespace automotive {
namespace occupant_awareness {
namespace V1_0 {
namespace implementation {

using ::aidl::android::hardware::automotive::occupant_awareness::ConfidenceLevel;
using ::aidl::android::hardware::automotive::occupant_awareness::DriverMonitoringDetection;
using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetection;
using ::aidl::android::hardware::automotive::occupant_awareness::PresenceDetection;

static int64_t kNanoSecondsPerMilliSecond = 1000 * 1000;

OccupantDetections DetectionGenerator::GetNextDetections() {
    OccupantDetections detections;
    detections.timeStampMillis = android::elapsedRealtimeNano() / kNanoSecondsPerMilliSecond;
    int remainingRoles = getSupportedRoles();
    while (remainingRoles) {
        int currentRole = remainingRoles & (~(remainingRoles - 1));
        remainingRoles = remainingRoles & (remainingRoles - 1);

        OccupantDetection occupantDetection;
        occupantDetection.role = static_cast<Role>(currentRole);

        // Add presence detection object for this occupant.
        PresenceDetection presenceDetection;
        presenceDetection.isOccupantDetected = true;
        presenceDetection.detectionDurationMillis = detections.timeStampMillis;
        occupantDetection.presenceData.emplace_back(presenceDetection);

        if (occupantDetection.role == Role::DRIVER) {
            // Add driver monitoring detection object for this occupant.
            DriverMonitoringDetection driverMonitoringDetection;
            driverMonitoringDetection.confidenceScore = ConfidenceLevel::HIGH;
            driverMonitoringDetection.isLookingOnRoad = 0;
            driverMonitoringDetection.gazeDurationMillis = detections.timeStampMillis;
            occupantDetection.attentionData.emplace_back(driverMonitoringDetection);
        }

        detections.detections.emplace_back(occupantDetection);
    }
    return detections;
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace occupant_awareness
}  // namespace automotive
}  // namespace hardware
}  // namespace android
+50 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwareness.h>

namespace android {
namespace hardware {
namespace automotive {
namespace occupant_awareness {
namespace V1_0 {
namespace implementation {

using ::aidl::android::hardware::automotive::occupant_awareness::BnOccupantAwareness;
using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetections;
using ::aidl::android::hardware::automotive::occupant_awareness::Role;

class DetectionGenerator {
  public:
    static int getSupportedRoles() {
        return static_cast<int>(Role::DRIVER) | static_cast<int>(Role::FRONT_PASSENGER);
    }
    static int getSupportedCapabilities() {
        return static_cast<int>(BnOccupantAwareness::CAP_PRESENCE_DETECTION) |
               static_cast<int>(BnOccupantAwareness::CAP_DRIVER_MONITORING_DETECTION);
    }

    OccupantDetections GetNextDetections();
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace occupant_awareness
}  // namespace automotive
}  // namespace hardware
}  // namespace android
+176 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <utils/SystemClock.h>

#include "OccupantAwareness.h"

namespace android {
namespace hardware {
namespace automotive {
namespace occupant_awareness {
namespace V1_0 {
namespace implementation {

using ndk::ScopedAStatus;

static const int32_t kAllCapabilities = OccupantAwareness::CAP_PRESENCE_DETECTION |
                                        OccupantAwareness::CAP_GAZE_DETECTION |
                                        OccupantAwareness::CAP_DRIVER_MONITORING_DETECTION;

constexpr int64_t kNanoSecondsPerMilliSecond = 1000 * 1000;

ScopedAStatus OccupantAwareness::startDetection(OccupantAwarenessStatus* status) {
    std::lock_guard<std::mutex> lock(mMutex);
    if (mStatus != OccupantAwarenessStatus::NOT_INITIALIZED) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    mStatus = OccupantAwarenessStatus::READY;
    mWorkerThread = std::thread(startWorkerThread, this);
    if (mCallback) {
        mCallback->onSystemStatusChanged(kAllCapabilities, mStatus);
    }

    *status = mStatus;
    return ScopedAStatus::ok();
}

ScopedAStatus OccupantAwareness::stopDetection(OccupantAwarenessStatus* status) {
    std::lock_guard<std::mutex> lock(mMutex);
    if (mStatus != OccupantAwarenessStatus::READY) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    mStatus = OccupantAwarenessStatus::NOT_INITIALIZED;
    mWorkerThread.join();
    if (mCallback) {
        mCallback->onSystemStatusChanged(kAllCapabilities, mStatus);
    }

    *status = mStatus;
    return ScopedAStatus::ok();
}

ScopedAStatus OccupantAwareness::getCapabilityForRole(Role occupantRole, int32_t* capabilities) {
    if (!isValidRole(occupantRole)) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    int intVal = static_cast<int>(occupantRole);
    if ((intVal & DetectionGenerator::getSupportedRoles()) == intVal) {
        int capabilities_ = DetectionGenerator::getSupportedCapabilities();
        if (occupantRole != Role::DRIVER) {
            capabilities_ &= ~CAP_DRIVER_MONITORING_DETECTION;
        }
        *capabilities = capabilities_;
    } else {
        *capabilities = 0;
    }

    return ScopedAStatus::ok();
}

ScopedAStatus OccupantAwareness::getState(Role occupantRole, int detectionCapability,
                                          OccupantAwarenessStatus* status) {
    if (!isValidRole(occupantRole)) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    if (!isValidDetectionCapabilities(detectionCapability) ||
        !isSingularCapability(detectionCapability)) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    int roleVal = static_cast<int>(occupantRole);

    if (((roleVal & DetectionGenerator::getSupportedRoles()) != roleVal) ||
        ((detectionCapability & DetectionGenerator::getSupportedCapabilities()) !=
         detectionCapability)) {
        *status = OccupantAwarenessStatus::NOT_SUPPORTED;
        return ScopedAStatus::ok();
    }

    std::lock_guard<std::mutex> lock(mMutex);
    *status = mStatus;
    return ScopedAStatus::ok();
}

ScopedAStatus OccupantAwareness::setCallback(
        const std::shared_ptr<IOccupantAwarenessClientCallback>& callback) {
    if (callback == nullptr) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    std::lock_guard<std::mutex> lock(mMutex);
    mCallback = callback;
    return ScopedAStatus::ok();
}

ScopedAStatus OccupantAwareness::getLatestDetection(OccupantDetections* detections) {
    std::lock_guard<std::mutex> lock(mMutex);

    if (mStatus != OccupantAwarenessStatus::READY) {
        return ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
    }

    *detections = mLatestDetections;
    return ScopedAStatus::ok();
}

bool OccupantAwareness::isValidRole(Role occupantRole) {
    int intVal = static_cast<int>(occupantRole);
    int allOccupants = static_cast<int>(Role::ALL_OCCUPANTS);
    return (occupantRole != Role::INVALID) && ((intVal & (~allOccupants)) == 0);
}

bool OccupantAwareness::isValidDetectionCapabilities(int detectionCapabilities) {
    return (detectionCapabilities != OccupantAwareness::CAP_NONE) &&
           ((detectionCapabilities & (~kAllCapabilities)) == 0);
}

bool OccupantAwareness::isSingularCapability(int detectionCapability) {
    // Check whether the value is 0, or the value has only one bit set.
    return (detectionCapability & (detectionCapability - 1)) == 0;
}

void OccupantAwareness::startWorkerThread(OccupantAwareness* occupantAwareness) {
    occupantAwareness->workerThreadFunction();
}

void OccupantAwareness::workerThreadFunction() {
    bool isFirstDetection = true;
    int64_t prevDetectionTimeMs;
    while (mStatus == OccupantAwarenessStatus::READY) {
        int64_t currentTimeMs = android::elapsedRealtimeNano() / kNanoSecondsPerMilliSecond;
        if ((isFirstDetection) || (currentTimeMs - prevDetectionTimeMs > mDetectionDurationMs)) {
            std::lock_guard<std::mutex> lock(mMutex);
            mLatestDetections = mGenerator.GetNextDetections();
            if (mCallback != nullptr) {
                mCallback->onDetectionEvent(mLatestDetections);
            }
            isFirstDetection = false;
            prevDetectionTimeMs = currentTimeMs;
        }
    }
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace occupant_awareness
}  // namespace automotive
}  // namespace hardware
}  // namespace android
+83 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <thread>

#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwareness.h>
#include <aidl/android/hardware/automotive/occupant_awareness/BnOccupantAwarenessClientCallback.h>
#include <utils/StrongPointer.h>

#include "DetectionGenerator.h"

namespace android {
namespace hardware {
namespace automotive {
namespace occupant_awareness {
namespace V1_0 {
namespace implementation {

using ::aidl::android::hardware::automotive::occupant_awareness::BnOccupantAwareness;
using ::aidl::android::hardware::automotive::occupant_awareness::IOccupantAwarenessClientCallback;
using ::aidl::android::hardware::automotive::occupant_awareness::OccupantAwarenessStatus;
using ::aidl::android::hardware::automotive::occupant_awareness::OccupantDetections;
using ::aidl::android::hardware::automotive::occupant_awareness::Role;

/**
 * The mock HAL can detect presence of Driver and front passenger, and driver awareness detection
 * for driver.
 **/
class OccupantAwareness : public BnOccupantAwareness {
  public:
    // Methods from ::android::hardware::automotive::occupant_awareness::IOccupantAwareness
    // follow.
    ndk::ScopedAStatus startDetection(OccupantAwarenessStatus* status) override;
    ndk::ScopedAStatus stopDetection(OccupantAwarenessStatus* status) override;
    ndk::ScopedAStatus getCapabilityForRole(Role occupantRole, int32_t* capabilities) override;
    ndk::ScopedAStatus getState(Role occupantRole, int detectionCapability,
                                OccupantAwarenessStatus* status) override;
    ndk::ScopedAStatus setCallback(
            const std::shared_ptr<IOccupantAwarenessClientCallback>& callback) override;
    ndk::ScopedAStatus getLatestDetection(OccupantDetections* detections) override;

  private:
    bool isValidRole(Role occupantRole);
    bool isValidDetectionCapabilities(int detectionCapabilities);
    bool isSingularCapability(int detectionCapability);

    void workerThreadFunction();
    static void startWorkerThread(OccupantAwareness* occupantAwareness);

    std::mutex mMutex;
    std::shared_ptr<IOccupantAwarenessClientCallback> mCallback = nullptr;
    OccupantAwarenessStatus mStatus = OccupantAwarenessStatus::NOT_INITIALIZED;

    OccupantDetections mLatestDetections;
    std::thread mWorkerThread;

    DetectionGenerator mGenerator;

    // Generate a new detection every 1ms.
    const int64_t mDetectionDurationMs = 1;
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace occupant_awareness
}  // namespace automotive
}  // namespace hardware
}  // namespace android
Loading