blob: ce613a88f6848e01b310aa3bb247231330a011b6 [file] [log] [blame]
/*
** Copyright 2016, The CyanogenMod Project
** Copyright (C) 2017-2018 The LineageOS Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
// #define LOG_NDEBUG 0
#define LOG_TAG "LiveDisplay-LegacyMM"
#include "impl/LegacyMM.h"
#include "controller/LegacyMMController.h"
#include "Utils.h"
#include <android-base/logging.h>
namespace {
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;
};
} // anonymous namespace
namespace vendor {
namespace lineage {
namespace livedisplay {
namespace V1_0 {
namespace implementation {
using android::BAD_VALUE;
using android::NO_INIT;
using android::OK;
using android::sp;
using android::status_t;
LegacyMM::LegacyMM() {
memset(&mDefaultPictureAdjustment, 0, sizeof(HSIC));
mController = std::make_unique<LegacyMMController>();
if (mController == nullptr) {
LOG(ERROR) << "Failed to create LegacyMMController";
return;
}
status_t rc = mController->init(0);
if (rc != OK) {
LOG(ERROR) << "Failed to initialize LegacyMMController";
return;
}
if (hasFeature(Feature::DISPLAY_MODES)) {
int32_t id;
// Get the initial mode from Utils
rc = Utils::readInitialModeId(&id);
if (rc != OK || id < 0) {
// Get controller default mode and save it
rc = mController->get_default_display_mode(0, &id);
if (rc == OK && id >= 0) {
Utils::writeInitialModeId(id);
} else {
Utils::writeInitialModeId(0);
}
}
auto mode = getDefaultDisplayMode();
if (mode != nullptr) {
setDisplayMode(mode->id, false);
}
}
}
LegacyMM::~LegacyMM() {
status_t rc = mController->init(1);
if (rc != OK) {
LOG(ERROR) << "Failed to deinitialize LegacyMMController";
}
}
status_t LegacyMM::getColorBalanceRange(Range& range) {
struct mm_range r;
memset(&r, 0, sizeof(struct mm_range));
status_t rc = mController->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 mController->set_color_balance(0, balance);
}
int32_t LegacyMM::getColorBalance() {
int32_t value = 0;
if (mController->get_color_balance(0, &value) != 0) {
value = 0;
}
return value;
}
status_t LegacyMM::getDisplayModes(std::vector<sp<disp_mode>>& profiles) {
status_t rc = OK;
uint32_t count = getNumDisplayModes();
if (!count) {
return rc;
}
struct d_mode {
int id;
char* name;
uint32_t len;
int32_t type;
d_mode() : id(-1), len(128), type(0) {
name = new char[128];
}
~d_mode() {
delete name;
}
};
d_mode tmp[count];
rc = mController->get_display_modes(0, 0, tmp, count);
if (rc == 0) {
for (uint32_t i = 0; i < count; i++) {
const sp<disp_mode> m = new disp_mode;
m->id = tmp[i].id;
m->name = tmp[i].name;
m->privFlags = 0; // TODO: fix flag
profiles.push_back(m);
}
}
return rc;
}
status_t LegacyMM::setDisplayMode(int32_t modeID, bool makeDefault) {
auto currentMode = getCurrentDisplayMode();
if (currentMode != nullptr && currentMode->id == modeID) {
return OK;
}
auto mode = getDisplayModeById(modeID);
if (mode == nullptr) {
return BAD_VALUE;
}
if (mController->set_active_display_mode(0, modeID) != 0) {
return BAD_VALUE;
}
if (makeDefault && mController->set_default_display_mode(0, modeID) != 0) {
return BAD_VALUE;
}
HSIC tmp;
if (getPictureAdjustment(tmp) == OK) {
mDefaultPictureAdjustment = tmp;
}
return OK;
}
sp<disp_mode> LegacyMM::getCurrentDisplayMode() {
int32_t id = 0;
uint32_t mask = 0;
status_t rc = mController->get_active_display_mode(0, &id, &mask);
if (rc == OK && id >= 0) {
return getDisplayModeById(id);
}
return nullptr;
}
sp<disp_mode> LegacyMM::getDefaultDisplayMode() {
int32_t id = 0;
if (Utils::readLocalModeId(&id) == OK && id >= 0) {
return getDisplayModeById(id);
}
if (Utils::readInitialModeId(&id) == OK && id >= 0) {
return getDisplayModeById(id);
}
status_t rc = mController->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 = mController->get_pa_range(0, &r);
if (rc == OK) {
ranges.hue.min = r.min.hue;
ranges.hue.max = r.max.hue;
ranges.hue.step = 1;
ranges.saturation.min = r.min.saturation;
ranges.saturation.max = r.max.saturation;
ranges.saturation.step = 1;
ranges.intensity.min = r.min.intensity;
ranges.intensity.max = r.max.intensity;
ranges.intensity.step = 1;
ranges.contrast.min = r.min.contrast;
ranges.contrast.max = r.max.contrast;
ranges.contrast.step = 1;
ranges.saturationThreshold.min = r.min.saturationThreshold;
ranges.saturationThreshold.max = r.max.saturationThreshold;
ranges.saturationThreshold.step = 1;
}
return rc;
}
status_t LegacyMM::getPictureAdjustment(HSIC& hsic) {
struct mm_pa_config config;
memset(&config, 0, sizeof(struct mm_pa_config));
status_t rc = mController->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;
}
HSIC LegacyMM::getDefaultPictureAdjustment() {
return mDefaultPictureAdjustment;
}
status_t LegacyMM::setPictureAdjustment(const 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 mController->set_pa_config(0, &config);
}
bool LegacyMM::hasFeature(Feature feature) {
uint32_t id;
switch (feature) {
case Feature::COLOR_BALANCE:
id = 0;
break;
case Feature::DISPLAY_MODES:
id = 1;
break;
case Feature::PICTURE_ADJUSTMENT:
id = 4;
break;
default:
return false;
}
if (mController->supported(0, id)) {
// display modes and color balance depend on each other
if (feature == Feature::DISPLAY_MODES || feature == Feature::COLOR_BALANCE) {
if (getNumDisplayModes() > 0) {
// make sure the range isn't zero
if (feature == Feature::COLOR_BALANCE) {
Range r;
if (getColorBalanceRange(r) == OK && isNonZero(r)) {
return true;
}
return false;
}
return true;
}
}
if (feature == Feature::PICTURE_ADJUSTMENT) {
HSICRanges r;
if (getPictureAdjustmentRanges(r) == OK && r.isValid()) {
return true;
}
}
}
return false;
}
uint32_t LegacyMM::getNumDisplayModes() {
uint32_t count = 0;
if (mController->get_num_display_modes(0, 0, &count) != 0) {
count = 0;
}
return count;
}
sp<disp_mode> LegacyMM::getDisplayModeById(int32_t id) {
std::vector<sp<disp_mode>> profiles;
status_t rc = getDisplayModes(profiles);
if (rc == OK) {
for (const auto& mode : profiles) {
if (id == mode->id) {
return mode;
}
}
}
return nullptr;
}
} // namespace implementation
} // namespace V1_0
} // namespace livedisplay
} // namespace lineage
} // namespace vendor