diff options
author | Steve Kondik <steve@cyngn.com> | 2015-02-18 03:44:31 -0800 |
---|---|---|
committer | Adnan Begovic <adnan@cyngn.com> | 2015-10-29 17:36:30 -0700 |
commit | e65f2833df18e755c847bc86376253a4b96e73f9 (patch) | |
tree | e61b573057968f05218a0ad697dd38183bf81149 /src/com/android/settings/livedisplay | |
parent | 8f57a61603b7bc2fca99a510cb6c8188fb9612d2 (diff) | |
download | packages_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')
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; + } + }; +} |