diff --git a/configs/framework_compatibility_matrix.xml b/configs/framework_compatibility_matrix.xml index f670a77..124105e 100644 --- a/configs/framework_compatibility_matrix.xml +++ b/configs/framework_compatibility_matrix.xml @@ -113,6 +113,14 @@ IAdaptiveBacklight default + + IDisplayColorCalibration + default + + + IDisplayModes + default + ISunlightEnhancement default diff --git a/configs/manifest.xml b/configs/manifest.xml index f90cd73..857d2c7 100644 --- a/configs/manifest.xml +++ b/configs/manifest.xml @@ -303,11 +303,21 @@ IAdaptiveBacklight default + + IDisplayColorCalibration + default + + + IDisplayModes + default + ISunlightEnhancement default @2.0::IAdaptiveBacklight/default + @2.0::IDisplayColorCalibration/default + @2.0::IDisplayModes/default @2.0::ISunlightEnhancement/default diff --git a/livedisplay/Android.bp b/livedisplay/Android.bp index 7e2cdbf..88bcafa 100644 --- a/livedisplay/Android.bp +++ b/livedisplay/Android.bp @@ -19,7 +19,9 @@ cc_binary { relative_install_path: "hw", srcs: [ "AdaptiveBacklight.cpp", + "DisplayModes.cpp", "SunlightEnhancement.cpp", + "DisplayColorCalibration.cpp", "service.cpp", ], shared_libs: [ diff --git a/livedisplay/DisplayColorCalibration.cpp b/livedisplay/DisplayColorCalibration.cpp new file mode 100644 index 0000000..9ce3d44 --- /dev/null +++ b/livedisplay/DisplayColorCalibration.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2019 The LineageOS 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 +#include + +#include + +#include "DisplayColorCalibration.h" + +using android::base::ReadFileToString; +using android::base::Split; +using android::base::Trim; +using android::base::WriteStringToFile; + +namespace vendor { +namespace lineage { +namespace livedisplay { +namespace V2_0 { +namespace samsung { + +static constexpr const char* kColorPath = "/sys/class/mdnie/mdnie/sensorRGB"; + +bool DisplayColorCalibration::isSupported() { + std::fstream rgb(kColorPath, rgb.in | rgb.out); + return rgb.good(); +} + +Return DisplayColorCalibration::getMaxValue() { + return 255; +} + +Return DisplayColorCalibration::getMinValue() { + return 1; +} + +Return DisplayColorCalibration::getCalibration(getCalibration_cb resultCb) { + std::vector rgb; + std::string tmp; + + if (ReadFileToString(kColorPath, &tmp)) { + std::vector colors = Split(Trim(tmp), " "); + for (const std::string& color : colors) { + rgb.push_back(std::stoi(color)); + } + } + + resultCb(rgb); + return Void(); +} + +Return DisplayColorCalibration::setCalibration(const hidl_vec& rgb) { + std::string contents; + for (const int32_t& color : rgb) { + contents += std::to_string(color) + " "; + } + return WriteStringToFile(Trim(contents), kColorPath, true); +} + +} // namespace samsung +} // namespace V2_0 +} // namespace livedisplay +} // namespace lineage +} // namespace vendor diff --git a/livedisplay/DisplayColorCalibration.h b/livedisplay/DisplayColorCalibration.h new file mode 100644 index 0000000..94188c0 --- /dev/null +++ b/livedisplay/DisplayColorCalibration.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019-2022 The LineageOS 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 +#include +#include + +namespace vendor { +namespace lineage { +namespace livedisplay { +namespace V2_0 { +namespace samsung { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +class DisplayColorCalibration : public IDisplayColorCalibration { + public: + bool isSupported(); + + // Methods from ::vendor::lineage::livedisplay::V2_0::IDisplayColorCalibration follow. + Return getMaxValue() override; + Return getMinValue() override; + Return getCalibration(getCalibration_cb resultCb) override; + Return setCalibration(const hidl_vec& rgb) override; + + // Methods from ::android::hidl::base::V1_0::IBase follow. +}; + +} // namespace samsung +} // namespace V2_0 +} // namespace livedisplay +} // namespace lineage +} // namespace vendor diff --git a/livedisplay/DisplayModes.cpp b/livedisplay/DisplayModes.cpp new file mode 100644 index 0000000..12af3dc --- /dev/null +++ b/livedisplay/DisplayModes.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2019 The LineageOS 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. + */ + +#define LOG_TAG "DisplayModesService" + +#include "DisplayModes.h" +#include +#include + +namespace vendor { +namespace lineage { +namespace livedisplay { +namespace V2_0 { +namespace samsung { + +static constexpr const char* kModePath = "/sys/class/mdnie/mdnie/mode"; +static constexpr const char* kModeMaxPath = "/sys/class/mdnie/mdnie/mode_max"; +#ifdef LIVES_IN_SYSTEM +static constexpr const char* kDefaultPath = "/data/misc/display/.displaymodedefault"; +#else +static constexpr const char* kDefaultPath = "/data/vendor/display/.displaymodedefault"; +#endif + +const std::map DisplayModes::kModeMap = { + // clang-format off + {0, "Dynamic"}, + {1, "Standard"}, + {2, "Natural"}, + {3, "Cinema"}, + {4, "Adaptive"}, + // clang-format on +}; + +DisplayModes::DisplayModes() : mDefaultModeId(4) { + std::ifstream defaultFile(kDefaultPath); + int value; + + defaultFile >> value; + LOG(DEBUG) << "Default file read result " << value << " fail " << defaultFile.fail(); + if (defaultFile.fail()) { + return; + } + + for (const auto& entry : kModeMap) { + if (value == entry.first) { + mDefaultModeId = entry.first; + break; + } + } + + setDisplayMode(mDefaultModeId, false); +} + +bool DisplayModes::isSupported() { + std::ofstream modeFile(kModePath); + return modeFile.good(); +} + +// Methods from ::vendor::lineage::livedisplay::V2_0::IDisplayModes follow. +Return DisplayModes::getDisplayModes(getDisplayModes_cb resultCb) { + std::ifstream maxModeFile(kModeMaxPath); + int value; + std::vector modes; + if (!maxModeFile.fail()) { + maxModeFile >> value; + } else { + value = kModeMap.size(); + } + for (const auto& entry : kModeMap) { + if (entry.first < value) modes.push_back({entry.first, entry.second}); + } + resultCb(modes); + return Void(); +} + +Return DisplayModes::getCurrentDisplayMode(getCurrentDisplayMode_cb resultCb) { + int32_t currentModeId = mDefaultModeId; + std::ifstream modeFile(kModePath); + int value; + modeFile >> value; + if (!modeFile.fail()) { + for (const auto& entry : kModeMap) { + if (value == entry.first) { + currentModeId = entry.first; + break; + } + } + } + resultCb({currentModeId, kModeMap.at(currentModeId)}); + return Void(); +} + +Return DisplayModes::getDefaultDisplayMode(getDefaultDisplayMode_cb resultCb) { + resultCb({mDefaultModeId, kModeMap.at(mDefaultModeId)}); + return Void(); +} + +Return DisplayModes::setDisplayMode(int32_t modeID, bool makeDefault) { + const auto iter = kModeMap.find(modeID); + if (iter == kModeMap.end()) { + return false; + } + std::ofstream modeFile(kModePath); + modeFile << iter->first; + if (modeFile.fail()) { + return false; + } + + if (makeDefault) { + std::ofstream defaultFile(kDefaultPath); + defaultFile << iter->first; + if (defaultFile.fail()) { + return false; + } + mDefaultModeId = iter->first; + } + return true; +} + +// Methods from ::android::hidl::base::V1_0::IBase follow. + +} // namespace samsung +} // namespace V2_0 +} // namespace livedisplay +} // namespace lineage +} // namespace vendor diff --git a/livedisplay/DisplayModes.h b/livedisplay/DisplayModes.h new file mode 100644 index 0000000..149edf3 --- /dev/null +++ b/livedisplay/DisplayModes.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2019 The LineageOS 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 VENDOR_LINEAGE_LIVEDISPLAY_V2_0_DISPLAYMODES_H +#define VENDOR_LINEAGE_LIVEDISPLAY_V2_0_DISPLAYMODES_H + +#include +#include +#include + +namespace vendor { +namespace lineage { +namespace livedisplay { +namespace V2_0 { +namespace samsung { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +class DisplayModes : public IDisplayModes { + public: + DisplayModes(); + bool isSupported(); + + // Methods from ::vendor::lineage::livedisplay::V2_0::IDisplayModes follow. + Return getDisplayModes(getDisplayModes_cb resultCb) override; + Return getCurrentDisplayMode(getCurrentDisplayMode_cb resultCb) override; + Return getDefaultDisplayMode(getDefaultDisplayMode_cb resultCb) override; + Return setDisplayMode(int32_t modeID, bool makeDefault) override; + + // Methods from ::android::hidl::base::V1_0::IBase follow. + private: + static const std::map kModeMap; + int32_t mDefaultModeId; +}; + +} // namespace samsung +} // namespace V2_0 +} // namespace livedisplay +} // namespace lineage +} // namespace vendor + +#endif // VENDOR_LINEAGE_LIVEDISPLAY_V2_0_DISPLAYMODES_H diff --git a/livedisplay/service.cpp b/livedisplay/service.cpp index 78a0241..c1ee7bc 100644 --- a/livedisplay/service.cpp +++ b/livedisplay/service.cpp @@ -25,7 +25,9 @@ #include #include "AdaptiveBacklight.h" +#include "DisplayModes.h" #include "SunlightEnhancement.h" +#include "DisplayColorCalibration.h" using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; @@ -34,11 +36,15 @@ using android::status_t; using android::OK; using vendor::lineage::livedisplay::V2_0::samsung::AdaptiveBacklight; +using vendor::lineage::livedisplay::V2_0::samsung::DisplayModes; using vendor::lineage::livedisplay::V2_0::samsung::SunlightEnhancement; +using vendor::lineage::livedisplay::V2_0::samsung::DisplayColorCalibration; int main() { sp adaptiveBacklight; + sp displayModes; sp sunlightEnhancement; + sp displayColorCalibration; status_t status; LOG(INFO) << "LiveDisplay HAL service is starting."; @@ -50,6 +56,11 @@ int main() { goto shutdown; } + displayModes = new DisplayModes(); + if (displayModes == nullptr) { + LOG(ERROR) << "Can not create an instance of LiveDisplay HAL DisplayModes Iface, exiting."; + goto shutdown; + } sunlightEnhancement = new SunlightEnhancement(); if (sunlightEnhancement == nullptr) { @@ -58,6 +69,12 @@ int main() { goto shutdown; } + displayColorCalibration = new DisplayColorCalibration(); + if (displayColorCalibration == nullptr) { + LOG(ERROR) << "Can not create an instance of LiveDisplay HAL DisplayColorCalibration " + "Iface, exiting."; + goto shutdown; + } configureRpcThreadpool(1, true /*callerWillJoin*/); @@ -70,6 +87,14 @@ int main() { } } + if (displayModes->isSupported()) { + status = displayModes->registerAsService(); + if (status != OK) { + LOG(ERROR) << "Could not register service for LiveDisplay HAL DisplayModes Iface (" + << status << ")"; + goto shutdown; + } + } if (sunlightEnhancement->isSupported()) { status = sunlightEnhancement->registerAsService(); @@ -81,6 +106,15 @@ int main() { } } + if (displayColorCalibration->isSupported()) { + status = displayColorCalibration->registerAsService(); + if (status != OK) { + LOG(ERROR) + << "Could not register service for LiveDisplay HAL DisplayColorCalibration Iface (" + << status << ")"; + goto shutdown; + } + } LOG(INFO) << "LiveDisplay HAL service is ready."; joinRpcThreadpool();