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

Commit 46f388ce authored by Todd Poynor's avatar Todd Poynor
Browse files

thermalservice: add HIDL ThermalCallback implementation

The IThermalCallback implementation in thermalserviced enables vendor
thermal management code to send thermal events to ThermalService.

Test: manual: marlin with modified thermal-engine.conf
Bug: 30982366
Change-Id: Ic566bc51aebcd03163f8909f846ee4f7025ed472
parent e2938987
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
subdirs = [
    "libthermalcallback"
]

cc_library {
    name: "libthermalservice",

@@ -33,10 +37,17 @@ cc_binary {
        "thermalserviced.cpp",
    ],

    include_dirs: ["frameworks/native"],

    shared_libs: [
        "libthermalservice",
        "libbinder",
        "libutils",
        "libthermalcallback",
        "android.hardware.thermal@1.1",
        "libhidlbase",
        "libhidltransport",
        "liblog",
    ],

    cflags: [
+19 −0
Original line number Diff line number Diff line
cc_library_shared {
    name: "libthermalcallback",
    srcs: [
        "ThermalCallback.cpp",
    ],
    cflags: [
        "-Wall",
        "-Werror",
    ],
    include_dirs: ["frameworks/native"],
    shared_libs: [
        "android.hardware.thermal@1.1",
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libthermalservice",
        "libutils",
    ],
}
+69 −0
Original line number Diff line number Diff line
#define LOG_TAG "android.hardware.thermal.thermalcallback@1.1-impl"
#include <log/log.h>

#include "ThermalCallback.h"
#include "services/thermalservice/ThermalService.h"
#include <math.h>
#include <android/os/Temperature.h>
#include <hardware/thermal.h>

namespace android {
namespace hardware {
namespace thermal {
namespace V1_1 {
namespace implementation {

using ::android::os::ThermalService;
using ::android::hardware::thermal::V1_0::TemperatureType;

// Register a binder ThermalService object for sending events
void ThermalCallback::registerThermalService(sp<ThermalService> thermalService)
{
    mThermalService = thermalService;
}

// Methods from IThermalCallback::V1_1 follow.
Return<void> ThermalCallback::notifyThrottling(
      bool isThrottling,
      const android::hardware::thermal::V1_0::Temperature& temperature) {

    // Convert HIDL IThermal Temperature to binder IThermalService Temperature.
    if (mThermalService != nullptr) {
        float value = NAN;
        int type = DEVICE_TEMPERATURE_UNKNOWN;

        switch(temperature.type) {
          case TemperatureType::CPU:
            type = DEVICE_TEMPERATURE_CPU;
            break;
          case TemperatureType::GPU:
            type = DEVICE_TEMPERATURE_GPU;
            break;
          case TemperatureType::BATTERY:
            type = DEVICE_TEMPERATURE_BATTERY;
            break;
          case TemperatureType::SKIN:
            type = DEVICE_TEMPERATURE_SKIN;
            break;
          case TemperatureType::UNKNOWN:
          default:
            type = DEVICE_TEMPERATURE_UNKNOWN;
            break;
        }

        value = temperature.currentValue == UNKNOWN_TEMPERATURE ? NAN :
            temperature.currentValue;

        android::os::Temperature thermal_svc_temp(value, type);
        mThermalService->notifyThrottling(isThrottling, thermal_svc_temp);
    } else {
        ALOGE("IThermalService binder service not created, drop throttling event");
    }
    return Void();
}

}  // namespace implementation
}  // namespace V1_1
}  // namespace thermal
}  // namespace hardware
}  // namespace android
+43 −0
Original line number Diff line number Diff line
#ifndef ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
#define ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H

#include <android/hardware/thermal/1.1/IThermalCallback.h>
#include <android/hardware/thermal/1.0/types.h>
#include <android/os/Temperature.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include "services/thermalservice/ThermalService.h"

namespace android {
namespace hardware {
namespace thermal {
namespace V1_1 {
namespace implementation {

using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::os::ThermalService;

class ThermalCallback : public IThermalCallback {
 public:
    // Register a binder ThermalService object for sending events
    void registerThermalService(sp<ThermalService> thermalService);

    // Methods from IThermalCallback::V1_1 follow.
    Return<void> notifyThrottling(
        bool isThrottling,
        const android::hardware::thermal::V1_0::Temperature& temperature)
        override;

 private:
    // Our registered binder ThermalService object to use for sending events
    sp<android::os::ThermalService> mThermalService;
};

}  // namespace implementation
}  // namespace V1_1
}  // namespace thermal
}  // namespace hardware
}  // namespace android

#endif  // ANDROID_HARDWARE_THERMAL_V1_1_THERMALCALLBACK_H
+84 −2
Original line number Diff line number Diff line
@@ -19,21 +19,103 @@

#include "thermalserviced.h"
#include "ThermalService.h"
#include "libthermalcallback/ThermalCallback.h"

#include <android/hardware/thermal/1.1/IThermal.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <hidl/HidlTransportSupport.h>

using namespace android;
using ::android::hardware::thermal::V1_1::IThermal;
using ::android::hardware::thermal::V1_0::Temperature;
using ::android::hardware::thermal::V1_1::IThermalCallback;
using ::android::hardware::thermal::V1_1::implementation::ThermalCallback;
using ::android::hardware::configureRpcThreadpool;
using ::android::hardware::hidl_death_recipient;
using ::android::hidl::base::V1_0::IBase;
using ::android::os::ThermalService;

template<typename T>
using Return = hardware::Return<T>;

namespace {

// Our thermalserviced main object
ThermalServiceDaemon* gThermalServiceDaemon;

// Thermal HAL client
sp<IThermal> gThermalHal = nullptr;

// Binder death notifier informing of Thermal HAL death.
struct ThermalServiceDeathRecipient : hidl_death_recipient {
    virtual void serviceDied(
        uint64_t cookie __unused, const wp<IBase>& who __unused) {
        gThermalHal = nullptr;
        ALOGE("IThermal HAL died");
        gThermalServiceDaemon->getThermalHal();
    }
};

sp<ThermalServiceDeathRecipient> gThermalHalDied = nullptr;

}  // anonymous namespace

void ThermalServiceDaemon::thermalServiceStartup() {
    // Binder IThermalService startup
    mThermalService = new android::os::ThermalService;
    mThermalService->publish(mThermalService);
    // Register IThermalService object with IThermalCallback
    if (mThermalCallback != nullptr)
        mThermalCallback->registerThermalService(mThermalService);
    IPCThreadState::self()->joinThreadPool();
}

// Lookup Thermal HAL, register death notifier, register our
// ThermalCallback with the Thermal HAL.
void ThermalServiceDaemon::getThermalHal() {
    gThermalHal = IThermal::getService();
    if (gThermalHal == nullptr) {
        ALOGW("Unable to get Thermal HAL V1.1, vendor thermal event notification not available");
        return;
    }

    // Binder death notifier for Thermal HAL
    if (gThermalHalDied == nullptr)
        gThermalHalDied = new ThermalServiceDeathRecipient();

    if (gThermalHalDied != nullptr)
        gThermalHal->linkToDeath(gThermalHalDied, 0x451F /* cookie */);

    if (mThermalCallback != nullptr) {
        Return<void> ret = gThermalHal->registerThermalCallback(
            mThermalCallback);
        if (!ret.isOk())
            ALOGE("registerThermalCallback failed, status: %s",
                  ret.description().c_str());
    }
}

void ThermalServiceDaemon::thermalCallbackStartup() {
    status_t err;

    // HIDL IThermalCallback startup
    // Need at least 2 threads in thread pool since we wait for dead HAL
    // to come back on the binder death notification thread and we need
    // another thread for the incoming service now available call.
    configureRpcThreadpool(2, false /* callerWillJoin */);
    mThermalCallback = new ThermalCallback();
    err = mThermalCallback->registerAsService();
    ALOGE_IF(err != OK, "Cannot register %s: %d",
        IThermalCallback::descriptor, err);

    // Lookup Thermal HAL and register our ThermalCallback.
    getThermalHal();
}

int main(int /*argc*/, char** /*argv*/) {
    ThermalServiceDaemon* daemon = new ThermalServiceDaemon();
    daemon->thermalServiceStartup();
    gThermalServiceDaemon = new ThermalServiceDaemon();
    gThermalServiceDaemon->thermalCallbackStartup();
    gThermalServiceDaemon->thermalServiceStartup();
    /* NOTREACHED */
}
Loading