summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2016-08-23 02:37:56 -0700
committerSteve Kondik <steve@cyngn.com>2016-08-23 02:37:56 -0700
commit74128e2849286af0ad3b0b19b140887e1a8b59db (patch)
tree7c74b942e634fc948f576f8739531c000ca5113e
parentec15025b00e200249af05813b9582eb8e6998e78 (diff)
downloadandroid_hardware_cyanogen-cm-13.0.tar.gz
android_hardware_cyanogen-cm-13.0.tar.bz2
android_hardware_cyanogen-cm-13.0.zip
* This code implements the LiveDisplay native interface and includes support for Qualcomm's SDM as well as the previous MM interface. 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 was developed by Steve Kondik with assistance from Scott Mertz. Various bits of CYNGN proprietary IP have been removed. FUTURE WORK: - Refactor CMHardwareService and LiveDisplayService to eliminate useless abstractions and consolidate code. - This is an awful lot of code which is loaded into system_server. It would be wise to refactor it into a daemon process or standalone service. The Java portion does need to remain memory resident in order to respond to sensor events and changes in ambient conditions without risk of being OOM killed. Change-Id: I906a2f3aa1ba3e32881c6d49587f424e094521d6
-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);
+}