summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/livedisplay
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2015-02-18 03:44:31 -0800
committerAdnan Begovic <adnan@cyngn.com>2015-10-29 17:36:30 -0700
commite65f2833df18e755c847bc86376253a4b96e73f9 (patch)
treee61b573057968f05218a0ad697dd38183bf81149 /src/com/android/settings/livedisplay
parent8f57a61603b7bc2fca99a510cb6c8188fb9612d2 (diff)
downloadpackages_apps_Settings-e65f2833df18e755c847bc86376253a4b96e73f9.zip
packages_apps_Settings-e65f2833df18e755c847bc86376253a4b96e73f9.tar.gz
packages_apps_Settings-e65f2833df18e755c847bc86376253a4b96e73f9.tar.bz2
livedisplay: Add LiveDisplay settings
* Add preference for LiveDisplay mode, and additional supporting options for auto mode. * CABC, SRE, CE are all under this umbrella now. * Manual RGB tweaking is now handled here and the requirement for CMHW has been removed as it will go thru RenderEngine. * Moved all related code into the livedisplay package. Change-Id: I0b00f2bfd8f8227d64ad271bbe0f004f0b4bcf9d
Diffstat (limited to 'src/com/android/settings/livedisplay')
-rw-r--r--src/com/android/settings/livedisplay/DisplayColor.java255
-rw-r--r--src/com/android/settings/livedisplay/DisplayGamma.java341
-rw-r--r--src/com/android/settings/livedisplay/DisplayTemperature.java260
-rw-r--r--src/com/android/settings/livedisplay/LiveDisplay.java350
4 files changed, 1206 insertions, 0 deletions
diff --git a/src/com/android/settings/livedisplay/DisplayColor.java b/src/com/android/settings/livedisplay/DisplayColor.java
new file mode 100644
index 0000000..6ca0ac7
--- /dev/null
+++ b/src/com/android/settings/livedisplay/DisplayColor.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2013-2015 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 com.android.settings.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.preference.DialogPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.android.settings.IntervalSeekBar;
+import com.android.settings.R;
+
+/**
+ * Special preference type that allows configuration of Color settings
+ */
+public class DisplayColor extends DialogPreference {
+ private static final String TAG = "ColorCalibration";
+
+ private final Context mContext;
+
+ // These arrays must all match in length and order
+ private static final int[] SEEKBAR_ID = new int[] {
+ R.id.color_red_seekbar,
+ R.id.color_green_seekbar,
+ R.id.color_blue_seekbar
+ };
+
+ private static final int[] SEEKBAR_VALUE_ID = new int[] {
+ R.id.color_red_value,
+ R.id.color_green_value,
+ R.id.color_blue_value
+ };
+
+ private ColorSeekBar[] mSeekBars = new ColorSeekBar[SEEKBAR_ID.length];
+
+ private final float[] mCurrentColors = new float[3];
+ private final float[] mOriginalColors = new float[3];
+
+ public DisplayColor(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mContext = context;
+
+ setDialogLayoutResource(R.layout.display_color_calibration);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.settings_reset_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ String colorAdjustmentTemp = Settings.System.getStringForUser(mContext.getContentResolver(),
+ Settings.System.DISPLAY_COLOR_ADJUSTMENT,
+ UserHandle.USER_CURRENT);
+ String[] colorAdjustment = colorAdjustmentTemp == null ?
+ null : colorAdjustmentTemp.split(" ");
+ if (colorAdjustment == null || colorAdjustment.length != 3) {
+ colorAdjustment = new String[] { "1.0", "1.0", "1.0" };
+ }
+ try {
+ mOriginalColors[0] = Float.parseFloat(colorAdjustment[0]);
+ mOriginalColors[1] = Float.parseFloat(colorAdjustment[1]);
+ mOriginalColors[2] = Float.parseFloat(colorAdjustment[2]);
+ } catch (NumberFormatException e) {
+ mOriginalColors[0] = 1.0f;
+ mOriginalColors[1] = 1.0f;
+ mOriginalColors[2] = 1.0f;
+ }
+
+ System.arraycopy(mOriginalColors, 0, mCurrentColors, 0, 3);
+
+ for (int i = 0; i < SEEKBAR_ID.length; i++) {
+ IntervalSeekBar seekBar = (IntervalSeekBar) view.findViewById(SEEKBAR_ID[i]);
+ TextView value = (TextView) view.findViewById(SEEKBAR_VALUE_ID[i]);
+ mSeekBars[i] = new ColorSeekBar(seekBar, value, i);
+ mSeekBars[i].mSeekBar.setProgressFloat(mCurrentColors[i]);
+ }
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ for (int i = 0; i < mSeekBars.length; i++) {
+ mSeekBars[i].mSeekBar.setProgressFloat(1.00f);
+ mCurrentColors[i] = 1.0f;
+ }
+ updateColors(mCurrentColors);
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ updateColors(positiveResult ? mCurrentColors : mOriginalColors);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (getDialog() == null || !getDialog().isShowing()) {
+ return superState;
+ }
+
+ // Save the dialog state
+ final SavedState myState = new SavedState(superState);
+ myState.currentColors = mCurrentColors;
+ myState.originalColors = mOriginalColors;
+
+ // Restore the old state when the activity or dialog is being paused
+ updateColors(mOriginalColors);
+
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+
+ System.arraycopy(myState.originalColors, 0, mOriginalColors, 0, 3);
+ System.arraycopy(myState.currentColors, 0, mCurrentColors, 0, 3);
+ for (int i = 0; i < mSeekBars.length; i++) {
+ mSeekBars[i].mSeekBar.setProgressFloat(mCurrentColors[i]);
+ }
+ updateColors(mCurrentColors);
+ }
+
+ private static class SavedState extends BaseSavedState {
+ float[] originalColors;
+ float[] currentColors;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ originalColors = source.createFloatArray();
+ currentColors = source.createFloatArray();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeFloatArray(originalColors);
+ dest.writeFloatArray(currentColors);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private void updateColors(float[] colors) {
+ Settings.System.putStringForUser(mContext.getContentResolver(),
+ Settings.System.DISPLAY_COLOR_ADJUSTMENT,
+ new StringBuilder().append(colors[0]).append(" ")
+ .append(colors[1]).append(" ")
+ .append(colors[2]).toString(),
+ UserHandle.USER_CURRENT);
+ }
+
+ private class ColorSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private int mIndex;
+ private final IntervalSeekBar mSeekBar;
+ private TextView mValue;
+
+ public ColorSeekBar(IntervalSeekBar seekBar, TextView value, int index) {
+ mSeekBar = seekBar;
+ mValue = value;
+ mIndex = index;
+
+ mSeekBar.setOnSeekBarChangeListener(this);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ IntervalSeekBar isb = (IntervalSeekBar)seekBar;
+ float fp = isb.getProgressFloat();
+ if (fromUser) {
+ mCurrentColors[mIndex] = fp;
+ updateColors(mCurrentColors);
+ }
+
+ int percent = Math.round(100F * fp);
+ mValue.setText(String.format("%d%%", percent));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+ }
+}
diff --git a/src/com/android/settings/livedisplay/DisplayGamma.java b/src/com/android/settings/livedisplay/DisplayGamma.java
new file mode 100644
index 0000000..38a187b
--- /dev/null
+++ b/src/com/android/settings/livedisplay/DisplayGamma.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2013-2015 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 com.android.settings.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import org.cyanogenmod.hardware.DisplayGammaCalibration;
+
+/**
+ * Special preference type that allows configuration of Gamma settings
+ */
+public class DisplayGamma extends DialogPreference {
+ private static final String TAG = "GammaCalibration";
+
+ private static final int[] BAR_COLORS = new int[] {
+ R.string.color_red_title,
+ R.string.color_green_title,
+ R.string.color_blue_title
+ };
+
+ private GammaSeekBar[][] mSeekBars;
+
+ private String[][] mCurrentColors;
+ private String[] mOriginalColors;
+ private int mNumberOfControls;
+
+ public DisplayGamma(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ if (!isSupported()) {
+ return;
+ }
+
+ mNumberOfControls = DisplayGammaCalibration.getNumberOfControls();
+ mSeekBars = new GammaSeekBar[mNumberOfControls][BAR_COLORS.length];
+
+ mOriginalColors = new String[mNumberOfControls];
+ mCurrentColors = new String[mNumberOfControls][];
+
+ setDialogLayoutResource(R.layout.display_gamma_calibration);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.settings_reset_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ final ViewGroup container = (ViewGroup) view.findViewById(R.id.gamma_container);
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+ final SharedPreferences prefs = getSharedPreferences();
+ final Resources res = container.getResources();
+ final String[] gammaDescriptors = res.getStringArray(R.array.gamma_descriptors);
+
+ // Create multiple sets of seekbars, depending on the
+ // number of controls the device has
+ for (int index = 0; index < mNumberOfControls; index++) {
+ mOriginalColors[index] = DisplayGammaCalibration.getCurGamma(index);
+ mCurrentColors[index] = mOriginalColors[index].split(" ");
+
+ final String defaultKey = "display_gamma_default_" + index;
+ if (!prefs.contains(defaultKey)) {
+ prefs.edit().putString(defaultKey, mOriginalColors[index]).commit();
+ }
+
+ if (mNumberOfControls != 1) {
+ TextView header = (TextView) inflater.inflate(
+ R.layout.display_gamma_calibration_header, container, false);
+
+ if (index < gammaDescriptors.length) {
+ header.setText(gammaDescriptors[index]);
+ } else {
+ header.setText(res.getString(
+ R.string.gamma_tuning_control_set_header, index + 1));
+ }
+ container.addView(header);
+ }
+
+ for (int color = 0; color < BAR_COLORS.length; color++) {
+ ViewGroup item = (ViewGroup) inflater.inflate(
+ R.layout.display_gamma_calibration_item, container, false);
+
+ mSeekBars[index][color] = new GammaSeekBar(index, color, item);
+ mSeekBars[index][color].setGamma(Integer.valueOf(mCurrentColors[index][color]));
+ // make sure to add the seekbar group to the container _after_
+ // creating GammaSeekBar, so that GammaSeekBar has a chance to
+ // get the correct subviews without getting confused by duplicate IDs
+ container.addView(item);
+ }
+ }
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ for (int index = 0; index < mSeekBars.length; index++) {
+ final SharedPreferences prefs = getSharedPreferences();
+ final String defaultKey = "display_gamma_default_" + index;
+ // this key is guaranteed to be present, as we have
+ // created it in onBindDialogView()
+ final String[] defaultColors = prefs.getString(defaultKey, null).split(" ");
+
+ for (int color = 0; color < BAR_COLORS.length; color++) {
+ mSeekBars[index][color].setGamma(Integer.valueOf(defaultColors[color]));
+ mCurrentColors[index][color] = defaultColors[color];
+ }
+ DisplayGammaCalibration.setGamma(index,
+ TextUtils.join(" ", mCurrentColors[index]));
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult) {
+ Editor editor = getEditor();
+ for (int i = 0; i < mNumberOfControls; i++) {
+ editor.putString("display_gamma_" + i, DisplayGammaCalibration.getCurGamma(i));
+ }
+ editor.commit();
+ } else if (mOriginalColors != null) {
+ for (int i = 0; i < mNumberOfControls; i++) {
+ DisplayGammaCalibration.setGamma(i, mOriginalColors[i]);
+ }
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (getDialog() == null || !getDialog().isShowing()) {
+ return superState;
+ }
+
+ // Save the dialog state
+ final SavedState myState = new SavedState(superState);
+ myState.controlCount = mNumberOfControls;
+ myState.currentColors = mCurrentColors;
+ myState.originalColors = mOriginalColors;
+
+ // Restore the old state when the activity or dialog is being paused
+ for (int i = 0; i < mNumberOfControls; i++) {
+ DisplayGammaCalibration.setGamma(i, mOriginalColors[i]);
+ }
+ mOriginalColors = null;
+
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ mNumberOfControls = myState.controlCount;
+ mOriginalColors = myState.originalColors;
+ mCurrentColors = myState.currentColors;
+
+ for (int index = 0; index < mNumberOfControls; index++) {
+ for (int color = 0; color < BAR_COLORS.length; color++) {
+ mSeekBars[index][color].setGamma(Integer.valueOf(mCurrentColors[index][color]));
+ }
+ DisplayGammaCalibration.setGamma(index, TextUtils.join(" ", mCurrentColors[index]));
+ }
+ }
+
+ public static boolean isSupported() {
+ try {
+ return DisplayGammaCalibration.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework isn't installed
+ return false;
+ }
+ }
+
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ for (int i = 0; i < DisplayGammaCalibration.getNumberOfControls(); i++) {
+ final String values = prefs.getString("display_gamma_" + i, null);
+ if (values != null) {
+ DisplayGammaCalibration.setGamma(i, values);
+ }
+ }
+ }
+
+ private static class SavedState extends BaseSavedState {
+ int controlCount;
+ String[] originalColors;
+ String[][] currentColors;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ controlCount = source.readInt();
+ originalColors = source.createStringArray();
+ currentColors = new String[controlCount][];
+ for (int i = 0; i < controlCount; i++) {
+ currentColors[i] = source.createStringArray();
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(controlCount);
+ dest.writeStringArray(originalColors);
+ for (int i = 0; i < controlCount; i++) {
+ dest.writeStringArray(currentColors[i]);
+ }
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private class GammaSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private int mControlIndex;
+ private int mColorIndex;
+ private int mOriginal;
+ private int mMin;
+ private SeekBar mSeekBar;
+ private TextView mValue;
+
+ public GammaSeekBar(int controlIndex, int colorIndex, ViewGroup container) {
+ mControlIndex = controlIndex;
+ mColorIndex = colorIndex;
+
+ mMin = DisplayGammaCalibration.getMinValue(controlIndex);
+
+ mValue = (TextView) container.findViewById(R.id.color_value);
+ mSeekBar = (SeekBar) container.findViewById(R.id.color_seekbar);
+
+ TextView label = (TextView) container.findViewById(R.id.color_text);
+ label.setText(container.getContext().getString(BAR_COLORS[colorIndex]));
+
+ mSeekBar.setMax(DisplayGammaCalibration.getMaxValue(controlIndex) - mMin);
+ mSeekBar.setProgress(0);
+ mValue.setText(String.valueOf(mSeekBar.getProgress() + mMin));
+
+ // this must be done last, we don't want to apply our initial value to the hardware
+ mSeekBar.setOnSeekBarChangeListener(this);
+ }
+
+ public void setGamma(int gamma) {
+ mSeekBar.setProgress(gamma - mMin);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ mCurrentColors[mControlIndex][mColorIndex] = String.valueOf(progress + mMin);
+ DisplayGammaCalibration.setGamma(mControlIndex,
+ TextUtils.join(" ", mCurrentColors[mControlIndex]));
+ }
+ mValue.setText(String.valueOf(progress + mMin));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+ }
+}
diff --git a/src/com/android/settings/livedisplay/DisplayTemperature.java b/src/com/android/settings/livedisplay/DisplayTemperature.java
new file mode 100644
index 0000000..971bd3e
--- /dev/null
+++ b/src/com/android/settings/livedisplay/DisplayTemperature.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2015 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 com.android.settings.livedisplay;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.UserHandle;
+import android.preference.DialogPreference;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * Preference for selection of color temperature range for LiveDisplay
+ */
+public class DisplayTemperature extends DialogPreference {
+ private static final String TAG = "DisplayTemperature";
+
+ private final Context mContext;
+
+ private ColorTemperatureSeekBar mDayTemperature;
+ private ColorTemperatureSeekBar mNightTemperature;
+
+ private int mOriginalDayTemperature;
+ private int mOriginalNightTemperature;
+
+ private final int mDefaultDayTemperature;
+ private final int mDefaultNightTemperature;
+
+ public DisplayTemperature(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+
+ mDefaultDayTemperature = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_dayColorTemperature);
+ mDefaultNightTemperature = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_nightColorTemperature);
+
+ setDialogLayoutResource(R.layout.display_temperature);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.settings_reset_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mOriginalDayTemperature = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_DAY,
+ mDefaultDayTemperature,
+ UserHandle.USER_CURRENT);
+ mOriginalNightTemperature = Settings.System.getIntForUser(mContext.getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_NIGHT,
+ mDefaultNightTemperature,
+ UserHandle.USER_CURRENT);
+
+ SeekBar day = (SeekBar) view.findViewById(R.id.day_temperature_seekbar);
+ TextView dayText = (TextView) view.findViewById(R.id.day_temperature_value);
+ mDayTemperature = new ColorTemperatureSeekBar(day, dayText);
+
+ SeekBar night = (SeekBar) view.findViewById(R.id.night_temperature_seekbar);
+ TextView nightText = (TextView) view.findViewById(R.id.night_temperature_value);
+ mNightTemperature = new ColorTemperatureSeekBar(night, nightText);
+
+ mDayTemperature.setProgress(mOriginalDayTemperature);
+ mNightTemperature.setProgress(mOriginalNightTemperature);
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mDayTemperature.setProgress(mDefaultDayTemperature);
+ mNightTemperature.setProgress(mDefaultNightTemperature);
+ updateTemperature(true);
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+ updateTemperature(positiveResult);
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (getDialog() == null || !getDialog().isShowing()) {
+ return superState;
+ }
+
+ // Save the dialog state
+ final SavedState myState = new SavedState(superState);
+ myState.originalDayTemperature = mOriginalDayTemperature;
+ myState.originalNightTemperature = mOriginalNightTemperature;
+ myState.currentDayTemperature = mDayTemperature.getProgress();
+ myState.currentNightTemperature = mNightTemperature.getProgress();
+
+ // Restore the old state when the activity or dialog is being paused
+ updateTemperature(false);
+
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+
+ mOriginalDayTemperature = myState.originalDayTemperature;
+ mOriginalNightTemperature = myState.originalNightTemperature;
+ mDayTemperature.setProgress(myState.currentDayTemperature);
+ mNightTemperature.setProgress(myState.currentNightTemperature);;
+
+ updateTemperature(true);
+ }
+
+ private static class SavedState extends BaseSavedState {
+ int originalDayTemperature;
+ int originalNightTemperature;
+ int currentDayTemperature;
+ int currentNightTemperature;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ originalDayTemperature = source.readInt();
+ originalNightTemperature = source.readInt();
+ currentDayTemperature = source.readInt();
+ currentNightTemperature = source.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(originalDayTemperature);
+ dest.writeInt(originalNightTemperature);
+ dest.writeInt(currentDayTemperature);
+ dest.writeInt(currentNightTemperature);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private void updateTemperature(boolean accept) {
+ int day = accept ? mDayTemperature.getProgress() : mOriginalDayTemperature;
+ int night = accept ? mNightTemperature.getProgress() : mOriginalNightTemperature;
+ callChangeListener(new Integer[] { day, night });
+
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_DAY, day,
+ UserHandle.USER_CURRENT);
+
+ Settings.System.putIntForUser(mContext.getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_NIGHT, night,
+ UserHandle.USER_CURRENT);
+ }
+
+ private class ColorTemperatureSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private final SeekBar mSeekBar;
+ private final TextView mValue;
+
+ private static final int MIN = 1000;
+ private static final int MAX = 10000;
+
+ public ColorTemperatureSeekBar(SeekBar seekBar, TextView value) {
+ mSeekBar = seekBar;
+ mValue = value;
+
+ mSeekBar.setMax(MAX - MIN);
+ mSeekBar.setOnSeekBarChangeListener(this);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ updateTemperature(true);
+ }
+ mValue.setText(mContext.getResources().getString(
+ R.string.live_display_color_temperature_label, progress + MIN));
+ }
+
+ public void setProgress(int progress) {
+ int p = progress < MIN ? MIN : progress;
+ mSeekBar.setProgress(p - MIN);
+ }
+
+ public int getProgress() {
+ return mSeekBar.getProgress() + MIN;
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+ }
+}
diff --git a/src/com/android/settings/livedisplay/LiveDisplay.java b/src/com/android/settings/livedisplay/LiveDisplay.java
new file mode 100644
index 0000000..07283a6
--- /dev/null
+++ b/src/com/android/settings/livedisplay/LiveDisplay.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2015 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 com.android.settings.livedisplay;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.SearchIndexableResource;
+import android.provider.Settings;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+
+import org.cyanogenmod.hardware.AdaptiveBacklight;
+import org.cyanogenmod.hardware.ColorEnhancement;
+import org.cyanogenmod.hardware.SunlightEnhancement;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LiveDisplay extends SettingsPreferenceFragment implements
+ Preference.OnPreferenceChangeListener, Indexable {
+
+ private static final String TAG = "LiveDisplay";
+
+ private static final String KEY_CATEGORY_LIVE_DISPLAY = "live_display_options";
+ private static final String KEY_CATEGORY_CALIBRATION = "calibration";
+
+ private static final String KEY_LIVE_DISPLAY = "live_display";
+ private static final String KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE =
+ "live_display_auto_outdoor_mode";
+ private static final String KEY_LIVE_DISPLAY_LOW_POWER = "live_display_low_power";
+ private static final String KEY_LIVE_DISPLAY_COLOR_ENHANCE = "live_display_color_enhance";
+ private static final String KEY_LIVE_DISPLAY_TEMPERATURE = "live_display_color_temperature";
+
+ private static final String KEY_DISPLAY_COLOR = "color_calibration";
+ private static final String KEY_DISPLAY_GAMMA = "gamma_tuning";
+ private static final String KEY_SCREEN_COLOR_SETTINGS = "screencolor_settings";
+
+ public static final int MODE_DAY = 0;
+ public static final int MODE_NIGHT = 1;
+ public static final int MODE_AUTO = 2;
+ public static final int MODE_OUTDOOR = 3;
+
+ private final Handler mHandler = new Handler();
+ private final SettingsObserver mObserver = new SettingsObserver();
+
+ private ListPreference mLiveDisplay;
+
+ private SwitchPreference mColorEnhancement;
+ private SwitchPreference mLowPower;
+ private SwitchPreference mOutdoorMode;
+
+ private PreferenceScreen mScreenColorSettings;
+ private DisplayTemperature mDisplayTemperature;
+
+ private String[] mModeEntries;
+ private String[] mModeValues;
+ private String[] mModeSummaries;
+
+ private int mDefaultDayTemperature;
+ private int mDefaultNightTemperature;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final Activity activity = getActivity();
+ final ContentResolver resolver = activity.getContentResolver();
+ final Resources res = getResources();
+
+ mDefaultDayTemperature = res.getInteger(
+ com.android.internal.R.integer.config_dayColorTemperature);
+ mDefaultNightTemperature = res.getInteger(
+ com.android.internal.R.integer.config_nightColorTemperature);
+
+ addPreferencesFromResource(R.xml.livedisplay);
+
+ PreferenceCategory liveDisplayPrefs = (PreferenceCategory)
+ findPreference(KEY_CATEGORY_LIVE_DISPLAY);
+ PreferenceCategory calibrationPrefs = (PreferenceCategory)
+ findPreference(KEY_CATEGORY_CALIBRATION);
+
+ int displayMode = Settings.System.getIntForUser(resolver,
+ Settings.System.DISPLAY_TEMPERATURE_MODE,
+ 0, UserHandle.USER_CURRENT);
+ mLiveDisplay = (ListPreference) findPreference(KEY_LIVE_DISPLAY);
+ mLiveDisplay.setValue(String.valueOf(displayMode));
+
+ mModeEntries = res.getStringArray(
+ com.android.internal.R.array.live_display_entries);
+ mModeValues = res.getStringArray(
+ com.android.internal.R.array.live_display_values);
+ mModeSummaries = res.getStringArray(
+ com.android.internal.R.array.live_display_summaries);
+
+ // Remove outdoor mode from lists if there is no support
+ if (!SunlightEnhancement.isSupported()) {
+ int idx = ArrayUtils.indexOf(mModeValues, String.valueOf(MODE_OUTDOOR));
+ String[] entriesTemp = new String[mModeEntries.length - 1];
+ String[] valuesTemp = new String[mModeValues.length - 1];
+ String[] summariesTemp = new String[mModeSummaries.length - 1];
+ int j = 0;
+ for (int i = 0; i < mModeEntries.length; i++) {
+ if (i == idx) {
+ continue;
+ }
+ entriesTemp[j] = mModeEntries[i];
+ valuesTemp[j] = mModeValues[i];
+ summariesTemp[j] = mModeSummaries[i];
+ j++;
+ }
+ mModeEntries = entriesTemp;
+ mModeValues = valuesTemp;
+ mModeSummaries = summariesTemp;
+ }
+
+ mLiveDisplay.setEntries(mModeEntries);
+ mLiveDisplay.setEntryValues(mModeValues);
+ mLiveDisplay.setOnPreferenceChangeListener(this);
+
+ mDisplayTemperature = (DisplayTemperature) findPreference(KEY_LIVE_DISPLAY_TEMPERATURE);
+
+ mLowPower = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_LOW_POWER);
+ if (liveDisplayPrefs != null && mLowPower != null
+ && !isAdaptiveBacklightSupported()) {
+ liveDisplayPrefs.removePreference(mLowPower);
+ mLowPower = null;
+ }
+
+ mOutdoorMode = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE);
+ if (liveDisplayPrefs != null && mOutdoorMode != null
+ && !isSunlightEnhancementSupported()) {
+ liveDisplayPrefs.removePreference(mOutdoorMode);
+ mOutdoorMode = null;
+ }
+
+ mColorEnhancement = (SwitchPreference) findPreference(KEY_LIVE_DISPLAY_COLOR_ENHANCE);
+ if (liveDisplayPrefs != null && mColorEnhancement != null
+ && !isColorEnhancementSupported()) {
+ liveDisplayPrefs.removePreference(mColorEnhancement);
+ mColorEnhancement = null;
+ }
+
+ if (calibrationPrefs != null && !DisplayGamma.isSupported()) {
+ Preference gammaPref = findPreference(KEY_DISPLAY_GAMMA);
+ if (gammaPref != null) {
+ calibrationPrefs.removePreference(gammaPref);
+ }
+ }
+
+ mScreenColorSettings = (PreferenceScreen) findPreference(KEY_SCREEN_COLOR_SETTINGS);
+ if (calibrationPrefs != null) {
+ if (!isPostProcessingSupported(getActivity()) && mScreenColorSettings != null) {
+ calibrationPrefs.removePreference(mScreenColorSettings);
+ } else if ("user".equals(Build.TYPE)) {
+ // Remove simple RGB controls if HSIC controls are available
+ Preference displayColor = findPreference(KEY_DISPLAY_COLOR);
+ if (displayColor != null) {
+ calibrationPrefs.removePreference(displayColor);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateModeSummary();
+ updateTemperatureSummary();
+ mObserver.register(true);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mObserver.register(false);
+ }
+
+ private void updateModeSummary() {
+ int mode = Settings.System.getIntForUser(getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_MODE,
+ MODE_DAY, UserHandle.USER_CURRENT);
+
+ int index = ArrayUtils.indexOf(mModeValues, String.valueOf(mode));
+ mLiveDisplay.setSummary(mModeSummaries[index]);
+ }
+
+ private void updateTemperatureSummary() {
+ int day = Settings.System.getIntForUser(getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_DAY,
+ mDefaultDayTemperature,
+ UserHandle.USER_CURRENT);
+ int night = Settings.System.getIntForUser(getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_NIGHT,
+ mDefaultNightTemperature,
+ UserHandle.USER_CURRENT);
+
+ mDisplayTemperature.setSummary(getResources().getString(
+ R.string.live_display_color_temperature_summary, day, night));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object objValue) {
+ if (preference == mLiveDisplay) {
+ Settings.System.putIntForUser(getContentResolver(),
+ Settings.System.DISPLAY_TEMPERATURE_MODE,
+ Integer.valueOf((String)objValue), UserHandle.USER_CURRENT);
+ }
+ return true;
+ }
+
+ private static boolean isAdaptiveBacklightSupported() {
+ try {
+ return AdaptiveBacklight.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework not installed
+ return false;
+ }
+ }
+
+ private static boolean isSunlightEnhancementSupported() {
+ try {
+ return SunlightEnhancement.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework not installed
+ return false;
+ }
+ }
+
+ private static boolean isColorEnhancementSupported() {
+ try {
+ return ColorEnhancement.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework not installed
+ return false;
+ }
+ }
+
+ private static boolean isPostProcessingSupported(Context context) {
+ return Utils.isPackageInstalled(context, "com.qualcomm.display");
+ }
+
+ private final class SettingsObserver extends ContentObserver {
+ private final Uri DISPLAY_TEMPERATURE_DAY_URI =
+ Settings.System.getUriFor(Settings.System.DISPLAY_TEMPERATURE_DAY);
+ private final Uri DISPLAY_TEMPERATURE_NIGHT_URI =
+ Settings.System.getUriFor(Settings.System.DISPLAY_TEMPERATURE_NIGHT);
+ private final Uri DISPLAY_TEMPERATURE_MODE_URI =
+ Settings.System.getUriFor(Settings.System.DISPLAY_TEMPERATURE_MODE);
+
+ public SettingsObserver() {
+ super(mHandler);
+ }
+
+ public void register(boolean register) {
+ final ContentResolver cr = getContentResolver();
+ if (register) {
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_DAY_URI, false, this);
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_NIGHT_URI, false, this);
+ cr.registerContentObserver(DISPLAY_TEMPERATURE_MODE_URI, false, this);
+ } else {
+ cr.unregisterContentObserver(this);
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ updateModeSummary();
+ updateTemperatureSummary();
+ }
+ }
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ private boolean mHasSunlightEnhancement, mHasColorEnhancement, mHasLowPower;
+ private boolean mHasDisplayGamma;
+
+ @Override
+ public void prepare() {
+ mHasSunlightEnhancement = isSunlightEnhancementSupported();
+ mHasColorEnhancement = isColorEnhancementSupported();
+ mHasLowPower = isAdaptiveBacklightSupported();
+ mHasDisplayGamma = DisplayGamma.isSupported();
+ }
+
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ ArrayList<SearchIndexableResource> result =
+ new ArrayList<SearchIndexableResource>();
+
+ SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.livedisplay;
+ result.add(sir);
+
+ return result;
+ }
+
+ @Override
+ public List<String> getNonIndexableKeys(Context context) {
+ ArrayList<String> result = new ArrayList<String>();
+ if (!mHasSunlightEnhancement) {
+ result.add(KEY_LIVE_DISPLAY_AUTO_OUTDOOR_MODE);
+ }
+ if (!mHasColorEnhancement) {
+ result.add(KEY_LIVE_DISPLAY_COLOR_ENHANCE);
+ }
+ if (!mHasLowPower) {
+ result.add(KEY_LIVE_DISPLAY_LOW_POWER);
+ }
+ if (!isPostProcessingSupported(context)) {
+ result.add(KEY_SCREEN_COLOR_SETTINGS);
+ }
+ if (!mHasDisplayGamma) {
+ result.add(KEY_DISPLAY_GAMMA);
+ }
+ return result;
+ }
+ };
+}