livedisplay: Add support for direct color balance control
* We currently use the DisplayColorCalibration API for setting display temperature which makes a lot of guesses about what temperature the display really is. Some devices will support the new ColorBalance API (via QDCM or other mechanism), which offers a calibrated alternative. Add support for this, which will supercede DCC if available. * Additionally, define the available color temperature range as a set of overlayable values so this can be specified per-device. This range will be mapped to balance values using the power curve calculations in the new MathUtils class. Change-Id: I99608c09807b747d962680293c7b0cee8d669003
This commit is contained in:
@@ -20,6 +20,7 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
import android.util.Range;
|
||||
|
||||
import cyanogenmod.app.CMContextConstants;
|
||||
|
||||
@@ -129,6 +130,11 @@ public final class CMHardwareManager {
|
||||
*/
|
||||
public static final int FEATURE_UNIQUE_DEVICE_ID = 0x10000;
|
||||
|
||||
/**
|
||||
* Color balance
|
||||
*/
|
||||
public static final int FEATURE_COLOR_BALANCE = 0x20000;
|
||||
|
||||
private static final List<Integer> BOOLEAN_FEATURES = Arrays.asList(
|
||||
FEATURE_ADAPTIVE_BACKLIGHT,
|
||||
FEATURE_COLOR_ENHANCEMENT,
|
||||
@@ -803,6 +809,39 @@ public final class CMHardwareManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Range<Integer> getColorBalanceRange() {
|
||||
int min = 0;
|
||||
int max = 0;
|
||||
try {
|
||||
if (checkService()) {
|
||||
min = sService.getColorBalanceMin();
|
||||
max = sService.getColorBalanceMax();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return new Range<Integer>(min, max);
|
||||
}
|
||||
|
||||
public int getColorBalance() {
|
||||
try {
|
||||
if (checkService()) {
|
||||
return sService.getColorBalance();
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean setColorBalance(int value) {
|
||||
try {
|
||||
if (checkService()) {
|
||||
return sService.setColorBalance(value);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if service is valid
|
||||
*/
|
||||
|
||||
@@ -58,4 +58,9 @@ interface ICMHardwareService {
|
||||
boolean isSunlightEnhancementSelfManaged();
|
||||
|
||||
String getUniqueDeviceId();
|
||||
|
||||
int getColorBalanceMin();
|
||||
int getColorBalanceMax();
|
||||
int getColorBalance();
|
||||
boolean setColorBalance(int value);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import static cyanogenmod.hardware.LiveDisplayManager.MODE_OFF;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Range;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
@@ -50,10 +51,15 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
private final boolean mDefaultCABC;
|
||||
private final boolean mDefaultColorEnhancement;
|
||||
|
||||
private final Range<Integer> mColorTemperatureRange;
|
||||
private final Range<Integer> mColorBalanceRange;
|
||||
|
||||
public LiveDisplayConfig(BitSet capabilities, int defaultMode,
|
||||
int defaultDayTemperature, int defaultNightTemperature,
|
||||
boolean defaultAutoOutdoorMode, boolean defaultAutoContrast,
|
||||
boolean defaultCABC, boolean defaultColorEnhancement) {
|
||||
boolean defaultCABC, boolean defaultColorEnhancement,
|
||||
Range<Integer> colorTemperatureRange,
|
||||
Range<Integer> colorBalanceRange) {
|
||||
super();
|
||||
mCapabilities = (BitSet) capabilities.clone();
|
||||
mAllModes.set(MODE_FIRST, MODE_LAST);
|
||||
@@ -64,6 +70,8 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
mDefaultAutoOutdoorMode = defaultAutoOutdoorMode;
|
||||
mDefaultCABC = defaultCABC;
|
||||
mDefaultColorEnhancement = defaultColorEnhancement;
|
||||
mColorTemperatureRange = colorTemperatureRange;
|
||||
mColorBalanceRange = colorBalanceRange;
|
||||
}
|
||||
|
||||
private LiveDisplayConfig(Parcel parcel) {
|
||||
@@ -80,6 +88,10 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
boolean defaultAutoOutdoorMode = false;
|
||||
boolean defaultCABC = false;
|
||||
boolean defaultColorEnhancement = false;
|
||||
int minColorTemperature = 0;
|
||||
int maxColorTemperature = 0;
|
||||
int minColorBalance = 0;
|
||||
int maxColorBalance = 0;
|
||||
|
||||
if (parcelableVersion >= Build.CM_VERSION_CODES.FIG) {
|
||||
capabilities = parcel.readLong();
|
||||
@@ -90,6 +102,10 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
defaultAutoOutdoorMode = parcel.readInt() == 1;
|
||||
defaultCABC = parcel.readInt() == 1;
|
||||
defaultColorEnhancement = parcel.readInt() == 1;
|
||||
minColorTemperature = parcel.readInt();
|
||||
maxColorTemperature = parcel.readInt();
|
||||
minColorBalance = parcel.readInt();
|
||||
maxColorBalance = parcel.readInt();
|
||||
}
|
||||
|
||||
// set temps
|
||||
@@ -102,6 +118,8 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
mDefaultAutoOutdoorMode = defaultAutoOutdoorMode;
|
||||
mDefaultCABC = defaultCABC;
|
||||
mDefaultColorEnhancement = defaultColorEnhancement;
|
||||
mColorTemperatureRange = Range.create(minColorTemperature, maxColorTemperature);
|
||||
mColorBalanceRange = Range.create(minColorBalance, maxColorBalance);
|
||||
|
||||
// Complete parcel info for the concierge
|
||||
parcelInfo.complete();
|
||||
@@ -118,6 +136,8 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
sb.append(" defaultAutoContrast=").append(mDefaultAutoContrast);
|
||||
sb.append(" defaultCABC=").append(mDefaultCABC);
|
||||
sb.append(" defaultColorEnhancement=").append(mDefaultColorEnhancement);
|
||||
sb.append(" colorTemperatureRange=").append(mColorTemperatureRange);
|
||||
sb.append(" colorBalanceRange=").append(mColorBalanceRange);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -141,6 +161,10 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
out.writeInt(mDefaultAutoOutdoorMode ? 1 : 0);
|
||||
out.writeInt(mDefaultCABC ? 1 : 0);
|
||||
out.writeInt(mDefaultColorEnhancement ? 1 : 0);
|
||||
out.writeInt(mColorTemperatureRange.getLower());
|
||||
out.writeInt(mColorTemperatureRange.getUpper());
|
||||
out.writeInt(mColorBalanceRange.getLower());
|
||||
out.writeInt(mColorBalanceRange.getUpper());
|
||||
|
||||
// Complete the parcel info for the concierge
|
||||
parcelInfo.complete();
|
||||
@@ -243,6 +267,24 @@ public class LiveDisplayConfig implements Parcelable {
|
||||
return mDefaultColorEnhancement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range of supported color temperatures
|
||||
*
|
||||
* @return range in Kelvin
|
||||
*/
|
||||
public Range<Integer> getColorTemperatureRange() {
|
||||
return mColorTemperatureRange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the range of supported color balance
|
||||
*
|
||||
* @return linear range which maps into the temperature range curve
|
||||
*/
|
||||
public Range<Integer> getColorBalanceRange() {
|
||||
return mColorBalanceRange;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public static final Parcelable.Creator<LiveDisplayConfig> CREATOR =
|
||||
new Parcelable.Creator<LiveDisplayConfig>() {
|
||||
|
||||
@@ -102,10 +102,17 @@ public class LiveDisplayManager {
|
||||
*/
|
||||
public static final int FEATURE_DISPLAY_MODES = 15;
|
||||
|
||||
/**
|
||||
* System supports direct range-based control of display
|
||||
* color balance (temperature). This is preferred over
|
||||
* simple RGB adjustment.
|
||||
*/
|
||||
public static final int FEATURE_COLOR_BALANCE = 16;
|
||||
|
||||
/** @hide */
|
||||
public static final int FEATURE_FIRST = FEATURE_CABC;
|
||||
/** @hide */
|
||||
public static final int FEATURE_LAST = FEATURE_DISPLAY_MODES;
|
||||
public static final int FEATURE_LAST = FEATURE_COLOR_BALANCE;
|
||||
|
||||
private static final String TAG = "LiveDisplay";
|
||||
|
||||
|
||||
@@ -1311,7 +1311,7 @@ public final class CMSettings {
|
||||
|
||||
/** @hide */
|
||||
public static final Validator DISPLAY_TEMPERATURE_DAY_VALIDATOR =
|
||||
new InclusiveIntegerRangeValidator(1000, 10000);
|
||||
new InclusiveIntegerRangeValidator(0, 100000);
|
||||
|
||||
/**
|
||||
* Color temperature of the display at night
|
||||
@@ -1320,7 +1320,7 @@ public final class CMSettings {
|
||||
|
||||
/** @hide */
|
||||
public static final Validator DISPLAY_TEMPERATURE_NIGHT_VALIDATOR =
|
||||
new InclusiveIntegerRangeValidator(1000, 10000);
|
||||
new InclusiveIntegerRangeValidator(0, 100000);
|
||||
|
||||
/**
|
||||
* Display color temperature adjustment mode, one of DAY (default), NIGHT, or AUTO.
|
||||
|
||||
67
sdk/src/java/org/cyanogenmod/internal/util/MathUtils.java
Normal file
67
sdk/src/java/org/cyanogenmod/internal/util/MathUtils.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
package org.cyanogenmod.internal.util;
|
||||
|
||||
public final class MathUtils {
|
||||
|
||||
/**
|
||||
* Given a range of values which change continuously in a non-linear way,
|
||||
* we can map back and forth to a linear scale using some quadratic equations.
|
||||
*
|
||||
* The linear scale ranges from 0 -> 1. This method will calculate the
|
||||
* coefficients needed to solve the conversion functions in the next two methods.
|
||||
*
|
||||
* lower = actual value when linear value = 0
|
||||
* mid = actual value when linear value = .5
|
||||
* upper actual value when linear value = 1
|
||||
*
|
||||
* @param lower
|
||||
* @param mid
|
||||
* @param upper
|
||||
* @return array of coefficients
|
||||
*/
|
||||
public static double[] powerCurve(double lower, double mid, double upper) {
|
||||
final double[] curve = new double[3];
|
||||
curve[0] = ((lower * upper) - (mid * mid)) / (lower - (2 * mid) + upper);
|
||||
curve[1] = Math.pow((mid - lower), 2) / (lower - (2 * mid) + upper);
|
||||
curve[2] = 2 * Math.log((upper - mid) / (mid - lower));
|
||||
return curve;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a value on a power curve to a linear value
|
||||
*
|
||||
* @param curve obtained from powerCurve()
|
||||
* @param value to convert to linear scale
|
||||
* @return linear value from 0 -> 1
|
||||
*/
|
||||
public static double powerCurveToLinear(final double[] curve, double value) {
|
||||
return Math.log((value - curve[0]) / curve[1]) / curve[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a value on a linear scale to a value on a power curve
|
||||
*
|
||||
* @param curve obtained from powerCurve()
|
||||
* @param value from 0 -> 1 to map onto power curve
|
||||
* @return actual value on the given curve
|
||||
*/
|
||||
public static double linearToPowerCurve(final double[] curve, double value) {
|
||||
return curve[0] + curve[1] * Math.exp(curve[2] * value);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user