diff options
| -rw-r--r-- | livedisplay/.clang-format | 13 | ||||
| -rw-r--r-- | livedisplay/Android.mk | 54 | ||||
| -rw-r--r-- | livedisplay/impl/LegacyMM.cpp | 336 | ||||
| -rw-r--r-- | livedisplay/impl/LegacyMM.h | 108 | ||||
| -rw-r--r-- | livedisplay/impl/SDM.cpp | 506 | ||||
| -rw-r--r-- | livedisplay/impl/SDM.h | 123 | ||||
| -rw-r--r-- | livedisplay/impl/Utils.cpp | 117 | ||||
| -rw-r--r-- | livedisplay/impl/Utils.h | 43 | ||||
| -rw-r--r-- | livedisplay/inc/Lighting.h | 50 | ||||
| -rw-r--r-- | livedisplay/inc/LiveDisplay.h | 87 | ||||
| -rw-r--r-- | livedisplay/inc/LiveDisplayAPI.h | 54 | ||||
| -rw-r--r-- | livedisplay/inc/LiveDisplayBackend.h | 37 | ||||
| -rw-r--r-- | livedisplay/inc/Types.h | 144 | ||||
| -rw-r--r-- | livedisplay/jni/jniutils.h | 40 | ||||
| -rw-r--r-- | livedisplay/jni/org_cyanogenmod_hardware_LiveDisplayVendorImpl.cpp | 444 | ||||
| -rw-r--r-- | livedisplay/src/LiveDisplay.cpp | 285 | ||||
| -rw-r--r-- | livedisplay/test/Android.mk | 9 | ||||
| -rw-r--r-- | livedisplay/test/pp_client.c | 67 |
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); +} |
