summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordianlujitao <dianlujitao@lineageos.org>2018-02-22 16:33:17 +0800
committerdianlujitao <dianlujitao@lineageos.org>2018-04-18 22:49:20 +0800
commit5f8e56adfbaa105a5d75e63fbefacd7cf6b46939 (patch)
treec9a083d4d1e998c734a9a239e441123c6790e3c8
parent112bc6c950f5b0df2b2cf1575629358627171545 (diff)
downloadandroid_hardware_lineage_interfaces-5f8e56adfbaa105a5d75e63fbefacd7cf6b46939.tar.gz
android_hardware_lineage_interfaces-5f8e56adfbaa105a5d75e63fbefacd7cf6b46939.tar.bz2
android_hardware_lineage_interfaces-5f8e56adfbaa105a5d75e63fbefacd7cf6b46939.zip
lineage/interfaces: Add IColor SDM backend implementation
* This code implements the LiveDisplay native interface and includes support for Qualcomm's SDM. Communication with these backends is handled via the vendor-supplied libraries, and is decoupled by using dynamic loading. * This is useful for devices which have had a full display calibration performed using vendor-supplied tools such as QDCM. * This code is based on libjni_livedisplay developed by Steve Kondik with assistance from Scott Mertz. Change-Id: I8d80ec17768e49fad1d3e30a36dd296a5bc2742e
-rw-r--r--livedisplay/1.0/default/.clang-format13
-rw-r--r--livedisplay/1.0/default/Android.bp47
-rw-r--r--livedisplay/1.0/default/controller/SDMController.cpp163
-rw-r--r--livedisplay/1.0/default/impl/SDM.cpp488
-rw-r--r--livedisplay/1.0/default/include/Color.h105
-rw-r--r--livedisplay/1.0/default/include/ColorBackend.h71
-rw-r--r--livedisplay/1.0/default/include/Types.h81
-rw-r--r--livedisplay/1.0/default/include/Utils.h57
-rw-r--r--livedisplay/1.0/default/include/controller/SDMController.h117
-rw-r--r--livedisplay/1.0/default/include/impl/SDM.h115
-rw-r--r--livedisplay/1.0/default/service.cpp69
-rw-r--r--livedisplay/1.0/default/src/Color.cpp382
-rw-r--r--livedisplay/1.0/default/src/Utils.cpp142
-rw-r--r--livedisplay/1.0/default/vendor.lineage.livedisplay@1.0-service-sdm.rc4
-rw-r--r--livedisplay/Android.bp1
15 files changed, 1855 insertions, 0 deletions
diff --git a/livedisplay/1.0/default/.clang-format b/livedisplay/1.0/default/.clang-format
new file mode 100644
index 0000000..fc4eb1b
--- /dev/null
+++ b/livedisplay/1.0/default/.clang-format
@@ -0,0 +1,13 @@
+BasedOnStyle: Google
+AllowShortBlocksOnASingleLine: false
+AllowShortFunctionsOnASingleLine: false
+
+AccessModifierOffset: -2
+ColumnLimit: 100
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+IndentWidth: 4
+PointerAlignment: Left
+TabWidth: 4
+UseTab: Never
+PenaltyExcessCharacter: 32
diff --git a/livedisplay/1.0/default/Android.bp b/livedisplay/1.0/default/Android.bp
new file mode 100644
index 0000000..39c95a4
--- /dev/null
+++ b/livedisplay/1.0/default/Android.bp
@@ -0,0 +1,47 @@
+// Copyright (C) 2017-2018 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.
+
+cc_defaults {
+ name: "livedisplay_defaults",
+ relative_install_path: "hw",
+ defaults: ["hidl_defaults"],
+ proprietary: true,
+ local_include_dirs: ["include"],
+ srcs: [
+ "service.cpp",
+ "src/Color.cpp",
+ "src/Utils.cpp"
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libutils",
+ "vendor.lineage.livedisplay@1.0_vendor",
+ ],
+}
+
+cc_binary {
+ name: "vendor.lineage.livedisplay@1.0-service-sdm",
+ init_rc: ["vendor.lineage.livedisplay@1.0-service-sdm.rc"],
+ defaults: ["livedisplay_defaults"],
+ cflags: ["-DCOLOR_BACKEND_SDM"],
+ srcs: [
+ "impl/SDM.cpp",
+ "controller/SDMController.cpp",
+ ],
+}
diff --git a/livedisplay/1.0/default/controller/SDMController.cpp b/livedisplay/1.0/default/controller/SDMController.cpp
new file mode 100644
index 0000000..d1e1949
--- /dev/null
+++ b/livedisplay/1.0/default/controller/SDMController.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 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 "controller/SDMController.h"
+
+#define LOAD_SDM_FUNCTION(name) mFn_##name = loadFunction<disp_api_##name>("disp_api_" #name);
+
+#define CLOSE_SDM_FUNCTION(name) mFn_##name = nullptr;
+
+#define FOR_EACH_FUNCTION(MACRO) \
+ MACRO(init) \
+ MACRO(deinit) \
+ MACRO(get_global_color_balance_range) \
+ MACRO(set_global_color_balance) \
+ MACRO(get_global_color_balance) \
+ MACRO(get_num_display_modes) \
+ MACRO(get_display_modes) \
+ MACRO(get_active_display_mode) \
+ MACRO(set_active_display_mode) \
+ MACRO(set_default_display_mode) \
+ MACRO(get_default_display_mode) \
+ MACRO(get_global_pa_range) \
+ MACRO(get_global_pa_config) \
+ MACRO(set_global_pa_config) \
+ MACRO(get_feature_version)
+
+#define CONTROLLER_CHECK(function, ...) \
+ if (mFn_##function == nullptr) { \
+ return -1; \
+ } \
+ int err = mFn_##function(__VA_ARGS__); \
+ if (err != 0) { \
+ return err; \
+ } \
+ return 0;
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+constexpr char SDMController::kFilename[] = "libsdm-disp-vndapis.so";
+
+SDMController::SDMController() {
+ mHandle = openlib();
+ if (mHandle != nullptr) {
+ FOR_EACH_FUNCTION(LOAD_SDM_FUNCTION)
+ }
+}
+
+shared_ptr<void> SDMController::openlib() {
+ shared_ptr<void> handle(dlopen(kFilename, RTLD_NOW), [this](void* p) {
+ FOR_EACH_FUNCTION(CLOSE_SDM_FUNCTION)
+ if (p != nullptr) {
+ int err = dlclose(p);
+ p = nullptr;
+ if (err != 0) {
+ LOG(ERROR) << "DLCLOSE failed for " << kFilename;
+ }
+ }
+ });
+ if (handle == nullptr) {
+ LOG(ERROR) << "DLOPEN failed for " << kFilename << " (" << dlerror() << ")";
+ return nullptr;
+ }
+ return handle;
+}
+
+SDMController& SDMController::getInstance() {
+ static SDMController instance{};
+ return instance;
+}
+
+int32_t SDMController::init(uint64_t* hctx, uint32_t flags) {
+ CONTROLLER_CHECK(init, hctx, flags);
+}
+
+int32_t SDMController::deinit(uint64_t hctx, uint32_t flags) {
+ CONTROLLER_CHECK(deinit, hctx, flags);
+}
+
+int32_t SDMController::get_global_color_balance_range(uint64_t hctx, uint32_t disp_id, void* range) {
+ CONTROLLER_CHECK(get_global_color_balance_range, hctx, disp_id, range);
+}
+
+int32_t SDMController::set_global_color_balance(uint64_t hctx, uint32_t disp_id, int32_t warmness,
+ uint32_t flags) {
+ CONTROLLER_CHECK(set_global_color_balance, hctx, disp_id, warmness, flags);
+}
+
+int32_t SDMController::get_global_color_balance(uint64_t hctx, uint32_t disp_id, int32_t* warmness,
+ uint32_t* flags) {
+ CONTROLLER_CHECK(get_global_color_balance, hctx, disp_id, warmness, flags);
+}
+
+int32_t SDMController::get_num_display_modes(uint64_t hctx, uint32_t disp_id, uint32_t mode_type,
+ int32_t* mode_cnt, uint32_t* flags) {
+ CONTROLLER_CHECK(get_num_display_modes, hctx, disp_id, mode_type, mode_cnt, flags);
+}
+
+int32_t SDMController::get_display_modes(uint64_t hctx, uint32_t disp_id, uint32_t mode_type,
+ void* modes, int32_t mode_cnt, uint32_t* flags) {
+ CONTROLLER_CHECK(get_display_modes, hctx, disp_id, mode_type, modes, mode_cnt, flags);
+}
+
+int32_t SDMController::get_active_display_mode(uint64_t hctx, uint32_t disp_id, int32_t* mode_id,
+ uint32_t* mask, uint32_t* flags) {
+ CONTROLLER_CHECK(get_active_display_mode, hctx, disp_id, mode_id, mask, flags);
+}
+
+int32_t SDMController::set_active_display_mode(uint64_t hctx, uint32_t disp_id, int32_t mode_id,
+ uint32_t flags) {
+ CONTROLLER_CHECK(set_active_display_mode, hctx, disp_id, mode_id, flags);
+}
+
+int32_t SDMController::set_default_display_mode(uint64_t hctx, uint32_t disp_id, int32_t mode_id,
+ uint32_t flags) {
+ CONTROLLER_CHECK(set_default_display_mode, hctx, disp_id, mode_id, flags);
+}
+
+int32_t SDMController::get_default_display_mode(uint64_t hctx, uint32_t disp_id, int32_t* mode_id,
+ uint32_t* flags) {
+ CONTROLLER_CHECK(get_default_display_mode, hctx, disp_id, mode_id, flags);
+}
+
+int32_t SDMController::get_global_pa_range(uint64_t hctx, uint32_t disp_id, void* range) {
+ CONTROLLER_CHECK(get_global_pa_range, hctx, disp_id, range);
+}
+
+int32_t SDMController::get_global_pa_config(uint64_t hctx, uint32_t disp_id, uint32_t* enable,
+ void* cfg) {
+ CONTROLLER_CHECK(get_global_pa_config, hctx, disp_id, enable, cfg);
+}
+
+int32_t SDMController::set_global_pa_config(uint64_t hctx, uint32_t disp_id, uint32_t enable,
+ void* cfg) {
+ CONTROLLER_CHECK(set_global_pa_config, hctx, disp_id, enable, cfg);
+}
+
+int32_t SDMController::get_feature_version(uint64_t hctx, uint32_t feature_id, void* ver,
+ uint32_t* flags) {
+ CONTROLLER_CHECK(get_feature_version, hctx, feature_id, ver, flags);
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
diff --git a/livedisplay/1.0/default/impl/SDM.cpp b/livedisplay/1.0/default/impl/SDM.cpp
new file mode 100644
index 0000000..975ae98
--- /dev/null
+++ b/livedisplay/1.0/default/impl/SDM.cpp
@@ -0,0 +1,488 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ * Copyright (C) 2017-2018 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_NDEBUG 0
+
+#define LOG_TAG "LiveDisplay-SDM"
+
+#include <android-base/properties.h>
+
+#include "Utils.h"
+#include "impl/SDM.h"
+
+#define DPPS_BUF_SIZE 64
+
+#define FEATURE_VER_SW_PA_API 0x00000001
+#define FEATURE_VER_SW_COLORBAL_API 0x00000003
+#define FEATURE_VER_SW_SAVEMODES_API 0x00000004
+
+#define FOSS_ON "foss:on"
+#define FOSS_OFF "foss:off"
+
+// For use when only sysfs modes are available
+#define STANDARD_NODE_ID 600
+
+#define SRGB_NODE "/sys/class/graphics/fb0/srgb"
+#define SRGB_NODE_ID 601
+
+#define DCI_P3_NODE "/sys/class/graphics/fb0/dci_p3"
+#define DCI_P3_NODE_ID 602
+
+#define PRIV_MODE_FLAG_SDM 1
+#define PRIV_MODE_FLAG_SYSFS 2
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::BAD_VALUE;
+using ::android::OK;
+
+status_t SDM::initialize() {
+ status_t rc = NO_INIT;
+
+ rc = SDMController::getInstance().init(&mHandle, 0);
+ if (rc != OK) {
+ return rc;
+ }
+
+ mActiveModeId = -1;
+
+ if (hasFeature(Feature::DISPLAY_MODES)) {
+ rc = saveInitialDisplayMode();
+ if (rc != OK) {
+ LOG(ERROR) << "Failed to save initial display mode! err=" << rc;
+ return rc;
+ }
+ sp<disp_mode> defMode = getDefaultDisplayMode();
+ if (defMode != nullptr) {
+ setDisplayMode(defMode->id, false);
+ }
+ }
+
+ mFOSSEnabled = stol(android::base::GetProperty("ro.qualcomm.foss", "0")) > 0;
+
+ return OK;
+}
+
+status_t SDM::deinitialize() {
+ SDMController::getInstance().deinit(mHandle, 0);
+ mHandle = -1;
+ return OK;
+}
+
+uint32_t SDM::getNumSDMDisplayModes() {
+ uint32_t flags = 0;
+ int32_t count = 0;
+ if (SDMController::getInstance().get_num_display_modes(mHandle, 0, 0, &count, &flags)) {
+ count = 0;
+ }
+ return count;
+}
+
+uint32_t SDM::getNumDisplayModes() {
+ int32_t count = getNumSDMDisplayModes();
+ if (getLocalSRGBMode() != nullptr) {
+ count++;
+ }
+ if (getLocalDCIP3Mode() != nullptr) {
+ count++;
+ }
+ return count;
+}
+
+sp<disp_mode> SDM::getDisplayModeById(int32_t id) {
+ vector<sp<disp_mode>> profiles;
+ status_t rc = getDisplayModes(profiles);
+ if (rc == OK) {
+ for (const auto& mode : profiles) {
+ if (id == mode->id) {
+ return mode;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+status_t SDM::setModeState(sp<disp_mode> mode, bool state) {
+ int32_t id = 0;
+
+ if (mode->privFlags == PRIV_MODE_FLAG_SYSFS) {
+ if (mode->id != STANDARD_NODE_ID) {
+ LOG(VERBOSE) << "sysfs node: " << mode->privData << " state=" << state;
+ return Utils::writeInt(mode->privData.c_str(), state ? 1 : 0);
+ } else {
+ // NOOP
+ return OK;
+ }
+ } else if (mode->privFlags == PRIV_MODE_FLAG_SDM) {
+ if (state) {
+ return SDMController::getInstance().set_active_display_mode(mHandle, 0, mode->id, 0);
+ } else {
+ if (Utils::readInitialModeId(&id) == OK) {
+ LOG(VERBOSE) << "set sdm mode to default: id" << id;
+ return SDMController::getInstance().set_active_display_mode(mHandle, 0, id, 0);
+ }
+ }
+ }
+ return BAD_VALUE;
+}
+
+status_t SDM::getDisplayModes(vector<sp<disp_mode>>& profiles) {
+ status_t rc = OK;
+
+ uint32_t count = getNumDisplayModes();
+ if (!count) return rc;
+
+ uint32_t sdm_count = getNumSDMDisplayModes();
+
+ if (sdm_count == 0) {
+ // sysfs only case, create a dummy standard mode
+ const sp<disp_mode> m = new disp_mode;
+ m->id = STANDARD_NODE_ID;
+ m->name = "standard";
+ m->privFlags = PRIV_MODE_FLAG_SYSFS;
+ m->privData = "";
+ profiles.push_back(m);
+ } else {
+ struct sdm_mode {
+ int32_t id;
+ int32_t type;
+ int32_t len;
+ char* name;
+ };
+
+ sdm_mode* tmp = new sdm_mode[sdm_count];
+ memset(tmp, 0, sizeof(sdm_mode) * sdm_count);
+ for (uint32_t i = 0; i < sdm_count; i++) {
+ tmp[i].id = -1;
+ tmp[i].name = new char[128];
+ tmp[i].len = 128;
+ }
+
+ uint32_t flags = 0;
+ rc = SDMController::getInstance().get_display_modes(mHandle, 0, 0, tmp, sdm_count, &flags);
+ if (rc == 0) {
+ for (uint32_t i = 0; i < sdm_count; i++) {
+ const sp<disp_mode> m = new disp_mode;
+ m->id = tmp[i].id;
+ m->name = tmp[i].name;
+ m->privFlags = PRIV_MODE_FLAG_SDM;
+ profiles.push_back(m);
+ }
+ }
+ for (uint32_t i = 0; i < sdm_count; i++) delete tmp[i].name;
+ delete[] tmp;
+ }
+
+ sp<disp_mode> srgb = getLocalSRGBMode();
+ sp<disp_mode> dci_p3 = getLocalDCIP3Mode();
+ if (srgb != nullptr) {
+ profiles.push_back(srgb);
+ }
+ if (dci_p3 != nullptr) {
+ profiles.push_back(dci_p3);
+ }
+
+ return rc;
+}
+
+sp<disp_mode> SDM::getCurrentDisplayMode() {
+ return getDisplayModeById(mActiveModeId);
+}
+
+sp<disp_mode> SDM::getDefaultDisplayMode() {
+ int32_t id = 0;
+ if (Utils::readLocalModeId(&id) == OK && id >= 0) {
+ return getDisplayModeById(id);
+ }
+ if (Utils::readInitialModeId(&id) == OK && id >= 0) {
+ return getDisplayModeById(id);
+ }
+ return nullptr;
+}
+
+sp<disp_mode> SDM::getLocalSRGBMode() {
+ char path[PATH_MAX];
+ sprintf(path, "%s", SRGB_NODE);
+
+ if (access(path, W_OK) != 0) {
+ return nullptr;
+ }
+ sp<disp_mode> m = new disp_mode;
+ m->id = SRGB_NODE_ID;
+ m->name = "srgb";
+ m->privFlags = PRIV_MODE_FLAG_SYSFS;
+ m->privData = path;
+ return m;
+}
+
+sp<disp_mode> SDM::getLocalDCIP3Mode() {
+ char path[PATH_MAX];
+ sprintf(path, "%s", DCI_P3_NODE);
+
+ if (access(path, W_OK) != 0) {
+ return nullptr;
+ }
+ sp<disp_mode> m = new disp_mode;
+ m->id = DCI_P3_NODE_ID;
+ m->name = "dci_p3";
+ m->privFlags = PRIV_MODE_FLAG_SYSFS;
+ m->privData = path;
+ return m;
+}
+
+status_t SDM::getPictureAdjustmentRanges(HSICRanges& ranges) {
+ hsic_ranges r;
+ memset(&r, 0, sizeof(struct hsic_ranges));
+
+ status_t rc = SDMController::getInstance().get_global_pa_range(mHandle, 0, &r);
+ if (rc == OK) {
+ ranges.hue.min = r.hue.min;
+ ranges.hue.max = r.hue.max;
+ ranges.hue.step = r.hue.step;
+ ranges.saturation.min = r.saturation.min;
+ ranges.saturation.max = r.saturation.max;
+ ranges.saturation.step = r.saturation.step;
+ ranges.intensity.min = r.intensity.min;
+ ranges.intensity.max = r.intensity.max;
+ ranges.intensity.step = r.intensity.step;
+ ranges.contrast.min = r.contrast.min;
+ ranges.contrast.max = r.contrast.max;
+ ranges.contrast.step = r.contrast.step;
+ ranges.saturationThreshold.min = r.saturationThreshold.min;
+ ranges.saturationThreshold.max = r.saturationThreshold.max;
+ ranges.saturationThreshold.step = r.saturationThreshold.step;
+ }
+ return rc;
+}
+
+bool SDM::hasFeature(Feature feature) {
+ uint32_t id = 0, flags = 0;
+ struct version {
+ uint8_t x, y;
+ uint16_t z;
+ };
+ version v;
+
+ switch (feature) {
+ case Feature::DISPLAY_MODES:
+ id = FEATURE_VER_SW_SAVEMODES_API;
+ break;
+ case Feature::COLOR_BALANCE:
+ id = FEATURE_VER_SW_COLORBAL_API;
+ break;
+ case Feature::PICTURE_ADJUSTMENT:
+ id = FEATURE_VER_SW_PA_API;
+ case Feature::ADAPTIVE_BACKLIGHT:
+ if (mFOSSEnabled) {
+ return true;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ if (SDMController::getInstance().get_feature_version(mHandle, id, &v, &flags) != OK) {
+ return false;
+ }
+
+ if (v.x <= 0 && v.y <= 0 && v.z <= 0) {
+ return false;
+ }
+
+ // Color balance depends on calibration data in SDM
+ if (feature == Feature::DISPLAY_MODES || feature == Feature::COLOR_BALANCE) {
+ if (getNumDisplayModes() > 0) {
+ // make sure the range isn't zero
+ if (feature == Feature::COLOR_BALANCE) {
+ Range r;
+ if (getColorBalanceRange(r) == OK && isNonZero(r)) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ } else if (feature == Feature::PICTURE_ADJUSTMENT) {
+ HSICRanges r;
+ if (getPictureAdjustmentRanges(r) == OK && r.isValid()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+status_t SDM::saveInitialDisplayMode() {
+ int32_t id = 0;
+ uint32_t flags = 0;
+ if (Utils::readInitialModeId(&id) != OK || id < 0) {
+ if (SDMController::getInstance().get_default_display_mode(mHandle, 0, &id, &flags) == OK &&
+ id >= 0) {
+ return Utils::writeInitialModeId(id);
+ } else {
+ return Utils::writeInitialModeId(0);
+ }
+ }
+ return OK;
+}
+
+status_t SDM::getColorBalanceRange(Range& range) {
+ status_t rc = SDMController::getInstance().get_global_color_balance_range(mHandle, 0, &range);
+ LOG(VERBOSE) << "getColorBalanceRange: min=" << range.min << " max=" << range.max
+ << " step=" << range.step;
+ return rc;
+}
+
+status_t SDM::getPictureAdjustment(HSIC& hsic) {
+ uint32_t enable = 0;
+ hsic_config config;
+ memset(&config, 0, sizeof(struct hsic_config));
+
+ status_t rc = SDMController::getInstance().get_global_pa_config(mHandle, 0, &enable, &config);
+ if (rc == OK) {
+ hsic.hue = config.data.hue;
+ hsic.saturation = config.data.saturation;
+ hsic.intensity = config.data.intensity;
+ hsic.contrast = config.data.contrast;
+ hsic.saturationThreshold = config.data.saturationThreshold;
+ }
+ return rc;
+}
+
+status_t SDM::setDisplayMode(int32_t modeID, bool makeDefault) {
+ status_t rc = OK;
+
+ if (modeID == mActiveModeId) {
+ return rc;
+ }
+
+ sp<disp_mode> mode = getDisplayModeById(modeID);
+ if (mode == nullptr) {
+ return BAD_VALUE;
+ }
+
+ LOG(DEBUG) << "setDisplayMode: current mode=" << mActiveModeId;
+
+ if (mActiveModeId >= 0) {
+ sp<disp_mode> oldMode = getCurrentDisplayMode();
+ LOG(DEBUG) << "setDisplayMode: oldMode=" << oldMode->id << " flags=" << oldMode->privFlags;
+ if (oldMode->privFlags == PRIV_MODE_FLAG_SYSFS || mode->privFlags == PRIV_MODE_FLAG_SYSFS) {
+ LOG(DEBUG) << "disabling old mode";
+ rc = setModeState(oldMode, false);
+ if (rc != OK) {
+ LOG(ERROR) << "Failed to disable previous mode! err=" << rc;
+ return rc;
+ }
+ }
+ }
+
+ rc = setModeState(mode, true);
+ if (rc == OK) {
+ mActiveModeId = mode->id;
+ if (makeDefault) {
+ rc = Utils::writeLocalModeId(mode->id);
+ if (rc != OK) {
+ LOG(ERROR) << "failed to save mode! err=" << rc;
+ return rc;
+ }
+ if (mode->privFlags == PRIV_MODE_FLAG_SDM) {
+ rc = SDMController::getInstance().set_default_display_mode(mHandle, 0, mode->id, 0);
+ if (rc != OK) {
+ LOG(ERROR) << "failed to save mode! err=" << rc;
+ return rc;
+ }
+ }
+ }
+ HSIC tmp;
+ rc = getPictureAdjustment(tmp);
+ if (rc != OK) {
+ LOG(ERROR) << "failed to retrieve picture adjustment after mode setting!";
+ } else {
+ LOG(DEBUG) << "new default PA: " << tmp.hue << " " << tmp.saturation << " "
+ << tmp.intensity << " " << tmp.contrast << " " << tmp.saturationThreshold;
+ mDefaultPictureAdjustment = tmp;
+ }
+ } else {
+ LOG(ERROR) << "Failed to setModeState! err=" << rc;
+ return rc;
+ }
+
+ LOG(DEBUG) << "setDisplayMode: " << modeID << " default: " << makeDefault
+ << " flags: " << mode->privFlags;
+ return OK;
+}
+
+status_t SDM::setAdaptiveBacklightEnabled(bool enabled) {
+ status_t rc = NO_INIT;
+ if (enabled == mCachedFOSSStatus) {
+ return OK;
+ }
+ char* buf = new char[DPPS_BUF_SIZE];
+ sprintf(buf, "%s", enabled ? FOSS_ON : FOSS_OFF);
+ if (Utils::sendDPPSCommand(buf, DPPS_BUF_SIZE) == OK) {
+ if (strncmp(buf, "Success", 7) == 0) {
+ rc = OK;
+ mCachedFOSSStatus = enabled;
+ }
+ }
+ delete[] buf;
+ return rc;
+}
+
+bool SDM::isAdaptiveBacklightEnabled() {
+ return mCachedFOSSStatus;
+}
+
+int32_t SDM::getColorBalance() {
+ int32_t value = -1;
+ uint32_t flags = 0;
+ if (SDMController::getInstance().get_global_color_balance(mHandle, 0, &value, &flags) != 0) {
+ value = 0;
+ }
+ return value;
+}
+
+status_t SDM::setColorBalance(int32_t balance) {
+ return SDMController::getInstance().set_global_color_balance(mHandle, 0, balance, 0);
+}
+
+status_t SDM::setPictureAdjustment(const HSIC& hsic) {
+ hsic_config config;
+ memset(&config, 0, sizeof(struct hsic_config));
+ config.data.hue = hsic.hue;
+ config.data.saturation = hsic.saturation;
+ config.data.intensity = hsic.intensity;
+ config.data.contrast = hsic.contrast;
+ config.data.saturationThreshold = hsic.saturationThreshold;
+
+ return SDMController::getInstance().set_global_pa_config(mHandle, 0, 1, &config);
+}
+
+HSIC SDM::getDefaultPictureAdjustment() {
+ return mDefaultPictureAdjustment;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
diff --git a/livedisplay/1.0/default/include/Color.h b/livedisplay/1.0/default/include/Color.h
new file mode 100644
index 0000000..75d53cc
--- /dev/null
+++ b/livedisplay/1.0/default/include/Color.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ * Copyright (C) 2017-2018 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_V1_0_COLOR_H
+#define VENDOR_LINEAGE_LIVEDISPLAY_V1_0_COLOR_H
+
+#include <utils/Mutex.h>
+#include <vendor/lineage/livedisplay/1.0/IColor.h>
+
+#include "ColorBackend.h"
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::Mutex;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+using ::vendor::lineage::livedisplay::V1_0::IColor;
+
+class Color : public IColor {
+ public:
+ static sp<Color> getInstance();
+
+ Return<Features> getSupportedFeatures() override;
+
+ Return<void> getDisplayModes(getDisplayModes_cb _hidl_cb) override;
+ Return<void> getCurrentDisplayMode(getCurrentDisplayMode_cb _hidl_cb) override;
+ Return<void> getDefaultDisplayMode(getDefaultDisplayMode_cb _hidl_cb) override;
+ Return<bool> setDisplayMode(int32_t modeID, bool makeDefault) override;
+
+ Return<bool> setAdaptiveBacklightEnabled(bool enabled) override;
+ Return<bool> isAdaptiveBacklightEnabled() override;
+
+ Return<bool> setOutdoorModeEnabled(bool enabled) override;
+ Return<bool> isOutdoorModeEnabled() override;
+
+ Return<void> getColorBalanceRange(getColorBalanceRange_cb _hidl_cb) override;
+ Return<int32_t> getColorBalance() override;
+ Return<bool> setColorBalance(int32_t value) override;
+
+ Return<bool> setPictureAdjustment(const HSIC& hsic) override;
+ Return<void> getPictureAdjustment(getPictureAdjustment_cb _hidl_cb) override;
+ Return<void> getDefaultPictureAdjustment(getDefaultPictureAdjustment_cb _hidl_cb) override;
+
+ Return<void> getHueRange(getHueRange_cb _hidl_cb) override;
+ Return<void> getSaturationRange(getSaturationRange_cb _hidl_cb) override;
+ Return<void> getIntensityRange(getIntensityRange_cb _hidl_cb) override;
+ Return<void> getContrastRange(getContrastRange_cb _hidl_cb) override;
+ Return<void> getSaturationThresholdRange(getSaturationThresholdRange_cb _hidl_cb) override;
+
+ ~Color();
+
+ private:
+ bool connect();
+ void reset();
+
+ Color();
+ static sp<Color> sInstance;
+
+ uint32_t mFeatures;
+ bool mConnected;
+
+ bool check(Feature f) {
+ return connect() && (mFeatures & (uint32_t)f);
+ }
+ void error(const char* msg = NULL);
+
+ DisplayMode modePointerToObj(sp<disp_mode> mode);
+ DisplayMode invalidDisplayMode();
+
+ void addFeature(Feature f) {
+ mFeatures |= (uint32_t)f;
+ };
+
+ sp<ColorBackend> mBackend;
+ Mutex mLock;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
+
+#endif // VENDOR_LINEAGE_LIVEDISPLAY_V1_0_COLOR_H
diff --git a/livedisplay/1.0/default/include/ColorBackend.h b/livedisplay/1.0/default/include/ColorBackend.h
new file mode 100644
index 0000000..2bf4f9f
--- /dev/null
+++ b/livedisplay/1.0/default/include/ColorBackend.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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_V1_0_COLORBACKEND_H
+#define VENDOR_LINEAGE_LIVEDISPLAY_V1_0_COLORBACKEND_H
+
+#include <vector>
+
+#include "Types.h"
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::status_t;
+
+using std::vector;
+
+class ColorBackend : public android::RefBase {
+ public:
+ virtual status_t setAdaptiveBacklightEnabled(bool enabled) = 0;
+ virtual bool isAdaptiveBacklightEnabled() = 0;
+
+ virtual status_t setOutdoorModeEnabled(bool enabled) = 0;
+ virtual bool isOutdoorModeEnabled() = 0;
+
+ virtual status_t getColorBalanceRange(Range& range) = 0;
+ virtual status_t setColorBalance(int32_t balance) = 0;
+ virtual int32_t getColorBalance() = 0;
+
+ virtual status_t getDisplayModes(vector<sp<disp_mode>>& profiles) = 0;
+ virtual status_t setDisplayMode(int32_t modeID, bool makeDefault) = 0;
+ virtual sp<disp_mode> getCurrentDisplayMode() = 0;
+ virtual sp<disp_mode> getDefaultDisplayMode() = 0;
+
+ virtual status_t getPictureAdjustmentRanges(HSICRanges& ranges) = 0;
+ virtual status_t getPictureAdjustment(HSIC& hsic) = 0;
+ virtual HSIC getDefaultPictureAdjustment() = 0;
+ virtual status_t setPictureAdjustment(const HSIC& hsic) = 0;
+
+ virtual status_t initialize() = 0;
+ virtual status_t deinitialize() = 0;
+ virtual bool hasFeature(Feature feature) = 0;
+
+ virtual ~ColorBackend() {
+ }
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
+
+#endif // VENDOR_LINEAGE_LIVEDISPLAY_V1_0_COLORBACKEND_H
diff --git a/livedisplay/1.0/default/include/Types.h b/livedisplay/1.0/default/include/Types.h
new file mode 100644
index 0000000..e2db6d7
--- /dev/null
+++ b/livedisplay/1.0/default/include/Types.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 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_V1_0_TYPES_H
+#define VENDOR_LINEAGE_LIVEDISPLAY_V1_0_TYPES_H
+
+#include <utils/RefBase.h>
+#include <vendor/lineage/livedisplay/1.0/IColor.h>
+#include <string>
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using std::string;
+
+struct disp_mode : public android::RefBase {
+ int32_t id;
+ string name;
+
+ uint32_t privFlags;
+ string privData;
+
+ disp_mode() : id(-1) {
+ }
+};
+
+inline bool isNonZero(Range r) {
+ return r.min != 0 || r.max != 0;
+}
+
+inline bool isNonZero(FloatRange r) {
+ return r.min != 0.f || r.max != 0.f;
+}
+
+struct HSICRanges {
+ HSICRanges() {
+ }
+ HSICRanges(Range _hue, FloatRange _saturation, FloatRange _intensity, FloatRange _contrast,
+ FloatRange _saturationThreshold)
+ : hue(_hue),
+ saturation(_saturation),
+ intensity(_intensity),
+ contrast(_contrast),
+ saturationThreshold(_saturationThreshold) {
+ }
+
+ Range hue;
+ FloatRange saturation;
+ FloatRange intensity;
+ FloatRange contrast;
+ FloatRange saturationThreshold;
+
+ bool isValid() {
+ return isNonZero(hue) && isNonZero(saturation) && isNonZero(intensity) &&
+ isNonZero(contrast);
+ }
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
+
+#endif // VENDOR_LINEAGE_LIVEDISPLAY_V1_0_TYPES_H
diff --git a/livedisplay/1.0/default/include/Utils.h b/livedisplay/1.0/default/include/Utils.h
new file mode 100644
index 0000000..2833d52
--- /dev/null
+++ b/livedisplay/1.0/default/include/Utils.h
@@ -0,0 +1,57 @@
+/*
+** Copyright 2016, The CyanogenMod Project
+** 2017-2018, 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_V1_0_UTILS_H
+#define VENDOR_LINEAGE_LIVEDISPLAY_V1_0_UTILS_H
+
+#include <stdlib.h>
+#include <utils/Errors.h>
+
+using ::android::status_t;
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+class Utils {
+ public:
+ static status_t readInt(const char* node, int32_t* value);
+
+ static status_t writeInt(const char* node, int32_t value);
+
+ static status_t sendDPPSCommand(char* buf, size_t len);
+
+ static status_t exists(const char* node);
+
+ static status_t writeLocalModeId(int32_t id);
+
+ static status_t readLocalModeId(int32_t* id);
+
+ static status_t writeInitialModeId(int32_t id);
+
+ static status_t readInitialModeId(int32_t* id);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
+
+#endif // VENDOR_LINEAGE_LIVEDISPLAY_V1_0_UTILS_H
diff --git a/livedisplay/1.0/default/include/controller/SDMController.h b/livedisplay/1.0/default/include/controller/SDMController.h
new file mode 100644
index 0000000..d3557b9
--- /dev/null
+++ b/livedisplay/1.0/default/include/controller/SDMController.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2018 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_V1_0_SDMCONTROLLER_H
+#define VENDOR_LINEAGE_LIVEDISPLAY_V1_0_SDMCONTROLLER_H
+
+#include <android-base/logging.h>
+#include <dlfcn.h>
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::std::shared_ptr;
+
+class SDMController {
+ private:
+ SDMController();
+ template <typename Function>
+ Function loadFunction(const char* name) {
+ void* fn = dlsym(mHandle.get(), name);
+ if (fn == nullptr) {
+ LOG(ERROR) << "loadFunction -- failed to load function " << name;
+ }
+ return reinterpret_cast<Function>(fn);
+ }
+
+ shared_ptr<void> openlib();
+
+ public:
+ static SDMController& getInstance();
+
+ int32_t init(uint64_t* hctx, uint32_t flags);
+ int32_t deinit(uint64_t hctx, uint32_t flags);
+ int32_t get_global_color_balance_range(uint64_t hctx, uint32_t disp_id, void* range);
+ int32_t set_global_color_balance(uint64_t hctx, uint32_t disp_id, int32_t warmness,
+ uint32_t flags);
+ int32_t get_global_color_balance(uint64_t hctx, uint32_t disp_id, int32_t* warmness,
+ uint32_t* flags);
+ int32_t get_num_display_modes(uint64_t hctx, uint32_t disp_id, uint32_t mode_type,
+ int32_t* mode_cnt, uint32_t* flags);
+ int32_t get_display_modes(uint64_t hctx, uint32_t disp_id, uint32_t mode_type, void* modes,
+ int32_t mode_cnt, uint32_t* flags);
+ int32_t get_active_display_mode(uint64_t hctx, uint32_t disp_id, int32_t* mode_id,
+ uint32_t* mask, uint32_t* flags);
+ int32_t set_active_display_mode(uint64_t hctx, uint32_t disp_id, int32_t mode_id,
+ uint32_t flags);
+ int32_t set_default_display_mode(uint64_t hctx, uint32_t disp_id, int32_t mode_id,
+ uint32_t flags);
+ int32_t get_default_display_mode(uint64_t hctx, uint32_t disp_id, int32_t* mode_id,
+ uint32_t* flags);
+ int32_t get_global_pa_range(uint64_t hctx, uint32_t disp_id, void* range);
+ int32_t get_global_pa_config(uint64_t hctx, uint32_t disp_id, uint32_t* enable, void* cfg);
+ int32_t set_global_pa_config(uint64_t hctx, uint32_t disp_id, uint32_t enable, void* cfg);
+ int32_t get_feature_version(uint64_t hctx, uint32_t feature_id, void* ver, uint32_t* flags);
+
+ private:
+ typedef int32_t (*disp_api_init)(uint64_t*, uint32_t);
+ typedef int32_t (*disp_api_deinit)(uint64_t, uint32_t);
+ typedef int32_t (*disp_api_get_global_color_balance_range)(uint64_t, uint32_t, void*);
+ typedef int32_t (*disp_api_set_global_color_balance)(uint64_t, uint32_t, int32_t, uint32_t);
+ typedef int32_t (*disp_api_get_global_color_balance)(uint64_t, uint32_t, int32_t*, uint32_t*);
+ typedef int32_t (*disp_api_get_num_display_modes)(uint64_t, uint32_t, int32_t, int32_t*,
+ uint32_t*);
+ typedef int32_t (*disp_api_get_display_modes)(uint64_t, uint32_t, int32_t, void*, int32_t,
+ uint32_t*);
+ typedef int32_t (*disp_api_get_active_display_mode)(uint64_t, uint32_t, int32_t*, uint32_t*,
+ uint32_t*);
+ typedef int32_t (*disp_api_set_active_display_mode)(uint64_t, uint32_t, int32_t, uint32_t);
+ typedef int32_t (*disp_api_set_default_display_mode)(uint64_t, uint32_t, int32_t, uint32_t);
+ typedef int32_t (*disp_api_get_default_display_mode)(uint64_t, uint32_t, int32_t*, uint32_t*);
+ typedef int32_t (*disp_api_get_global_pa_range)(uint64_t, uint32_t, void*);
+ typedef int32_t (*disp_api_get_global_pa_config)(uint64_t, uint32_t, uint32_t*, void*);
+ typedef int32_t (*disp_api_set_global_pa_config)(uint64_t, uint32_t, uint32_t, void*);
+ typedef int32_t (*disp_api_get_feature_version)(uint64_t, uint32_t, void*, uint32_t*);
+
+ static const char kFilename[];
+ shared_ptr<void> mHandle;
+ disp_api_init mFn_init;
+ disp_api_deinit mFn_deinit;
+ disp_api_get_global_color_balance_range mFn_get_global_color_balance_range;
+ disp_api_set_global_color_balance mFn_set_global_color_balance;
+ disp_api_get_global_color_balance mFn_get_global_color_balance;
+ disp_api_get_num_display_modes mFn_get_num_display_modes;
+ disp_api_get_display_modes mFn_get_display_modes;
+ disp_api_get_active_display_mode mFn_get_active_display_mode;
+ disp_api_set_active_display_mode mFn_set_active_display_mode;
+ disp_api_set_default_display_mode mFn_set_default_display_mode;
+ disp_api_get_default_display_mode mFn_get_default_display_mode;
+ disp_api_get_global_pa_range mFn_get_global_pa_range;
+ disp_api_get_global_pa_config mFn_get_global_pa_config;
+ disp_api_set_global_pa_config mFn_set_global_pa_config;
+ disp_api_get_feature_version mFn_get_feature_version;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
+
+#endif // VENDOR_LINEAGE_LIVEDISPLAY_V1_0_SDMCONTROLLER_H
diff --git a/livedisplay/1.0/default/include/impl/SDM.h b/livedisplay/1.0/default/include/impl/SDM.h
new file mode 100644
index 0000000..cb419e2
--- /dev/null
+++ b/livedisplay/1.0/default/include/impl/SDM.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod Project
+ * Copyright (C) 2017-2018 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_V1_0_SDM_H
+#define VENDOR_LINEAGE_LIVEDISPLAY_V1_0_SDM_H
+
+#include "ColorBackend.h"
+#include "controller/SDMController.h"
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::NO_INIT;
+
+using ::vendor::lineage::livedisplay::V1_0::IColor;
+
+struct hsic_int_range {
+ int32_t max;
+ int32_t min;
+ uint32_t step;
+};
+
+struct hsic_float_range {
+ float max;
+ float min;
+ float step;
+};
+
+struct hsic_ranges {
+ uint32_t flags;
+ struct hsic_int_range hue;
+ struct hsic_float_range saturation;
+ struct hsic_float_range intensity;
+ struct hsic_float_range contrast;
+ struct hsic_float_range saturationThreshold;
+};
+
+struct hsic_config {
+ uint32_t flags;
+ HSIC data;
+};
+
+class SDM : public ColorBackend {
+ public:
+ virtual status_t getDisplayModes(vector<sp<disp_mode>>& profiles) override;
+ virtual sp<disp_mode> getCurrentDisplayMode() override;
+ virtual sp<disp_mode> getDefaultDisplayMode() override;
+ virtual status_t setDisplayMode(int32_t modeID, bool makeDefault) override;
+
+ virtual status_t setAdaptiveBacklightEnabled(bool enabled) override;
+ virtual bool isAdaptiveBacklightEnabled() override;
+
+ virtual status_t setOutdoorModeEnabled(bool /* enabled */) override {
+ return NO_INIT;
+ }
+ virtual bool isOutdoorModeEnabled() override {
+ return false;
+ }
+
+ virtual status_t getColorBalanceRange(Range& range) override;
+ virtual int32_t getColorBalance() override;
+ virtual status_t setColorBalance(int32_t balance) override;
+
+ virtual status_t getPictureAdjustmentRanges(HSICRanges& ranges) override;
+ virtual status_t setPictureAdjustment(const HSIC& hsic) override;
+ virtual status_t getPictureAdjustment(HSIC& hsic) override;
+ virtual HSIC getDefaultPictureAdjustment() override;
+
+ virtual bool hasFeature(Feature f);
+ virtual status_t initialize();
+ virtual status_t deinitialize();
+
+ private:
+ status_t saveInitialDisplayMode();
+ uint32_t getNumDisplayModes();
+ uint32_t getNumSDMDisplayModes();
+
+ sp<disp_mode> getDisplayModeById(int32_t id);
+ status_t setModeState(sp<disp_mode> mode, bool state);
+ sp<disp_mode> getLocalSRGBMode();
+ sp<disp_mode> getLocalDCIP3Mode();
+
+ uint64_t mHandle;
+ bool mFOSSEnabled;
+ bool mCachedFOSSStatus;
+ int32_t mActiveModeId;
+
+ HSIC mDefaultPictureAdjustment;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
+
+#endif // VENDOR_LINEAGE_LIVEDISPLAY_V1_0_SDM_H
diff --git a/livedisplay/1.0/default/service.cpp b/livedisplay/1.0/default/service.cpp
new file mode 100644
index 0000000..1a082db
--- /dev/null
+++ b/livedisplay/1.0/default/service.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017-2018 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.
+ */
+
+#ifdef COLOR_BACKEND_SDM
+#define LOG_TAG "vendor.lineage.livedisplay@1.0-service-sdm"
+#else
+#error "Color backend undefined!"
+#endif
+
+#include <android-base/logging.h>
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "Color.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::OK;
+using android::sp;
+using android::status_t;
+
+using ::vendor::lineage::livedisplay::V1_0::IColor;
+using ::vendor::lineage::livedisplay::V1_0::implementation::Color;
+
+int main() {
+ status_t status;
+ android::sp<IColor> service = nullptr;
+
+ LOG(INFO) << "LiveDisplay HAL service is starting.";
+
+ // The LiveDisplay HAL may communicate to other vendor components via /dev/vndbinder
+ android::ProcessState::initWithDriver("/dev/vndbinder");
+
+ service = Color::getInstance();
+ if (service == nullptr) {
+ LOG(ERROR) << "Can not create an instance of LiveDisplay HAL Iface, exiting.";
+ goto shutdown;
+ }
+
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+ status = service->registerAsService();
+ if (status != OK) {
+ LOG(ERROR) << "Could not register service for LiveDisplay HAL Iface (" << status << ")";
+ goto shutdown;
+ }
+
+ LOG(INFO) << "LiveDisplay HAL service is ready.";
+ joinRpcThreadpool();
+ // Should not pass this line
+
+shutdown:
+ // In normal operation, we don't expect the thread pool to exit
+ LOG(ERROR) << "LiveDisplay HAL service is shutting down.";
+ return 1;
+}
diff --git a/livedisplay/1.0/default/src/Color.cpp b/livedisplay/1.0/default/src/Color.cpp
new file mode 100644
index 0000000..0345ecd
--- /dev/null
+++ b/livedisplay/1.0/default/src/Color.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2017-2018 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_NDEBUG 0
+
+#define LOG_TAG "LiveDisplay-HIDL"
+
+#include "Color.h"
+
+#ifdef COLOR_BACKEND_SDM
+#include "impl/SDM.h"
+#else
+#error "Color backend undefined!"
+#endif
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::NO_INIT;
+using ::android::OK;
+
+sp<Color> Color::sInstance = nullptr;
+
+Color::Color() : mConnected(false), mBackend(nullptr) {
+#ifdef COLOR_BACKEND_SDM
+ mBackend = new SDM();
+#endif
+ LOG(DEBUG) << "Loaded LiveDisplay native interface";
+}
+
+Color::~Color() {
+ reset();
+}
+
+void Color::reset() {
+ if (mConnected) {
+ mBackend->deinitialize();
+ }
+ mFeatures = 0;
+ mConnected = false;
+}
+
+void Color::error(const char* msg) {
+ if (msg != NULL) {
+ LOG(ERROR) << msg;
+ }
+
+ reset();
+}
+
+bool Color::connect() {
+ if (mConnected) {
+ return true;
+ }
+
+ mFeatures = 0;
+
+ if (mBackend == NULL) {
+ return false;
+ }
+
+ if (mBackend->initialize() != OK) {
+ LOG(ERROR) << "Failed to initialize backend!";
+ return false;
+ }
+
+ for (uint32_t i = 1; i <= (uint32_t)Feature::MAX; i <<= 1) {
+ Feature f = static_cast<Feature>(i);
+ if (mBackend->hasFeature(f)) {
+ addFeature(f);
+ }
+ }
+ mConnected = true;
+
+ return mFeatures > 0;
+}
+
+sp<Color> Color::getInstance() {
+ if (sInstance == nullptr) {
+ sInstance = new Color();
+ }
+ return sInstance;
+}
+
+DisplayMode Color::modePointerToObj(sp<disp_mode> mode) {
+ DisplayMode m;
+ m.id = mode->id;
+ m.name = mode->name;
+ return m;
+}
+
+DisplayMode Color::invalidDisplayMode() {
+ DisplayMode mode;
+ mode.id = -1;
+ return mode;
+}
+
+Return<Features> Color::getSupportedFeatures() {
+ connect();
+ return mFeatures;
+}
+
+Return<void> Color::getDisplayModes(getDisplayModes_cb _hidl_cb) {
+ hidl_vec<DisplayMode> profiles;
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ vector<sp<disp_mode>> spProfiles;
+ rc = mBackend->getDisplayModes(spProfiles);
+ if (rc != OK) {
+ error("Unable to fetch display modes!");
+ } else {
+ profiles.resize(spProfiles.size());
+ for (size_t i = 0; i < spProfiles.size(); i++) {
+ profiles[i].id = spProfiles[i]->id;
+ profiles[i].name = spProfiles[i]->name;
+ }
+ }
+ }
+
+ _hidl_cb(profiles);
+ return Void();
+}
+
+Return<void> Color::getCurrentDisplayMode(getCurrentDisplayMode_cb _hidl_cb) {
+ DisplayMode mode;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ sp<disp_mode> m = mBackend->getCurrentDisplayMode();
+ if (m != nullptr) {
+ mode = modePointerToObj(m);
+ } else {
+ mode = invalidDisplayMode();
+ }
+ }
+ _hidl_cb(mode);
+ return Void();
+}
+
+Return<void> Color::getDefaultDisplayMode(getDefaultDisplayMode_cb _hidl_cb) {
+ DisplayMode mode;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ sp<disp_mode> m = mBackend->getDefaultDisplayMode();
+ if (m != nullptr) {
+ mode = modePointerToObj(m);
+ } else {
+ mode = invalidDisplayMode();
+ }
+ }
+ _hidl_cb(mode);
+ return Void();
+}
+
+Return<bool> Color::setDisplayMode(int32_t modeID, bool makeDefault) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ rc = mBackend->setDisplayMode(modeID, makeDefault);
+ if (rc != OK) {
+ error("Unable to set display mode!");
+ }
+ }
+ return rc == OK;
+}
+
+Return<bool> Color::setAdaptiveBacklightEnabled(bool enabled) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::ADAPTIVE_BACKLIGHT)) {
+ rc = mBackend->setAdaptiveBacklightEnabled(enabled);
+ if (rc != OK) {
+ error("Unable to set adaptive backlight state!");
+ }
+ }
+ return rc == OK;
+}
+
+Return<bool> Color::isAdaptiveBacklightEnabled() {
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::ADAPTIVE_BACKLIGHT)) {
+ return mBackend->isAdaptiveBacklightEnabled();
+ }
+ return false;
+}
+
+Return<bool> Color::setOutdoorModeEnabled(bool enabled) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::OUTDOOR_MODE)) {
+ rc = mBackend->setOutdoorModeEnabled(enabled);
+ if (rc != OK) {
+ error("Unable to toggle outdoor mode!");
+ }
+ }
+ return rc == OK;
+}
+
+Return<bool> Color::isOutdoorModeEnabled() {
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::OUTDOOR_MODE)) {
+ return mBackend->isOutdoorModeEnabled();
+ }
+ return false;
+}
+
+Return<void> Color::getColorBalanceRange(getColorBalanceRange_cb _hidl_cb) {
+ Range range;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::COLOR_BALANCE)) {
+ status_t rc = mBackend->getColorBalanceRange(range);
+ if (rc != OK) {
+ error("Unable to fetch color balance range!");
+ range.max = range.min = 0;
+ }
+ }
+
+ _hidl_cb(range);
+ return Void();
+}
+
+Return<int32_t> Color::getColorBalance() {
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::COLOR_BALANCE)) {
+ return mBackend->getColorBalance();
+ }
+
+ return 0;
+}
+
+Return<bool> Color::setColorBalance(int32_t value) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::COLOR_BALANCE)) {
+ rc = mBackend->setColorBalance(value);
+ if (rc != OK) {
+ error("Unable to set color balance!");
+ }
+ }
+ return rc == OK;
+}
+
+Return<bool> Color::setPictureAdjustment(const HSIC& hsic) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ rc = mBackend->setPictureAdjustment(hsic);
+ if (rc != OK) {
+ error("Unable to set picture adjustment!");
+ }
+ }
+ return rc == OK;
+}
+
+Return<void> Color::getPictureAdjustment(getPictureAdjustment_cb _hidl_cb) {
+ HSIC hsic;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ status_t rc = mBackend->getPictureAdjustment(hsic);
+ if (rc != OK) {
+ error("Unable to get picture adjustment!");
+ }
+ }
+ _hidl_cb(hsic);
+ return Void();
+}
+
+Return<void> Color::getDefaultPictureAdjustment(getDefaultPictureAdjustment_cb _hidl_cb) {
+ HSIC hsic;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ hsic = mBackend->getDefaultPictureAdjustment();
+ }
+ _hidl_cb(hsic);
+ return Void();
+}
+
+Return<void> Color::getHueRange(getHueRange_cb _hidl_cb) {
+ HSICRanges ranges;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ status_t rc = mBackend->getPictureAdjustmentRanges(ranges);
+ if (rc != OK) {
+ error("Unable to get hue range!");
+ }
+ }
+ _hidl_cb(ranges.hue);
+ return Void();
+}
+
+Return<void> Color::getSaturationRange(getSaturationRange_cb _hidl_cb) {
+ HSICRanges ranges;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ status_t rc = mBackend->getPictureAdjustmentRanges(ranges);
+ if (rc != OK) {
+ error("Unable to get saturation range!");
+ }
+ }
+ _hidl_cb(ranges.saturation);
+ return Void();
+}
+
+Return<void> Color::getIntensityRange(getIntensityRange_cb _hidl_cb) {
+ HSICRanges ranges;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ status_t rc = mBackend->getPictureAdjustmentRanges(ranges);
+ if (rc != OK) {
+ error("Unable to get intensity range!");
+ }
+ }
+ _hidl_cb(ranges.intensity);
+ return Void();
+}
+
+Return<void> Color::getContrastRange(getContrastRange_cb _hidl_cb) {
+ HSICRanges ranges;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ status_t rc = mBackend->getPictureAdjustmentRanges(ranges);
+ if (rc != OK) {
+ error("Unable to get contrast range!");
+ }
+ }
+ _hidl_cb(ranges.contrast);
+ return Void();
+}
+
+Return<void> Color::getSaturationThresholdRange(getSaturationThresholdRange_cb _hidl_cb) {
+ HSICRanges ranges;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ status_t rc = mBackend->getPictureAdjustmentRanges(ranges);
+ if (rc != OK) {
+ error("Unable to get saturation threshold range!");
+ }
+ }
+ _hidl_cb(ranges.saturationThreshold);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
diff --git a/livedisplay/1.0/default/src/Utils.cpp b/livedisplay/1.0/default/src/Utils.cpp
new file mode 100644
index 0000000..b2cebc2
--- /dev/null
+++ b/livedisplay/1.0/default/src/Utils.cpp
@@ -0,0 +1,142 @@
+/*
+** Copyright 2016, The CyanogenMod Project
+** 2017-2018, 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 <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fstream>
+#include <string>
+
+#include <cutils/sockets.h>
+
+#include "Utils.h"
+
+constexpr char LOCAL_STORAGE_PATH[] = "/data/vendor/display";
+constexpr char LOCAL_MODE_ID[] = "livedisplay_mode";
+constexpr char LOCAL_INITIAL_MODE_ID[] = "livedisplay_initial_mode";
+
+namespace vendor {
+namespace lineage {
+namespace livedisplay {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::NO_INIT;
+using ::android::OK;
+using ::std::endl;
+using ::std::ifstream;
+using ::std::ofstream;
+using ::std::string;
+
+status_t Utils::exists(const char* node) {
+ struct stat sbuf;
+ return stat(node, &sbuf);
+}
+
+status_t Utils::readInt(const char* node, int32_t* value) {
+ string buf;
+ status_t ret = OK;
+ ifstream fin(node);
+ if (!fin.good()) {
+ return errno;
+ }
+ if (getline(fin, buf)) {
+ *value = stoi(buf);
+ } else {
+ ret = errno;
+ }
+ fin.close();
+ return ret;
+}
+
+status_t Utils::writeInt(const char* node, int32_t value) {
+ status_t ret = OK;
+ ofstream fout(node);
+ if (!fout.good()) {
+ return errno;
+ }
+ if (!(fout << value << endl)) {
+ ret = errno;
+ }
+ fout.close();
+ return ret;
+}
+
+status_t Utils::readLocalModeId(int32_t* id) {
+ char buf[PATH_MAX];
+ sprintf(buf, "%s/%s", LOCAL_STORAGE_PATH, LOCAL_MODE_ID);
+ return readInt(buf, id);
+}
+
+status_t Utils::writeLocalModeId(int32_t id) {
+ char buf[PATH_MAX];
+ sprintf(buf, "%s/%s", LOCAL_STORAGE_PATH, LOCAL_MODE_ID);
+ return writeInt(buf, id);
+}
+
+status_t Utils::readInitialModeId(int32_t* id) {
+ char buf[PATH_MAX];
+ sprintf(buf, "%s/%s", LOCAL_STORAGE_PATH, LOCAL_INITIAL_MODE_ID);
+ return readInt(buf, id);
+}
+
+status_t Utils::writeInitialModeId(int32_t id) {
+ char buf[PATH_MAX];
+ sprintf(buf, "%s/%s", LOCAL_STORAGE_PATH, LOCAL_INITIAL_MODE_ID);
+ return writeInt(buf, id);
+}
+
+status_t Utils::sendDPPSCommand(char* buf, size_t len) {
+ status_t rc = OK;
+ int sock = socket_local_client("pps", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (sock < 0) {
+ return sock;
+ }
+
+ if (write(sock, buf, strlen(buf) + 1) > 0) {
+ memset(buf, 0, len);
+ ssize_t ret;
+ while ((ret = read(sock, buf, len)) > 0) {
+ if ((size_t)ret == len) {
+ break;
+ }
+ len -= ret;
+ buf += ret;
+
+ struct pollfd p = {.fd = sock, .events = POLLIN, .revents = 0};
+
+ ret = poll(&p, 1, 20);
+ if ((ret <= 0) || !(p.revents & POLLIN)) {
+ break;
+ }
+ }
+ } else {
+ rc = NO_INIT;
+ }
+ close(sock);
+ return rc;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace livedisplay
+} // namespace lineage
+} // namespace vendor
diff --git a/livedisplay/1.0/default/vendor.lineage.livedisplay@1.0-service-sdm.rc b/livedisplay/1.0/default/vendor.lineage.livedisplay@1.0-service-sdm.rc
new file mode 100644
index 0000000..1ef94eb
--- /dev/null
+++ b/livedisplay/1.0/default/vendor.lineage.livedisplay@1.0-service-sdm.rc
@@ -0,0 +1,4 @@
+service livedisplay-hal-1-0 /vendor/bin/hw/vendor.lineage.livedisplay@1.0-service-sdm
+ class hal
+ user system
+ group system
diff --git a/livedisplay/Android.bp b/livedisplay/Android.bp
index bbb3e4b..ba90f2c 100644
--- a/livedisplay/Android.bp
+++ b/livedisplay/Android.bp
@@ -1,4 +1,5 @@
// This is an autogenerated file, do not edit.
subdirs = [
"1.0",
+ "1.0/default",
]