summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--livedisplay/.clang-format13
-rw-r--r--livedisplay/Android.mk54
-rw-r--r--livedisplay/impl/LegacyMM.cpp336
-rw-r--r--livedisplay/impl/LegacyMM.h108
-rw-r--r--livedisplay/impl/SDM.cpp506
-rw-r--r--livedisplay/impl/SDM.h123
-rw-r--r--livedisplay/impl/Utils.cpp117
-rw-r--r--livedisplay/impl/Utils.h43
-rw-r--r--livedisplay/inc/Lighting.h50
-rw-r--r--livedisplay/inc/LiveDisplay.h87
-rw-r--r--livedisplay/inc/LiveDisplayAPI.h54
-rw-r--r--livedisplay/inc/LiveDisplayBackend.h37
-rw-r--r--livedisplay/inc/Types.h144
-rw-r--r--livedisplay/jni/jniutils.h40
-rw-r--r--livedisplay/jni/org_cyanogenmod_hardware_LiveDisplayVendorImpl.cpp444
-rw-r--r--livedisplay/src/LiveDisplay.cpp285
-rw-r--r--livedisplay/test/Android.mk9
-rw-r--r--livedisplay/test/pp_client.c67
18 files changed, 2517 insertions, 0 deletions
diff --git a/livedisplay/.clang-format b/livedisplay/.clang-format
new file mode 100644
index 0000000..fc4eb1b
--- /dev/null
+++ b/livedisplay/.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/Android.mk b/livedisplay/Android.mk
new file mode 100644
index 0000000..69c5542
--- /dev/null
+++ b/livedisplay/Android.mk
@@ -0,0 +1,54 @@
+LIVEDISPLAY_TARGETS := msm8916 msm8939 msm8974 msm8992 msm8994
+LIVEDISPLAY_TARGETS += msm8996 msm8937 msm8953 msm8976
+
+ifeq ($(call is-board-platform-in-list, $(LIVEDISPLAY_TARGETS)),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+common_C_INCLUDES := \
+ $(LOCAL_PATH)/impl \
+ $(LOCAL_PATH)/inc
+
+include $(CLEAR_VARS)
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ liblog \
+ libutils
+
+LOCAL_SRC_FILES := \
+ src/LiveDisplay.cpp \
+ impl/Utils.cpp \
+ impl/LegacyMM.cpp \
+ impl/SDM.cpp
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := liblivedisplay
+LOCAL_CFLAGS := -std=c++11
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := \
+ jni/org_cyanogenmod_hardware_LiveDisplayVendorImpl.cpp
+
+LOCAL_C_INCLUDES := $(common_C_INCLUDES)
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ liblog \
+ libnativehelper \
+ libutils
+
+LOCAL_STATIC_LIBRARIES := liblivedisplay
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := libjni_livedisplay
+LOCAL_CFLAGS := -std=c++11
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/livedisplay/impl/LegacyMM.cpp b/livedisplay/impl/LegacyMM.cpp
new file mode 100644
index 0000000..3d4da93
--- /dev/null
+++ b/livedisplay/impl/LegacyMM.cpp
@@ -0,0 +1,336 @@
+/*
+** Copyright 2016, The CyanogenMod 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 <cutils/sockets.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LOG_TAG "LiveDisplay-LegacyMM"
+#include <utils/Log.h>
+
+#include "LegacyMM.h"
+
+namespace android {
+
+status_t LegacyMM::initialize() {
+ status_t rc = OK;
+ mLibHandle = dlopen(MM_DISP_LIB, RTLD_NOW);
+ if (mLibHandle == NULL) {
+ ALOGE("DLOPEN failed for %s", MM_DISP_LIB);
+ return NO_INIT;
+ }
+
+ disp_api_init = (int(*)(int32_t))dlsym(mLibHandle, "disp_api_init");
+ if (disp_api_init == NULL) {
+ ALOGE("dlsym failed for disp_api_init");
+ }
+ disp_api_supported = (int(*)(int32_t, int32_t))dlsym(mLibHandle, "disp_api_supported");
+ if (disp_api_supported == NULL) {
+ ALOGE("dlsym failed for disp_api_supported");
+ }
+ disp_api_get_color_balance_range =
+ (int(*)(int32_t, void*))dlsym(mLibHandle, "disp_api_get_color_balance_range");
+ if (disp_api_get_color_balance_range == NULL) {
+ ALOGE("dlsym failed for disp_api_get_color_balance_range");
+ }
+ disp_api_set_color_balance =
+ (int(*)(int32_t, int))dlsym(mLibHandle, "disp_api_set_color_balance");
+ if (disp_api_set_color_balance == NULL) {
+ ALOGE("dlsym failed for disp_api_set_color_balance");
+ }
+ disp_api_get_color_balance =
+ (int(*)(int32_t, int*))dlsym(mLibHandle, "disp_api_get_color_balance");
+ if (disp_api_get_color_balance == NULL) {
+ ALOGE("dlsym failed for disp_api_get_color_balance");
+ }
+ disp_api_get_num_display_modes =
+ (int(*)(int32_t, int32_t, int*))dlsym(mLibHandle, "disp_api_get_num_display_modes");
+ if (disp_api_get_num_display_modes == NULL) {
+ ALOGE("dlsym failed for disp_api_get_num_display_modes");
+ }
+ disp_api_get_display_modes =(int(*)(int32_t, int32_t, void*, int))dlsym(
+ mLibHandle, "disp_api_get_display_modes");
+ if (disp_api_get_display_modes == NULL) {
+ ALOGE("dlsym failed for disp_api_get_display_modes");
+ }
+ disp_api_get_active_display_mode = (int(*)(int32_t, int*, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_active_display_mode");
+ if (disp_api_get_active_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_get_active_display_mode");
+ }
+ disp_api_set_active_display_mode =
+ (int(*)(int32_t, int))dlsym(mLibHandle, "disp_api_set_active_display_mode");
+ if (disp_api_set_active_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_set_active_display_mode");
+ }
+ disp_api_set_default_display_mode =
+ (int(*)(int32_t, int))dlsym(mLibHandle, "disp_api_set_default_display_mode");
+ if (disp_api_set_default_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_set_default_display_mode");
+ }
+ disp_api_get_default_display_mode =
+ (int(*)(int32_t, int*))dlsym(mLibHandle, "disp_api_get_default_display_mode");
+ if (disp_api_get_default_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_get_default_display_mode");
+ }
+ disp_api_get_pa_range = (int(*)(int32_t, void*))dlsym(mLibHandle, "disp_api_get_pa_range");
+ if (disp_api_get_pa_range == NULL) {
+ ALOGE("dlsym failed for disp_api_get_pa_range");
+ }
+ disp_api_get_pa_config =
+ (int(*)(int32_t, void*))dlsym(mLibHandle, "disp_api_get_pa_config");
+ if (disp_api_get_pa_config == NULL) {
+ ALOGE("dlsym failed for disp_api_get_pa_config");
+ }
+ disp_api_set_pa_config =
+ (int(*)(int32_t, void*))dlsym(mLibHandle, "disp_api_set_pa_config");
+ if (disp_api_set_pa_config == NULL) {
+ ALOGE("dlsym failed for disp_api_set_pa_config");
+ }
+
+ return disp_api_init(0);
+}
+
+LegacyMM::~LegacyMM() {
+ if (mLibHandle != NULL) {
+ dlclose(mLibHandle);
+ }
+}
+
+status_t LegacyMM::deinitialize() {
+ if (mLibHandle != NULL) {
+ disp_api_init(1);
+ }
+ return OK;
+}
+
+bool LegacyMM::hasFeature(Feature feature) {
+ int id;
+ switch (feature) {
+ case Feature::COLOR_TEMPERATURE:
+ id = 0;
+ break;
+ case Feature::DISPLAY_MODES:
+ id = 1;
+ break;
+ case Feature::PICTURE_ADJUSTMENT:
+ id = 4;
+ break;
+ default:
+ return false;
+ }
+ if (disp_api_supported(0, id)) {
+ // display modes and color balance depend on each other
+ if (feature == Feature::DISPLAY_MODES ||
+ feature == Feature::COLOR_TEMPERATURE) {
+ if (getNumDisplayModes() > 0) {
+ // make sure the range isn't zero
+ if (feature == Feature::COLOR_TEMPERATURE) {
+ Range r;
+ if (getColorBalanceRange(r) == OK && r.isNonZero()) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ }
+ if (feature == Feature::PICTURE_ADJUSTMENT) {
+ HSICRanges r;
+ if (getPictureAdjustmentRanges(r) == OK && r.isValid()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+status_t LegacyMM::getColorBalanceRange(Range& range) {
+ struct mm_range r;
+ memset(&r, 0, sizeof(struct mm_range));
+
+ status_t rc = disp_api_get_color_balance_range(0, &r);
+ if (rc == OK) {
+ range.min = r.min;
+ range.max = r.max;
+ }
+ return rc;
+}
+
+status_t LegacyMM::setColorBalance(int32_t balance) {
+ return disp_api_set_color_balance(0, (int)balance);
+}
+
+int32_t LegacyMM::getColorBalance() {
+ int value = 0;
+ if (disp_api_get_color_balance(0, &value) != 0) {
+ value = 0;
+ }
+ return (int32_t)value;
+}
+
+int LegacyMM::getNumDisplayModes() {
+ int count = 0;
+ if (disp_api_get_num_display_modes(0, 0, &count) != 0) {
+ count = 0;
+ }
+ return count;
+}
+
+status_t LegacyMM::getDisplayModes(List<sp<DisplayMode>>& profiles) {
+ status_t rc = OK;
+ int i = 0;
+
+ int count = getNumDisplayModes();
+
+ if (!count) return rc;
+
+ struct d_mode {
+ int id;
+ char* name;
+ uint32_t len;
+ int32_t type;
+ };
+
+ d_mode* tmp = new d_mode[count];
+ memset(tmp, 0, sizeof(d_mode) * count);
+ for (i = 0; i < count; i++) {
+ tmp[i].id = -1;
+ tmp[i].name = new char[128];
+ tmp[i].len = 128;
+ }
+
+ rc = disp_api_get_display_modes(0, 0, tmp, count);
+ if (rc == 0) {
+ for (i = 0; i < count; i++) {
+ const sp<DisplayMode> m = new DisplayMode(tmp[i].id, tmp[i].name, tmp[i].len);
+ profiles.push_back(m);
+ delete tmp[i].name;
+ }
+ }
+ delete[] tmp;
+
+ return rc;
+}
+
+status_t LegacyMM::setDisplayMode(int32_t modeID, bool makeDefault) {
+ if (disp_api_set_active_display_mode(0, modeID) != 0) {
+ return BAD_VALUE;
+ }
+
+ if (makeDefault && disp_api_set_default_display_mode(0, modeID) != 0) {
+ return BAD_VALUE;
+ }
+
+ return OK;
+}
+
+sp<DisplayMode> LegacyMM::getDisplayModeById(int id) {
+ List<sp<DisplayMode>> profiles;
+ status_t rc = getDisplayModes(profiles);
+ if (rc == OK) {
+ for (List<sp<DisplayMode>>::iterator it = profiles.begin(); it != profiles.end(); ++it) {
+ const sp<DisplayMode> mode = *it;
+ if (id == mode->id) {
+ return mode;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+sp<DisplayMode> LegacyMM::getCurrentDisplayMode() {
+ int id = 0;
+ uint32_t mask = 0;
+
+ status_t rc = disp_api_get_active_display_mode(0, &id, &mask);
+ if (rc == OK && id >= 0) {
+ return getDisplayModeById(id);
+ }
+
+ return nullptr;
+}
+
+sp<DisplayMode> LegacyMM::getDefaultDisplayMode() {
+ int id = 0;
+
+ status_t rc = disp_api_get_default_display_mode(0, &id);
+ if (rc == OK && id >= 0) {
+ return getDisplayModeById(id);
+ }
+
+ return nullptr;
+}
+
+status_t LegacyMM::getPictureAdjustmentRanges(HSICRanges& ranges) {
+ struct mm_pa_range r;
+ memset(&r, 0, sizeof(struct mm_pa_range));
+
+ status_t rc = disp_api_get_pa_range(0, &r);
+ if (rc == OK) {
+ ranges.hue.min = r.min.hue;
+ ranges.hue.max = r.max.hue;
+ ranges.saturation.min = r.min.saturation;
+ ranges.saturation.max = r.max.saturation;
+ ranges.intensity.min = r.min.intensity;
+ ranges.intensity.max = r.max.intensity;
+ ranges.contrast.min = r.min.contrast;
+ ranges.contrast.max = r.max.contrast;
+ ranges.saturationThreshold.min = r.min.saturationThreshold;
+ ranges.saturationThreshold.max = r.max.saturationThreshold;
+ }
+ return rc;
+}
+
+status_t LegacyMM::getPictureAdjustment(HSIC& hsic) {
+ struct mm_pa_config config;
+ memset(&config, 0, sizeof(struct mm_pa_config));
+
+ status_t rc = disp_api_get_pa_config(0, &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 LegacyMM::getDefaultPictureAdjustment(HSIC& /* hsic */) {
+ return OK;
+}
+
+status_t LegacyMM::setPictureAdjustment(HSIC hsic) {
+ struct mm_pa_config config;
+ memset(&config, 0, sizeof(struct mm_pa_config));
+
+ config.flags = 0x0F; // lower 4 bits
+ 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 disp_api_set_pa_config(0, &config);
+}
+};
diff --git a/livedisplay/impl/LegacyMM.h b/livedisplay/impl/LegacyMM.h
new file mode 100644
index 0000000..380c598
--- /dev/null
+++ b/livedisplay/impl/LegacyMM.h
@@ -0,0 +1,108 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_LIVEDISPLAYLEGACYMM_H
+#define CYNGN_LIVEDISPLAYLEGACYMM_H
+
+#include <LiveDisplayBackend.h>
+
+#define MM_DISP_LIB "libmm-disp-apis.so"
+
+namespace android {
+
+struct mm_pa_data {
+ int hue;
+ int saturation;
+ int intensity;
+ int contrast;
+ int saturationThreshold;
+};
+
+struct mm_pa_config {
+ int flags;
+ struct mm_pa_data data;
+};
+
+struct mm_pa_range {
+ struct mm_pa_data max;
+ struct mm_pa_data min;
+};
+
+struct mm_range {
+ int max;
+ int min;
+};
+
+class LegacyMM : public LiveDisplayBackend {
+ public:
+ virtual status_t initialize();
+ virtual status_t deinitialize();
+ virtual bool hasFeature(Feature feature);
+
+ virtual status_t setAdaptiveBacklightEnabled(bool /* enabled */) {
+ return NO_INIT;
+ }
+ virtual bool isAdaptiveBacklightEnabled() {
+ return false;
+ }
+
+ virtual status_t setOutdoorModeEnabled(bool /* enabled */) {
+ return NO_INIT;
+ }
+ virtual bool isOutdoorModeEnabled() {
+ return false;
+ }
+
+ virtual status_t getColorBalanceRange(Range& range);
+ virtual status_t setColorBalance(int32_t balance);
+ virtual int32_t getColorBalance();
+
+ virtual status_t getDisplayModes(List<sp<DisplayMode>>& profiles);
+ virtual status_t setDisplayMode(int32_t modeID, bool makeDefault);
+ virtual sp<DisplayMode> getCurrentDisplayMode();
+ virtual sp<DisplayMode> getDefaultDisplayMode();
+
+ virtual status_t getPictureAdjustmentRanges(HSICRanges& ranges);
+ virtual status_t getPictureAdjustment(HSIC& hsic);
+ virtual status_t getDefaultPictureAdjustment(HSIC& hsic);
+ virtual status_t setPictureAdjustment(HSIC hsic);
+
+ virtual ~LegacyMM();
+
+ private:
+ sp<DisplayMode> getDisplayModeById(int32_t id);
+ int getNumDisplayModes();
+
+ void* mLibHandle;
+
+ int (*disp_api_init)(int32_t);
+ int (*disp_api_get_color_balance_range)(int32_t, void*);
+ int (*disp_api_set_color_balance)(int32_t, int);
+ int (*disp_api_get_color_balance)(int32_t, int*);
+ int (*disp_api_get_num_display_modes)(int32_t, int32_t, int*);
+ int (*disp_api_get_display_modes)(int32_t, int32_t, void*, int);
+ int (*disp_api_get_active_display_mode)(int32_t, int*, uint32_t*);
+ int (*disp_api_set_active_display_mode)(int32_t, int);
+ int (*disp_api_set_default_display_mode)(int32_t, int);
+ int (*disp_api_get_default_display_mode)(int32_t, int*);
+ int (*disp_api_get_pa_range)(int32_t, void*);
+ int (*disp_api_get_pa_config)(int32_t, void*);
+ int (*disp_api_set_pa_config)(int32_t, void*);
+ int (*disp_api_supported)(int32_t, int32_t);
+};
+};
+
+#endif
diff --git a/livedisplay/impl/SDM.cpp b/livedisplay/impl/SDM.cpp
new file mode 100644
index 0000000..4788281
--- /dev/null
+++ b/livedisplay/impl/SDM.cpp
@@ -0,0 +1,506 @@
+/*
+** Copyright 2016, The CyanogenMod 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 <dlfcn.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "LiveDisplay-SDM"
+#include <utils/Log.h>
+
+#include "SDM.h"
+#include "Utils.h"
+
+namespace android {
+
+status_t SDM::loadVendorLibrary() {
+ if (mLibHandle != NULL) {
+ return OK;
+ }
+
+ mLibHandle = dlopen(SDM_DISP_LIB, RTLD_NOW);
+ if (mLibHandle == NULL) {
+ ALOGE("DLOPEN failed for %s", SDM_DISP_LIB);
+ return NO_INIT;
+ }
+
+ disp_api_init = (int32_t(*)(int64_t*, uint32_t))dlsym(mLibHandle, "disp_api_init");
+ if (disp_api_init == NULL) {
+ ALOGE("dlsym failed for disp_api_init");
+ goto fail;
+ }
+ disp_api_deinit = (int32_t(*)(int64_t, uint32_t))dlsym(mLibHandle, "disp_api_deinit");
+ if (disp_api_deinit == NULL) {
+ ALOGE("dlsym failed for disp_api_deinit");
+ goto fail;
+ }
+ disp_api_get_global_color_balance_range = (int32_t(*)(int64_t, uint32_t, void*))dlsym(
+ mLibHandle, "disp_api_get_global_color_balance_range");
+ if (disp_api_get_global_color_balance_range == NULL) {
+ ALOGE("dlsym failed for disp_api_get_global_color_balance_range");
+ goto fail;
+ }
+ disp_api_set_global_color_balance = (int32_t(*)(int64_t, uint32_t, int32_t, uint32_t))dlsym(
+ mLibHandle, "disp_api_set_global_color_balance");
+ if (disp_api_set_global_color_balance == NULL) {
+ ALOGE("dlsym failed for disp_api_set_global_color_balance");
+ goto fail;
+ }
+ disp_api_get_global_color_balance = (int32_t(*)(int64_t, uint32_t, int32_t*, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_global_color_balance");
+ if (disp_api_get_global_color_balance == NULL) {
+ ALOGE("dlsym failed for disp_api_get_global_color_balance");
+ goto fail;
+ }
+ disp_api_get_num_display_modes =
+ (int32_t(*)(int64_t, uint32_t, int32_t, int32_t*, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_num_display_modes");
+ if (disp_api_get_num_display_modes == NULL) {
+ ALOGE("dlsym failed for disp_api_get_num_display_modes");
+ goto fail;
+ }
+ disp_api_get_display_modes =
+ (int32_t(*)(int64_t, uint32_t, int32_t, void*, int32_t, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_display_modes");
+ if (disp_api_get_display_modes == NULL) {
+ ALOGE("dlsym failed for disp_api_get_display_modes");
+ goto fail;
+ }
+ disp_api_get_active_display_mode =
+ (int32_t(*)(int64_t, uint32_t, int32_t*, uint32_t*, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_active_display_mode");
+ if (disp_api_get_active_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_get_active_display_mode");
+ goto fail;
+ }
+ disp_api_set_active_display_mode = (int32_t(*)(int64_t, uint32_t, int32_t, uint32_t))dlsym(
+ mLibHandle, "disp_api_set_active_display_mode");
+ if (disp_api_set_active_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_set_active_display_mode");
+ goto fail;
+ }
+ disp_api_set_default_display_mode = (int32_t(*)(int64_t, uint32_t, int32_t, uint32_t))dlsym(
+ mLibHandle, "disp_api_set_default_display_mode");
+ if (disp_api_set_default_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_set_default_display_mode");
+ goto fail;
+ }
+ disp_api_get_default_display_mode = (int32_t(*)(int64_t, uint32_t, int32_t*, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_default_display_mode");
+ if (disp_api_get_default_display_mode == NULL) {
+ ALOGE("dlsym failed for disp_api_get_default_display_mode");
+ goto fail;
+ }
+ disp_api_get_global_pa_range =
+ (int32_t(*)(int64_t, uint32_t, void*))dlsym(mLibHandle, "disp_api_get_global_pa_range");
+ if (disp_api_get_global_pa_range == NULL) {
+ ALOGE("dlsym failed for disp_api_get_global_pa_range");
+ goto fail;
+ }
+ disp_api_get_global_pa_config = (int32_t(*)(int64_t, uint32_t, uint32_t*, void*))dlsym(
+ mLibHandle, "disp_api_get_global_pa_config");
+ if (disp_api_get_global_pa_config == NULL) {
+ ALOGE("dlsym failed for disp_api_get_global_pa_config");
+ goto fail;
+ }
+ disp_api_set_global_pa_config = (int32_t(*)(int64_t, uint32_t, uint32_t, void*))dlsym(
+ mLibHandle, "disp_api_set_global_pa_config");
+ if (disp_api_set_global_pa_config == NULL) {
+ ALOGE("dlsym failed for disp_api_set_global_pa_config");
+ goto fail;
+ }
+ disp_api_get_feature_version = (int32_t(*)(int64_t, uint32_t, void*, uint32_t*))dlsym(
+ mLibHandle, "disp_api_get_feature_version");
+ if (disp_api_get_feature_version == NULL) {
+ ALOGE("dlsym failed for disp_api_get_feature_version");
+ goto fail;
+ }
+
+ return OK;
+
+fail:
+ ALOGE("Failed to link vendor library: %s", dlerror());
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+ return NO_INIT;
+}
+
+status_t SDM::initialize() {
+ status_t rc = loadVendorLibrary();
+ if (rc != OK) {
+ return rc;
+ }
+
+ rc = disp_api_init(&mHandle, 0);
+ if (rc != OK) {
+ return rc;
+ }
+
+ mActiveModeId = -1;
+
+ if (hasFeature(Feature::DISPLAY_MODES)) {
+ sp<DisplayMode> defMode = getDefaultDisplayMode();
+ if (defMode != nullptr) {
+ setDisplayMode(defMode->id, false);
+ }
+ }
+ return OK;
+}
+
+SDM::~SDM() {
+ if (mLibHandle != NULL) {
+ dlclose(mLibHandle);
+ }
+}
+
+status_t SDM::deinitialize() {
+ if (mLibHandle != NULL) {
+ disp_api_deinit(mHandle, 0);
+ mHandle = -1;
+ }
+ 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;
+}
+
+status_t SDM::getColorBalanceRange(Range& range) {
+ status_t rc = disp_api_get_global_color_balance_range(mHandle, 0, &range);
+ ALOGV("getColorBalanceRange: min=%d max=%d step=%d", range.min, range.max, range.step);
+ return rc;
+}
+
+status_t SDM::setColorBalance(int32_t balance) {
+ return disp_api_set_global_color_balance(mHandle, 0, balance, 0);
+}
+
+int32_t SDM::getColorBalance() {
+ int32_t value = -1;
+ uint32_t flags = 0;
+ if (disp_api_get_global_color_balance(mHandle, 0, &value, &flags) != 0) {
+ value = 0;
+ }
+ return value;
+}
+
+uint32_t SDM::getNumDisplayModes() {
+ uint32_t flags = 0;
+ int32_t count = 0;
+ if (disp_api_get_num_display_modes(mHandle, 0, 0, &count, &flags)) {
+ count = 0;
+ }
+ if (getLocalSRGBMode() != nullptr) {
+ count++;
+ }
+ return count;
+}
+
+status_t SDM::getDisplayModes(List<sp<DisplayMode>>& profiles) {
+ status_t rc = OK;
+ uint32_t flags = 0, i = 0;
+
+ uint32_t count = getNumDisplayModes();
+ if (!count) return rc;
+
+ sp<DisplayMode> srgb = getLocalSRGBMode();
+ uint32_t sdm_count = srgb == nullptr ? count : (count - 1);
+
+ 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 (i = 0; i < sdm_count; i++) {
+ tmp[i].id = -1;
+ tmp[i].name = new char[128];
+ tmp[i].len = 128;
+ }
+
+ rc = disp_api_get_display_modes(mHandle, 0, 0, tmp, sdm_count, &flags);
+ if (rc == 0) {
+ for (i = 0; i < sdm_count; i++) {
+ const sp<DisplayMode> m = new DisplayMode(tmp[i].id, tmp[i].name, tmp[i].len);
+ m->privFlags = PRIV_MODE_FLAG_SDM;
+ profiles.push_back(m);
+ delete tmp[i].name;
+ }
+ }
+ delete[] tmp;
+
+ if (srgb != nullptr) {
+ profiles.push_back(srgb);
+ }
+
+ return rc;
+}
+
+status_t SDM::setDisplayMode(int32_t modeID, bool makeDefault) {
+ status_t rc = OK;
+
+ if (modeID == mActiveModeId) {
+ return OK;
+ }
+
+ sp<DisplayMode> mode = getDisplayModeById(modeID);
+ if (mode == nullptr) {
+ return BAD_VALUE;
+ }
+
+ ALOGV("setDisplayMode: current mode=%d", mActiveModeId);
+
+ if (mActiveModeId >= 0) {
+ sp<DisplayMode> oldMode = getDisplayModeById(mActiveModeId);
+ ALOGV("setDisplayMode: oldMode=%d flags=%d", oldMode->id, oldMode->privFlags);
+ if (oldMode->privFlags == PRIV_MODE_FLAG_SYSFS ||
+ mode->privFlags == PRIV_MODE_FLAG_SYSFS) {
+ ALOGV("disabling old mode");
+ rc = setModeState(oldMode, false);
+ if (rc != OK) {
+ ALOGE("Failed to disable previous mode! err=%d", rc);
+ return rc;
+ }
+ }
+ }
+
+ rc = setModeState(mode, true);
+ if (rc == OK) {
+ mActiveModeId = mode->id;
+ if (makeDefault) {
+ rc = Utils::writeLocalModeId(mode->id);
+ if (rc != OK) {
+ ALOGE("failed to save mode! %d", rc);
+ return rc;
+ }
+ }
+ HSIC tmp;
+ rc = getPictureAdjustment(tmp);
+ if (rc != OK) {
+ ALOGE("failed to retrieve picture adjustment after mode setting!");
+ } else {
+ ALOGV("new default PA: %d %f %f %f %f", tmp.hue, tmp.saturation,
+ tmp.intensity, tmp.contrast, tmp.saturationThreshold);
+ mDefaultPictureAdjustment.setTo(tmp);
+ }
+ } else {
+ ALOGE("Failed to setModeState! err=%d", rc);
+ return rc;
+ }
+
+ ALOGV("setDisplayMode: %d default: %d flags: %d", modeID, makeDefault, mode->privFlags);
+ return OK;
+}
+
+sp<DisplayMode> SDM::getDisplayModeById(int32_t id) {
+ List<sp<DisplayMode>> profiles;
+ status_t rc = getDisplayModes(profiles);
+ if (rc == OK) {
+ for (List<sp<DisplayMode>>::iterator it = profiles.begin(); it != profiles.end(); ++it) {
+ const sp<DisplayMode> mode = *it;
+ if (id == mode->id) {
+ return mode;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+sp<DisplayMode> SDM::getCurrentDisplayMode() {
+ return getDisplayModeById(mActiveModeId);
+}
+
+sp<DisplayMode> SDM::getDefaultDisplayMode() {
+ int32_t id = 0;
+ if (Utils::readLocalModeId(&id) == OK && id >= 0) {
+ return getDisplayModeById(id);
+ }
+ return nullptr;
+}
+
+status_t SDM::setModeState(sp<DisplayMode> mode, bool state) {
+ uint32_t flags = 0;
+ int32_t id = 0;
+
+ if (mode->privFlags == PRIV_MODE_FLAG_SYSFS) {
+ ALOGV("sysfs node: %s state=%d", mode->privData.string(), state);
+ return Utils::writeInt(mode->privData.string(), state ? 1 : 0);
+ } else if (mode->privFlags == PRIV_MODE_FLAG_SDM) {
+ if (state) {
+ return disp_api_set_active_display_mode(mHandle, 0, mode->id, 0);
+ } else {
+ if (disp_api_get_default_display_mode(mHandle, 0, &id, &flags) == 0) {
+ ALOGV("set sdm mode to default: id=%d", id);
+ return disp_api_set_active_display_mode(mHandle, 0, id, 0);
+ }
+ }
+ }
+ return BAD_VALUE;
+}
+
+sp<DisplayMode> SDM::getLocalSRGBMode() {
+ char path[PATH_MAX];
+ sprintf(path, "%s", SRGB_NODE);
+
+ if (access(path, W_OK) != 0) {
+ return nullptr;
+ }
+ sp<DisplayMode> m = new DisplayMode(SRGB_NODE_ID, "srgb", 4);
+ m->privFlags = PRIV_MODE_FLAG_SYSFS;
+ m->privData.setTo(path);
+ return m;
+}
+
+status_t SDM::getPictureAdjustmentRanges(HSICRanges& ranges) {
+ hsic_ranges r;
+ memset(&r, 0, sizeof(struct hsic_ranges));
+
+ status_t rc = disp_api_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;
+}
+
+status_t SDM::getPictureAdjustment(HSIC& hsic) {
+ uint32_t enable = 0;
+ hsic_config config;
+ memset(&config, 0, sizeof(struct hsic_config));
+
+ status_t rc = disp_api_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::getDefaultPictureAdjustment(HSIC& hsic) {
+ hsic.setTo(mDefaultPictureAdjustment);
+ return OK;
+}
+
+status_t SDM::setPictureAdjustment(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 disp_api_set_global_pa_config(mHandle, 0, 1, &config);
+}
+
+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 = 4;
+ break;
+ case Feature::COLOR_TEMPERATURE:
+ id = 3;
+ break;
+ case Feature::PICTURE_ADJUSTMENT:
+ id = 1;
+ case Feature::ADAPTIVE_BACKLIGHT:
+ if (property_get_int32("ro.qualcomm.foss", 0) > 0) {
+ return true;
+ }
+ break;
+ default:
+ return false;
+ }
+
+ if (disp_api_get_feature_version(mHandle, id, &v, &flags) == 0) {
+ if (v.x > 0 || v.y > 0 || v.z > 0) {
+
+ // Color balance depends on calibration data in SDM
+ if (feature == Feature::DISPLAY_MODES ||
+ feature == Feature::COLOR_TEMPERATURE) {
+ if (getNumDisplayModes() > 0) {
+ // make sure the range isn't zero
+ if (feature == Feature::COLOR_TEMPERATURE) {
+ Range r;
+ if (getColorBalanceRange(r) == OK && r.isNonZero()) {
+ return true;
+ }
+ return false;
+ }
+ return true;
+ }
+ } else if (feature == Feature::PICTURE_ADJUSTMENT) {
+ HSICRanges r;
+ if (getPictureAdjustmentRanges(r) == OK && r.isValid()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+};
diff --git a/livedisplay/impl/SDM.h b/livedisplay/impl/SDM.h
new file mode 100644
index 0000000..735ecc0
--- /dev/null
+++ b/livedisplay/impl/SDM.h
@@ -0,0 +1,123 @@
+#ifndef CYNGN_LIVEDISPLAYSDM_H
+#define CYNGN_LIVEDISPLAYSDM_H
+
+#include <LiveDisplayBackend.h>
+
+#define SDM_DISP_LIB "libsdm-disp-apis.so"
+
+#define DPPS_BUF_SIZE 64
+
+#define FOSS_SUPPORTED "foss:support"
+#define FOSS_ON "foss:on"
+#define FOSS_OFF "foss:off"
+#define FOSS_STATUS "foss:status"
+
+#define SRGB_NODE "/sys/class/graphics/fb0/srgb"
+#define SRGB_NODE_ID 601
+
+#define PRIV_MODE_FLAG_SDM 1
+#define PRIV_MODE_FLAG_SYSFS 2
+
+namespace android {
+
+struct hsic_data {
+ int32_t hue;
+ float saturation;
+ float intensity;
+ float contrast;
+ float saturationThreshold;
+};
+
+struct hsic_config {
+ uint32_t unused;
+ hsic_data data;
+};
+
+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 unused;
+ 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;
+};
+
+class SDM : public LiveDisplayBackend {
+ public:
+ virtual status_t initialize();
+ virtual status_t deinitialize();
+ virtual bool hasFeature(Feature feature);
+
+ virtual status_t setAdaptiveBacklightEnabled(bool enabled);
+ virtual bool isAdaptiveBacklightEnabled();
+
+ virtual status_t setOutdoorModeEnabled(bool /* enabled */) {
+ return NO_INIT;
+ }
+ virtual bool isOutdoorModeEnabled() {
+ return false;
+ }
+
+ virtual status_t getColorBalanceRange(Range& range);
+ virtual status_t setColorBalance(int32_t balance);
+ virtual int32_t getColorBalance();
+
+ virtual status_t getDisplayModes(List<sp<DisplayMode>>& profiles);
+ virtual status_t setDisplayMode(int32_t modeID, bool makeDefault);
+ virtual sp<DisplayMode> getCurrentDisplayMode();
+ virtual sp<DisplayMode> getDefaultDisplayMode();
+
+ virtual status_t getPictureAdjustmentRanges(HSICRanges& ranges);
+ virtual status_t getPictureAdjustment(HSIC& hsic);
+ virtual status_t getDefaultPictureAdjustment(HSIC& hsic);
+ virtual status_t setPictureAdjustment(HSIC hsic);
+
+ virtual ~SDM();
+
+ private:
+ status_t loadVendorLibrary();
+
+ sp<DisplayMode> getLocalSRGBMode();
+ sp<DisplayMode> getDisplayModeById(int32_t id);
+ status_t setModeState(sp<DisplayMode> mode, bool state);
+ uint32_t getNumDisplayModes();
+
+ int64_t mHandle;
+ bool mCachedFOSSStatus;
+ int32_t mActiveModeId;
+
+ HSIC mDefaultPictureAdjustment;
+
+ void* mLibHandle;
+
+ int32_t (*disp_api_init)(int64_t*, uint32_t);
+ int32_t (*disp_api_deinit)(int64_t, uint32_t);
+ int32_t (*disp_api_get_global_color_balance_range)(int64_t, uint32_t, void*);
+ int32_t (*disp_api_set_global_color_balance)(int64_t, uint32_t, int32_t, uint32_t);
+ int32_t (*disp_api_get_global_color_balance)(int64_t, uint32_t, int32_t*, uint32_t*);
+ int32_t (*disp_api_get_num_display_modes)(int64_t, uint32_t, int32_t, int32_t*, uint32_t*);
+ int32_t (*disp_api_get_display_modes)(int64_t, uint32_t, int32_t, void*, int32_t, uint32_t*);
+ int32_t (*disp_api_get_active_display_mode)(int64_t, uint32_t, int32_t*, uint32_t*, uint32_t*);
+ int32_t (*disp_api_set_active_display_mode)(int64_t, uint32_t, int32_t, uint32_t);
+ int32_t (*disp_api_set_default_display_mode)(int64_t, uint32_t, int32_t, uint32_t);
+ int32_t (*disp_api_get_default_display_mode)(int64_t, uint32_t, int32_t*, uint32_t*);
+ int32_t (*disp_api_get_global_pa_range)(int64_t, uint32_t, void*);
+ int32_t (*disp_api_get_global_pa_config)(int64_t, uint32_t, uint32_t*, void*);
+ int32_t (*disp_api_set_global_pa_config)(int64_t, uint32_t, uint32_t, void*);
+ int32_t (*disp_api_get_feature_version)(int64_t, uint32_t, void*, uint32_t*);
+};
+};
+
+#endif
diff --git a/livedisplay/impl/Utils.cpp b/livedisplay/impl/Utils.cpp
new file mode 100644
index 0000000..f511465
--- /dev/null
+++ b/livedisplay/impl/Utils.cpp
@@ -0,0 +1,117 @@
+/*
+** Copyright 2016, The CyanogenMod 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 <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <sys/stat.h>
+
+#include <cutils/sockets.h>
+
+#include "Utils.h"
+
+#define LOCAL_STORAGE_PATH "/data/misc/display"
+#define LOCAL_MODE_ID "livedisplay_mode"
+
+namespace android {
+
+status_t Utils::exists(const char* node) {
+
+ struct stat sbuf;
+ return stat(node, &sbuf);
+}
+
+status_t Utils::readInt(const char* node, int32_t* value) {
+ char buf[32];
+ status_t ret = OK;
+
+ FILE *fp = fopen(node, "r");
+ if (!fp) {
+ return errno;
+ }
+ if (fgets(buf, sizeof(buf) - 1, fp)) {
+ *value = atoi(buf);
+ } else {
+ ret = errno;
+ }
+ fclose(fp);
+ return ret;
+}
+
+status_t Utils::writeInt(const char* node, int32_t value) {
+ char buf[32];
+ status_t ret = OK;
+
+ FILE *fp = fopen(node, "w");
+ if (!fp) {
+ return errno;
+ }
+ int bytes = snprintf(buf, sizeof(buf), "%d\n", value);
+
+ if (fputs(buf, fp) < 0) {
+ ret = errno;
+ }
+ fclose(fp);
+ 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::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;
+ } else {
+ 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;
+}
+
+};
diff --git a/livedisplay/impl/Utils.h b/livedisplay/impl/Utils.h
new file mode 100644
index 0000000..373503e
--- /dev/null
+++ b/livedisplay/impl/Utils.h
@@ -0,0 +1,43 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_UTILS_H
+#define CYNGN_UTILS_H
+
+#include <stdlib.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+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);
+};
+
+};
+#endif
diff --git a/livedisplay/inc/Lighting.h b/livedisplay/inc/Lighting.h
new file mode 100644
index 0000000..54df685
--- /dev/null
+++ b/livedisplay/inc/Lighting.h
@@ -0,0 +1,50 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_DISPLAYFEATURE_H
+#define CYNGN_DISPLAYFEATURE_H
+
+#include <utils/Errors.h>
+
+namespace android {
+
+// Natural light sources
+const int CANDLE[] = {255, 147, 41};
+const int TUNGSTEN_40W[] = {255, 197, 143};
+const int TUNGSTEN_100W[] = {255, 214, 170};
+const int HALOGEN[] = {255, 241, 224};
+const int CARBON_ARC[] = {255, 250, 244};
+const int HIGH_NOON_SUN[] = {255, 255, 251};
+const int DIRECT_SUNLIGHT[] = {255, 255, 255};
+const int OVERCAST_SKY[] = {201, 226, 255};
+const int CLEAR_BLUE_SKY[] = {64, 156, 255};
+
+// Fluorescent lights
+const int WARM[] = {255, 244, 229};
+const int STANDARD[] = {244, 255, 250};
+const int COOL_WHITE[] = {212, 235, 255};
+const int FULL_SPECTRUM[] = {255, 244, 242};
+const int GROW_LIGHT[] = {255, 239, 247};
+const int BLACK_LIGHT[] = {167, 0, 255};
+
+// Gas lights
+const int MERCURY_VAPOR[] = {216, 247, 255};
+const int SODIUM_VAPOR[] = {255, 209, 178};
+const int METAL_HALIDE[] = {242, 252, 255};
+const int HP_SODIUM[] = {255, 183, 76};
+};
+
+#endif
diff --git a/livedisplay/inc/LiveDisplay.h b/livedisplay/inc/LiveDisplay.h
new file mode 100644
index 0000000..8da282e
--- /dev/null
+++ b/livedisplay/inc/LiveDisplay.h
@@ -0,0 +1,87 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_LIVEDISPLAYBASE_H
+#define CYNGN_LIVEDISPLAYBASE_H
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/Singleton.h>
+
+#include "LiveDisplayBackend.h"
+#include "Types.h"
+
+namespace android {
+
+class LiveDisplay : public LiveDisplayAPI, public Singleton<LiveDisplay> {
+ friend class Singleton;
+
+ public:
+ bool hasFeature(Feature f) {
+ return connect() && (mFeatures & (uint32_t)f);
+ }
+
+ uint32_t getSupportedFeatures();
+
+ void reset();
+
+ virtual status_t setAdaptiveBacklightEnabled(bool enabled);
+ virtual bool isAdaptiveBacklightEnabled();
+
+ virtual status_t setOutdoorModeEnabled(bool enabled);
+ virtual bool isOutdoorModeEnabled();
+
+ virtual status_t getColorBalanceRange(Range& range);
+ virtual status_t setColorBalance(int32_t balance);
+ virtual int32_t getColorBalance();
+
+ virtual status_t getDisplayModes(List<sp<DisplayMode>>& profiles);
+ virtual status_t setDisplayMode(int32_t modeID, bool makeDefault);
+ virtual sp<DisplayMode> getCurrentDisplayMode();
+ virtual sp<DisplayMode> getDefaultDisplayMode();
+
+ virtual status_t getPictureAdjustmentRanges(HSICRanges& ranges);
+ virtual status_t getPictureAdjustment(HSIC& hsic);
+ virtual status_t getDefaultPictureAdjustment(HSIC& hsic);
+ virtual status_t setPictureAdjustment(HSIC hsic);
+
+ virtual ~LiveDisplay();
+ LiveDisplay();
+
+ private:
+ uint32_t mFeatures;
+ bool mConnected;
+
+ bool check(Feature f);
+ bool connect();
+ void error(const char* msg = NULL, ...);
+ bool isConnected() {
+ return mConnected;
+ }
+
+ void addFeature(Feature f) {
+ mFeatures |= (uint32_t)f;
+ };
+ void clearFeatures() {
+ mFeatures = 0;
+ };
+
+ LiveDisplayBackend* mBackend;
+ Mutex mLock;
+};
+};
+
+#endif
diff --git a/livedisplay/inc/LiveDisplayAPI.h b/livedisplay/inc/LiveDisplayAPI.h
new file mode 100644
index 0000000..1eae545
--- /dev/null
+++ b/livedisplay/inc/LiveDisplayAPI.h
@@ -0,0 +1,54 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_LIVEDISPLAYAPI_H
+#define CYNGN_LIVEDISPLAYAPI_H
+
+#include <utils/Errors.h>
+#include <utils/List.h>
+
+#include <Types.h>
+
+namespace android {
+
+class LiveDisplayAPI {
+ 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(List<sp<DisplayMode>>& profiles) = 0;
+ virtual status_t setDisplayMode(int32_t modeID, bool makeDefault) = 0;
+ virtual sp<DisplayMode> getCurrentDisplayMode() = 0;
+ virtual sp<DisplayMode> getDefaultDisplayMode() = 0;
+
+ virtual status_t getPictureAdjustmentRanges(HSICRanges& ranges) = 0;
+ virtual status_t getPictureAdjustment(HSIC& hsic) = 0;
+ virtual status_t getDefaultPictureAdjustment(HSIC& hsic) = 0;
+ virtual status_t setPictureAdjustment(HSIC hsic) = 0;
+
+ virtual ~LiveDisplayAPI() {
+ }
+};
+};
+
+#endif
diff --git a/livedisplay/inc/LiveDisplayBackend.h b/livedisplay/inc/LiveDisplayBackend.h
new file mode 100644
index 0000000..b56a6bd
--- /dev/null
+++ b/livedisplay/inc/LiveDisplayBackend.h
@@ -0,0 +1,37 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_LIVEDISPLAYBACKEND_H
+#define CYNGN_LIVEDISPLAYBACKEND_H
+
+#include <utils/Errors.h>
+
+#include <LiveDisplayAPI.h>
+
+namespace android {
+
+class LiveDisplayBackend : public LiveDisplayAPI {
+ public:
+ virtual status_t initialize() = 0;
+ virtual status_t deinitialize() = 0;
+ virtual bool hasFeature(Feature feature) = 0;
+
+ virtual ~LiveDisplayBackend() {
+ }
+};
+};
+
+#endif
diff --git a/livedisplay/inc/Types.h b/livedisplay/inc/Types.h
new file mode 100644
index 0000000..9044eb6
--- /dev/null
+++ b/livedisplay/inc/Types.h
@@ -0,0 +1,144 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_LIVEDISPLAY_TYPES_H
+#define CYNGN_LIVEDISPLAY_TYPES_H
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class Range {
+ public:
+ Range() : max(0), min(0), step(0) {
+ }
+ Range(int32_t _min, int32_t _max) : max(_max), min(_min) {
+ }
+ ~Range() {
+ }
+
+ int32_t max;
+ int32_t min;
+ uint32_t step;
+
+ bool isNonZero() {
+ return min != 0 || max != 0;
+ }
+};
+
+class FloatRange {
+ public:
+ FloatRange() : max(0.0), min(0.0), step(0.0) {
+ }
+ FloatRange(float _min, float _max) : max(_max), min(_min) {
+ }
+ ~FloatRange() {
+ }
+
+ float max;
+ float min;
+ float step;
+
+ bool isNonZero() {
+ return min != 0.0 || max != 0.0;
+ }
+};
+
+class HSIC {
+ public:
+ HSIC() : hue(0), saturation(0), intensity(0), contrast(0), saturationThreshold(0) {
+ }
+ HSIC(int32_t _hue, float _saturation, float _intensity, float _contrast,
+ float _saturationThreshold)
+ : hue(_hue),
+ saturation(_saturation),
+ intensity(_intensity),
+ contrast(_contrast),
+ saturationThreshold(_saturationThreshold) {
+ }
+ ~HSIC() {
+ }
+
+ void setTo(HSIC o) {
+ hue = o.hue;
+ saturation = o.saturation;
+ intensity = o.intensity;
+ contrast = o.contrast;
+ saturationThreshold = o.saturationThreshold;
+ }
+
+ int32_t hue;
+ float saturation;
+ float intensity;
+ float contrast;
+ float saturationThreshold;
+};
+
+class HSICRanges {
+ public:
+ 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 hue.isNonZero() && saturation.isNonZero() &&
+ intensity.isNonZero() && contrast.isNonZero();
+ }
+};
+
+class DisplayMode : public RefBase {
+ public:
+ DisplayMode() : id(-1) {
+ }
+
+ DisplayMode(int32_t _id, const char* _name, size_t _len) : id(_id) {
+ name.setTo(_name, _len);
+ }
+
+ int32_t id;
+ String8 name;
+
+ uint32_t privFlags;
+ String8 privData;
+};
+
+enum Level { OFF = -1, LOW, MEDIUM, HIGH, AUTO };
+
+enum Feature {
+ DISPLAY_MODES = 0x1,
+ COLOR_TEMPERATURE = 0x2,
+ OUTDOOR_MODE = 0x4,
+ ADAPTIVE_BACKLIGHT = 0x8,
+ PICTURE_ADJUSTMENT = 0x10,
+ MAX = PICTURE_ADJUSTMENT
+};
+};
+
+#endif
diff --git a/livedisplay/jni/jniutils.h b/livedisplay/jni/jniutils.h
new file mode 100644
index 0000000..6932f23
--- /dev/null
+++ b/livedisplay/jni/jniutils.h
@@ -0,0 +1,40 @@
+/*
+** Copyright 2016, The CyanogenMod 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 CYNGN_JNIUTILS_H
+#define CYNGN_JNIUTILS_H
+
+#include "JNIHelp.h"
+#include "jni.h"
+
+#define FIND_CLASS(var, className) \
+ var = env->FindClass(className); \
+ LOG_FATAL_IF(! var, "Unable to find class " className); \
+ var = jclass(env->NewGlobalRef(var));
+
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+ var = env->GetStaticMethodID(clazz, methodName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find static method" methodName);
+
+#define GET_METHOD_ID(var, clazz, methodName, fieldDescriptor) \
+ var = env->GetMethodID(clazz, methodName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find method" methodName);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+ var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+ LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
+#endif
diff --git a/livedisplay/jni/org_cyanogenmod_hardware_LiveDisplayVendorImpl.cpp b/livedisplay/jni/org_cyanogenmod_hardware_LiveDisplayVendorImpl.cpp
new file mode 100644
index 0000000..caeeafc
--- /dev/null
+++ b/livedisplay/jni/org_cyanogenmod_hardware_LiveDisplayVendorImpl.cpp
@@ -0,0 +1,444 @@
+/*
+** Copyright 2016, The CyanogenMod 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 "LiveDisplay-HW"
+
+#include "jniutils.h"
+
+#include "Types.h"
+#include "LiveDisplay.h"
+
+namespace android {
+
+static struct {
+ jclass clazz;
+ jmethodID constructor;
+ jfieldID id;
+ jfieldID name;
+} gDisplayModeClass;
+
+static struct {
+ jclass clazz;
+ jmethodID constructor;
+ jfieldID mHue;
+ jfieldID mSaturation;
+ jfieldID mIntensity;
+ jfieldID mContrast;
+ jfieldID mSaturationThreshold;
+} gHSICClass;
+
+static struct {
+ jclass clazz;
+ jmethodID constructor;
+} gRangeClass;
+
+static struct {
+ jclass clazz;
+ jmethodID constructor;
+} gFloatClass;
+
+static struct {
+ jclass clazz;
+ jmethodID constructor;
+} gIntegerClass;
+
+
+static jobject displayModeToObject(JNIEnv* env, sp<DisplayMode> mode)
+{
+ if (!mode.get() || mode->id < 0) {
+ return NULL;
+ }
+
+ return env->NewObject(gDisplayModeClass.clazz, gDisplayModeClass.constructor,
+ (jint) mode->id,
+ env->NewStringUTF(mode->name.string()));
+}
+
+static sp<DisplayMode> objectToDisplayMode(JNIEnv* env, jobject mode)
+{
+ jstring name = (jstring) env->GetObjectField(mode, gDisplayModeClass.name);
+ return new DisplayMode((int32_t) env->GetIntField(mode, gDisplayModeClass.id),
+ env->GetStringUTFChars(name, NULL),
+ env->GetStringUTFLength(name));
+}
+
+static jobject floatRangeToObject(JNIEnv* env, FloatRange range)
+{
+ jobject lower = env->NewObject(gFloatClass.clazz, gFloatClass.constructor,
+ (jfloat) range.min);
+
+ jobject upper = env->NewObject(gFloatClass.clazz, gFloatClass.constructor,
+ (jfloat) range.max);
+
+ return env->NewObject(gRangeClass.clazz, gRangeClass.constructor,
+ lower, upper);
+}
+
+static jobject intRangeToObject(JNIEnv* env, Range range)
+{
+ jobject lower = env->NewObject(gIntegerClass.clazz, gIntegerClass.constructor,
+ (jint) range.min);
+
+ jobject upper = env->NewObject(gIntegerClass.clazz, gIntegerClass.constructor,
+ (jint) range.max);
+
+ return env->NewObject(gRangeClass.clazz, gRangeClass.constructor,
+ lower, upper);
+}
+
+static jobject hsicToObject(JNIEnv* env, HSIC hsic)
+{
+ return env->NewObject(gHSICClass.clazz, gHSICClass.constructor,
+ (jfloat) hsic.hue, (jfloat) hsic.saturation,
+ (jfloat) hsic.intensity, (jfloat) hsic.contrast,
+ (jfloat) hsic.saturationThreshold);
+}
+
+static jint org_cyanogenmod_hardware_LiveDisplayVendorImpl_getSupportedFeatures(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ return (jint) LiveDisplay::getInstance().getSupportedFeatures();
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_isAdaptiveBacklightEnabled(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ return LiveDisplay::getInstance().isAdaptiveBacklightEnabled();
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_setAdaptiveBacklightEnabled(
+ JNIEnv* env __unused, jclass thiz __unused, jboolean enabled)
+{
+ return LiveDisplay::getInstance().setAdaptiveBacklightEnabled(enabled) == OK;
+}
+
+static jobjectArray org_cyanogenmod_hardware_LiveDisplayVendorImpl_getDisplayModes(
+ JNIEnv* env, jclass thiz __unused)
+{
+ List<sp<DisplayMode>> modes;
+ status_t rc = LiveDisplay::getInstance().getDisplayModes(modes);
+ if (rc != OK) {
+ return NULL;
+ }
+
+ jobjectArray modeList = env->NewObjectArray(modes.size(), gDisplayModeClass.clazz, NULL);
+ int i = 0;
+
+ if (rc == OK) {
+ for (List<sp<DisplayMode>>::iterator it = modes.begin();
+ it != modes.end(); ++it) {
+ const sp<DisplayMode> mode = *it;
+ env->SetObjectArrayElement(modeList, i,
+ displayModeToObject(env, mode));
+ i++;
+ }
+ }
+
+ return modeList;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getCurrentDisplayMode(
+ JNIEnv* env, jclass thiz __unused)
+{
+ return displayModeToObject(env,
+ LiveDisplay::getInstance().getCurrentDisplayMode());
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getDefaultDisplayMode(
+ JNIEnv* env, jclass thiz __unused)
+{
+ return displayModeToObject(env,
+ LiveDisplay::getInstance().getDefaultDisplayMode());
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_setDisplayMode(
+ JNIEnv* env, jclass thiz __unused, jobject mode, jboolean makeDefault)
+{
+ return LiveDisplay::getInstance().setDisplayMode(
+ objectToDisplayMode(env, mode)->id, makeDefault) == OK;
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_isOutdoorModeEnabled(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ return LiveDisplay::getInstance().isOutdoorModeEnabled();
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_setOutdoorModeEnabled(
+ JNIEnv* env __unused, jclass thiz __unused, jboolean enabled)
+{
+ return LiveDisplay::getInstance().setOutdoorModeEnabled(enabled) == OK;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getColorBalanceRange(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ Range range;
+ if (LiveDisplay::getInstance().getColorBalanceRange(range) == OK) {
+ return intRangeToObject(env, range);
+ }
+ return NULL;
+}
+
+static jint org_cyanogenmod_hardware_LiveDisplayVendorImpl_getColorBalance(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ return LiveDisplay::getInstance().getColorBalance();
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_setColorBalance(
+ JNIEnv* env __unused, jclass thiz __unused, jint value)
+{
+ return LiveDisplay::getInstance().setColorBalance(value) == OK;
+}
+
+static jboolean org_cyanogenmod_hardware_LiveDisplayVendorImpl_setPictureAdjustment(
+ JNIEnv* env __unused, jclass thiz __unused, jobject hsicObj)
+{
+ HSIC hsic(static_cast<int32_t>(env->GetFloatField(hsicObj, gHSICClass.mHue)),
+ env->GetFloatField(hsicObj, gHSICClass.mSaturation),
+ env->GetFloatField(hsicObj, gHSICClass.mIntensity),
+ env->GetFloatField(hsicObj, gHSICClass.mContrast),
+ env->GetFloatField(hsicObj, gHSICClass.mSaturationThreshold));
+
+ return LiveDisplay::getInstance().setPictureAdjustment(hsic) == OK;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getPictureAdjustment(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSIC hsic;
+
+ ALOGD("getPictureAdjustment");
+ if (LiveDisplay::getInstance().getPictureAdjustment(hsic) != OK) {
+ return NULL;
+ }
+
+ return hsicToObject(env, hsic);
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getDefaultPictureAdjustment(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSIC hsic;
+
+ ALOGD("getDefaultPictureAdjustment");
+ if (LiveDisplay::getInstance().getDefaultPictureAdjustment(hsic) != OK) {
+ return NULL;
+ }
+
+ return hsicToObject(env, hsic);
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getPictureAdjustmentRanges(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSICRanges ranges;
+ if (LiveDisplay::getInstance().getPictureAdjustmentRanges(ranges) == OK) {
+ jobjectArray modeList = env->NewObjectArray(5, gRangeClass.clazz, NULL);
+ env->SetObjectArrayElement(modeList, 0, intRangeToObject(env, ranges.hue));
+ env->SetObjectArrayElement(modeList, 1, floatRangeToObject(env, ranges.saturation));
+ env->SetObjectArrayElement(modeList, 2, floatRangeToObject(env, ranges.intensity));
+ env->SetObjectArrayElement(modeList, 3, floatRangeToObject(env, ranges.contrast));
+ env->SetObjectArrayElement(modeList, 4, floatRangeToObject(env, ranges.saturationThreshold));
+ return modeList;
+ }
+ return NULL;
+
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getHueRange(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSICRanges ranges;
+ if (LiveDisplay::getInstance().getPictureAdjustmentRanges(ranges) == OK) {
+ return floatRangeToObject(env, FloatRange(ranges.hue.min, ranges.hue.max));
+ }
+ return NULL;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getSaturationRange(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSICRanges ranges;
+ if (LiveDisplay::getInstance().getPictureAdjustmentRanges(ranges) == OK) {
+ return floatRangeToObject(env, ranges.saturation);
+ }
+ return NULL;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getIntensityRange(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSICRanges ranges;
+ if (LiveDisplay::getInstance().getPictureAdjustmentRanges(ranges) == OK) {
+ return floatRangeToObject(env, ranges.intensity);
+ }
+ return NULL;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getContrastRange(
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSICRanges ranges;
+ if (LiveDisplay::getInstance().getPictureAdjustmentRanges(ranges) == OK) {
+ return floatRangeToObject(env, ranges.contrast);
+ }
+ return NULL;
+}
+
+static jobject org_cyanogenmod_hardware_LiveDisplayVendorImpl_getSaturationThresholdRange (
+ JNIEnv* env __unused, jclass thiz __unused)
+{
+ HSICRanges ranges;
+ if (LiveDisplay::getInstance().getPictureAdjustmentRanges(ranges) == OK) {
+ return floatRangeToObject(env, ranges.saturationThreshold);
+ }
+ return NULL;
+}
+
+
+static JNINativeMethod gLiveDisplayVendorImplMethods[] = {
+ { "native_getSupportedFeatures",
+ "()I",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getSupportedFeatures },
+ { "native_isAdaptiveBacklightEnabled",
+ "()Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_isAdaptiveBacklightEnabled },
+ { "native_setAdaptiveBacklightEnabled",
+ "(Z)Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_setAdaptiveBacklightEnabled },
+ { "native_getDisplayModes",
+ "()[Lcyanogenmod/hardware/DisplayMode;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getDisplayModes },
+ { "native_getCurrentDisplayMode",
+ "()Lcyanogenmod/hardware/DisplayMode;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getCurrentDisplayMode },
+ { "native_getDefaultDisplayMode",
+ "()Lcyanogenmod/hardware/DisplayMode;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getDefaultDisplayMode },
+ { "native_setDisplayMode",
+ "(Lcyanogenmod/hardware/DisplayMode;Z)Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_setDisplayMode },
+ { "native_isOutdoorModeEnabled",
+ "()Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_isOutdoorModeEnabled },
+ { "native_setOutdoorModeEnabled",
+ "(Z)Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_setOutdoorModeEnabled },
+ { "native_getColorBalanceRange",
+ "()Landroid/util/Range;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getColorBalanceRange },
+ { "native_getColorBalance",
+ "()I",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getColorBalance },
+ { "native_setColorBalance",
+ "(I)Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_setColorBalance },
+ { "native_setPictureAdjustment",
+ "(Lcyanogenmod/hardware/HSIC;)Z",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_setPictureAdjustment },
+ { "native_getPictureAdjustment",
+ "()Lcyanogenmod/hardware/HSIC;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getPictureAdjustment },
+ { "native_getDefaultPictureAdjustment",
+ "()Lcyanogenmod/hardware/HSIC;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getDefaultPictureAdjustment },
+ { "native_getHueRange",
+ "()Landroid/util/Range;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getHueRange },
+ { "native_getSaturationRange",
+ "()Landroid/util/Range;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getSaturationRange },
+ { "native_getIntensityRange",
+ "()Landroid/util/Range;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getIntensityRange },
+ { "native_getContrastRange",
+ "()Landroid/util/Range;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getContrastRange },
+ { "native_getSaturationThresholdRange",
+ "()Landroid/util/Range;",
+ (void *)org_cyanogenmod_hardware_LiveDisplayVendorImpl_getSaturationThresholdRange },
+};
+
+
+static int register_org_cyanogenmod_hardware_LiveDisplayVendorImpl(JNIEnv *env)
+{
+ FIND_CLASS(gDisplayModeClass.clazz,
+ "cyanogenmod/hardware/DisplayMode");
+ GET_METHOD_ID(gDisplayModeClass.constructor,
+ gDisplayModeClass.clazz, "<init>", "(ILjava/lang/String;)V");
+ GET_FIELD_ID(gDisplayModeClass.id,
+ gDisplayModeClass.clazz, "id", "I");
+ GET_FIELD_ID(gDisplayModeClass.name,
+ gDisplayModeClass.clazz, "name", "Ljava/lang/String;");
+
+ FIND_CLASS(gHSICClass.clazz,
+ "cyanogenmod/hardware/HSIC");
+ GET_METHOD_ID(gHSICClass.constructor,
+ gHSICClass.clazz, "<init>", "(FFFFF)V");
+ GET_FIELD_ID(gHSICClass.mHue,
+ gHSICClass.clazz, "mHue", "F");
+ GET_FIELD_ID(gHSICClass.mSaturation,
+ gHSICClass.clazz, "mSaturation", "F");
+ GET_FIELD_ID(gHSICClass.mIntensity,
+ gHSICClass.clazz, "mIntensity", "F");
+ GET_FIELD_ID(gHSICClass.mContrast,
+ gHSICClass.clazz, "mContrast", "F");
+ GET_FIELD_ID(gHSICClass.mSaturationThreshold,
+ gHSICClass.clazz, "mSaturationThreshold", "F");
+
+ FIND_CLASS(gRangeClass.clazz,
+ "android/util/Range");
+ GET_METHOD_ID(gRangeClass.constructor,
+ gRangeClass.clazz, "<init>", "(Ljava/lang/Comparable;Ljava/lang/Comparable;)V");
+
+ FIND_CLASS(gFloatClass.clazz, "java/lang/Float");
+ GET_METHOD_ID(gFloatClass.constructor,
+ gFloatClass.clazz, "<init>", "(F)V");
+
+ FIND_CLASS(gIntegerClass.clazz, "java/lang/Integer");
+ GET_METHOD_ID(gIntegerClass.constructor,
+ gIntegerClass.clazz, "<init>", "(I)V");
+
+
+ int rc = jniRegisterNativeMethods(env,
+ "org/cyanogenmod/hardware/LiveDisplayVendorImpl",
+ gLiveDisplayVendorImplMethods,
+ NELEM(gLiveDisplayVendorImplMethods));
+ ALOGD("LiveDisplay registerNatives = %d", rc);
+ return rc;
+}
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved __unused)
+{
+ JNIEnv* env = NULL;
+ jint result = -1;
+
+ ALOGD("LiveDisplay JNI ONLOAD");
+
+ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+ ALOGE("GetEnv failed!");
+ return result;
+ }
+ ALOG_ASSERT(env, "Could not retrieve the env!");
+
+ register_org_cyanogenmod_hardware_LiveDisplayVendorImpl(env);
+
+ return JNI_VERSION_1_4;
+}
+
+};
diff --git a/livedisplay/src/LiveDisplay.cpp b/livedisplay/src/LiveDisplay.cpp
new file mode 100644
index 0000000..06d6957
--- /dev/null
+++ b/livedisplay/src/LiveDisplay.cpp
@@ -0,0 +1,285 @@
+/*
+** Copyright 2016, The CyanogenMod 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 "LiveDisplay-HW"
+
+#include <cutils/properties.h>
+#include <stdarg.h>
+
+#include "LiveDisplay.h"
+
+#include "LegacyMM.h"
+#include "SDM.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(LiveDisplay)
+
+LiveDisplay::LiveDisplay() : mConnected(false), mBackend(NULL) {
+ char board[PROPERTY_VALUE_MAX];
+ property_get("ro.board.platform", board, NULL);
+
+ if (!strcmp(board, "msm8916") || !strcmp(board, "msm8939") || !strcmp(board, "msm8992") ||
+ !strcmp(board, "msm8974") || !strcmp(board, "msm8994")) {
+ mBackend = new LegacyMM();
+ } else if (!strcmp(board, "msm8996") || !strcmp(board, "msm8937") ||
+ !strcmp(board, "msm8953") || !strcmp(board, "msm8976")) {
+ mBackend = new SDM();
+ } else {
+ mBackend = NULL;
+ return;
+ }
+ ALOGD("Loaded LiveDisplay native interface");
+}
+
+LiveDisplay::~LiveDisplay() {
+ reset();
+}
+
+void LiveDisplay::reset() {
+ if (mConnected) {
+ mBackend->deinitialize();
+ }
+ mFeatures = 0;
+ mConnected = false;
+}
+
+void LiveDisplay::error(const char* msg, ...) {
+ if (msg != NULL) {
+ va_list args;
+ ALOGE(msg, args);
+ }
+
+ reset();
+}
+
+bool LiveDisplay::connect() {
+ if (mConnected) {
+ return true;
+ }
+
+ mFeatures = 0;
+
+ if (mBackend == NULL) {
+ return false;
+ }
+
+ if (mBackend->initialize() != OK) {
+ ALOGE("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;
+}
+
+uint32_t LiveDisplay::getSupportedFeatures() {
+ connect();
+ return mFeatures;
+}
+
+bool LiveDisplay::check(Feature f) {
+ return hasFeature(f) && connect();
+}
+
+//----------------------------------------------------------------------------/
+
+status_t LiveDisplay::getDisplayModes(List<sp<DisplayMode>>& modes) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ rc = mBackend->getDisplayModes(modes);
+ if (rc != OK) {
+ error("Unable to fetch display modes!");
+ }
+ }
+ return rc;
+}
+
+sp<DisplayMode> LiveDisplay::getDefaultDisplayMode() {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ return mBackend->getDefaultDisplayMode();
+ }
+ return nullptr;
+}
+
+sp<DisplayMode> LiveDisplay::getCurrentDisplayMode() {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::DISPLAY_MODES)) {
+ return mBackend->getCurrentDisplayMode();
+ }
+ return nullptr;
+}
+
+status_t LiveDisplay::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;
+}
+
+status_t LiveDisplay::getColorBalanceRange(Range& range) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::COLOR_TEMPERATURE)) {
+ rc = mBackend->getColorBalanceRange(range);
+ if (rc != OK) {
+ error("Unable to fetch color balance range!");
+ }
+ }
+ return rc;
+}
+
+int LiveDisplay::getColorBalance() {
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::COLOR_TEMPERATURE)) {
+ return mBackend->getColorBalance();
+ }
+
+ return 0;
+}
+
+status_t LiveDisplay::setColorBalance(int value) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::COLOR_TEMPERATURE)) {
+ rc = mBackend->setColorBalance(value);
+ if (rc != OK) {
+ error("Unable to set color balance!");
+ }
+ }
+ return rc;
+}
+
+bool LiveDisplay::isOutdoorModeEnabled() {
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::OUTDOOR_MODE)) {
+ return mBackend->isOutdoorModeEnabled();
+ }
+ return false;
+}
+
+status_t LiveDisplay::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;
+}
+
+bool LiveDisplay::isAdaptiveBacklightEnabled() {
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::ADAPTIVE_BACKLIGHT)) {
+ return mBackend->isAdaptiveBacklightEnabled();
+ }
+ return false;
+}
+
+status_t LiveDisplay::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;
+}
+
+status_t LiveDisplay::getPictureAdjustment(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 get picture adjustment!");
+ }
+ }
+ return rc;
+}
+
+status_t LiveDisplay::getDefaultPictureAdjustment(HSIC& hsic) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ rc = mBackend->getDefaultPictureAdjustment(hsic);
+ if (rc != OK) {
+ error("Unable to get default picture adjustment!");
+ }
+ }
+ return rc;
+}
+
+
+status_t LiveDisplay::setPictureAdjustment(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;
+}
+
+status_t LiveDisplay::getPictureAdjustmentRanges(HSICRanges& ranges) {
+ status_t rc = NO_INIT;
+ Mutex::Autolock _l(mLock);
+
+ if (check(Feature::PICTURE_ADJUSTMENT)) {
+ rc = mBackend->getPictureAdjustmentRanges(ranges);
+ if (rc != OK) {
+ error("Unable to get picture adjustment ranges!");
+ }
+ }
+ return rc;
+}
+};
diff --git a/livedisplay/test/Android.mk b/livedisplay/test/Android.mk
new file mode 100644
index 0000000..52f858d
--- /dev/null
+++ b/livedisplay/test/Android.mk
@@ -0,0 +1,9 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := pp_client
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libcutils
+LOCAL_SRC_FILES := pp_client.c
+include $(BUILD_EXECUTABLE)
+
diff --git a/livedisplay/test/pp_client.c b/livedisplay/test/pp_client.c
new file mode 100644
index 0000000..706d779
--- /dev/null
+++ b/livedisplay/test/pp_client.c
@@ -0,0 +1,67 @@
+/*
+** Copyright 2016, The CyanogenMod 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 <string.h>
+#include <unistd.h>
+
+#include "cutils/sockets.h"
+
+#define BUF_SZ 4096
+
+static void send_pp_cmd(char *buf, size_t len)
+{
+ int sock = socket_local_client("pps",
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ if (sock >= 0) {
+ 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;
+ }
+ }
+ }
+ close(sock);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ char *buf = malloc(BUF_SZ);
+ printf("Send cmd: %s\n", argv[1]);
+ sprintf(buf, "%s", argv[1]);
+ send_pp_cmd(buf, BUF_SZ);
+ printf("Reply: %s\n", buf);
+}