diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/AmbientLuxObserver.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/AmbientLuxObserver.java index 32c7e70..bf1e85e 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/AmbientLuxObserver.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/AmbientLuxObserver.java @@ -152,16 +152,16 @@ public class AmbientLuxObserver { private void enableLightSensor(boolean enable) { if (enable && !mLightSensorEnabled) { - mAmbientLux = 0.0f; - mState = LOW; mLightSensorEnabled = true; - mRingBuffer.clear(); mSensorManager.registerListener(mListener, mLightSensor, mLightSensorRate * 1000, mLuxHandler); } else if (!enable && mLightSensorEnabled) { - mLightSensorEnabled = false; mSensorManager.unregisterListener(mListener); mLuxHandler.clear(); + mAmbientLux = 0.0f; + mState = LOW; + mLightSensorEnabled = false; + mRingBuffer.clear(); } } diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/ColorTemperatureController.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/ColorTemperatureController.java index 9f7da60..2874e74 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/ColorTemperatureController.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/ColorTemperatureController.java @@ -20,8 +20,6 @@ import static cyanogenmod.hardware.LiveDisplayManager.MODE_DAY; import static cyanogenmod.hardware.LiveDisplayManager.MODE_NIGHT; import static cyanogenmod.hardware.LiveDisplayManager.MODE_OFF; -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.net.Uri; import android.os.Handler; @@ -39,54 +37,204 @@ import cyanogenmod.util.ColorUtils; public class ColorTemperatureController extends LiveDisplayFeature { - private ValueAnimator mAnimator; - private DisplayHardwareController mDisplayHardware; + private final DisplayHardwareController mDisplayHardware; - private boolean mUseTemperatureAdjustment; + private final boolean mUseTemperatureAdjustment; - private int mDefaultDayTemperature; - private int mDefaultNightTemperature; + private final int mDefaultDayTemperature; + private final int mDefaultNightTemperature; + private int mColorTemperature = -1; private int mDayTemperature; private int mNightTemperature; + private boolean mTransitioning = false; + private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 1; - private static final int OFF_TEMPERATURE = 6500; + private static final Uri DISPLAY_TEMPERATURE_DAY = + CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY); + private static final Uri DISPLAY_TEMPERATURE_NIGHT = + CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT); - private int mColorTemperature = OFF_TEMPERATURE; - - public ColorTemperatureController(Context context, Handler handler, - DisplayHardwareController displayHardware) { + public ColorTemperatureController(Context context, + Handler handler, DisplayHardwareController displayHardware) { super(context, handler); mDisplayHardware = displayHardware; - } - - @Override - public boolean onStart() { - if (!mDisplayHardware.hasColorAdjustment()) { - return false; - } - - mUseTemperatureAdjustment = true; + mUseTemperatureAdjustment = mDisplayHardware.hasColorAdjustment(); mDefaultDayTemperature = mContext.getResources().getInteger( org.cyanogenmod.platform.internal.R.integer.config_dayColorTemperature); mDefaultNightTemperature = mContext.getResources().getInteger( org.cyanogenmod.platform.internal.R.integer.config_nightColorTemperature); - - registerSettings( - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY), - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT)); - return true; } - void getCapabilities(final BitSet caps) { + @Override + public void onStart() { + if (!mUseTemperatureAdjustment) { + return; + } + + mDayTemperature = getDayColorTemperature(); + mNightTemperature = getNightColorTemperature(); + + registerSettings(DISPLAY_TEMPERATURE_DAY, DISPLAY_TEMPERATURE_NIGHT); + } + + @Override + public boolean getCapabilities(final BitSet caps) { if (mUseTemperatureAdjustment) { caps.set(MODE_AUTO); caps.set(MODE_DAY); caps.set(MODE_NIGHT); } + return mUseTemperatureAdjustment; + } + + @Override + protected void onUpdate() { + updateColorTemperature(); + } + + @Override + protected void onScreenStateChanged() { + // pause/continue transition + if (mTransitioning) { + if (isScreenOn()) { + mHandler.post(mTransitionRunnable); + } else { + mHandler.removeCallbacks(mTransitionRunnable); + } + } + } + + @Override + protected void onTwilightUpdated() { + mHandler.post(mTransitionRunnable); + } + + @Override + protected synchronized void onSettingsChanged(Uri uri) { + if (uri == null || uri.equals(DISPLAY_TEMPERATURE_DAY)) { + mDayTemperature = getDayColorTemperature(); + } + if (uri == null || uri.equals(DISPLAY_TEMPERATURE_NIGHT)) { + mNightTemperature = getNightColorTemperature(); + } + updateColorTemperature(); + } + + @Override + public void dump(PrintWriter pw) { + pw.println(); + pw.println("ColorTemperatureController Configuration:"); + pw.println(" mDayTemperature=" + mDayTemperature); + pw.println(" mNightTemperature=" + mNightTemperature); + pw.println(); + pw.println(" ColorTemperatureController State:"); + pw.println(" mColorTemperature=" + mColorTemperature); + pw.println(" mTransitioning=" + mTransitioning); + } + + private final Runnable mTransitionRunnable = new Runnable() { + @Override + public void run() { + synchronized (ColorTemperatureController.this) { + updateColorTemperature(); + + mTransitioning = getMode() == MODE_AUTO && + mColorTemperature != mDayTemperature && + mColorTemperature != mNightTemperature; + + if (mTransitioning) { + // fire again in a minute + mHandler.postDelayed(mTransitionRunnable, DateUtils.MINUTE_IN_MILLIS); + } + } + } + }; + + private synchronized void updateColorTemperature() { + if (!mUseTemperatureAdjustment || !isScreenOn()) { + return; + } + int temperature = mDayTemperature; + int mode = getMode(); + + if (mode == MODE_OFF || isLowPowerMode()) { + temperature = mDefaultDayTemperature; + } else if (mode == MODE_NIGHT) { + temperature = mNightTemperature; + } else if (mode == MODE_AUTO) { + temperature = getTwilightK(); + } + + if (DEBUG) { + Slog.d(TAG, "updateColorTemperature mode=" + mode + + " temperature=" + temperature + " mColorTemperature=" + mColorTemperature); + } + + setDisplayTemperature(temperature); + } + + + private synchronized void setDisplayTemperature(int temperature) { + mColorTemperature = temperature; + + final float[] rgb = ColorUtils.temperatureToRGB(temperature); + if (mDisplayHardware.setAdditionalAdjustment(rgb)) { + if (DEBUG) { + Slog.d(TAG, "Adjust display temperature to " + temperature + "K"); + } + } + + } + + /** + * Where is the sun anyway? This calculation determines day or night, and scales + * the value around sunset/sunrise for a smooth transition. + * + * @param now + * @param sunset + * @param sunrise + * @return float between 0 and 1 + */ + private static float adj(long now, long sunset, long sunrise) { + if (sunset < 0 || sunrise < 0 + || now < sunset || now > (sunrise + TWILIGHT_ADJUSTMENT_TIME)) { + return 1.0f; + } + + if (now <= (sunset + TWILIGHT_ADJUSTMENT_TIME)) { + return MathUtils.lerp(1.0f, 0.0f, + (float)(now - sunset) / TWILIGHT_ADJUSTMENT_TIME); + } + + if (now >= sunrise) { + return MathUtils.lerp(1.0f, 0.0f, + (float)((sunrise + TWILIGHT_ADJUSTMENT_TIME) - now) / TWILIGHT_ADJUSTMENT_TIME); + } + + return 0.0f; + } + + /** + * Determine the color temperature we should use for the display based on + * the position of the sun. + * + * @return color temperature in Kelvin + */ + private int getTwilightK() { + float adjustment = 1.0f; + final TwilightState twilight = getTwilight(); + + if (twilight != null) { + final long now = System.currentTimeMillis(); + adjustment = adj(now, twilight.getYesterdaySunset(), twilight.getTodaySunrise()) * + adj(now, twilight.getTodaySunset(), twilight.getTomorrowSunrise()); + } + + return (int)MathUtils.lerp(mNightTemperature, mDayTemperature, adjustment); } int getDefaultDayTemperature() { @@ -118,154 +266,4 @@ public class ColorTemperatureController extends LiveDisplayFeature { void setNightColorTemperature(int temperature) { putInt(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT, temperature); } - - @Override - public void onModeChanged(int mode) { - super.onModeChanged(mode); - updateColorTemperature(); - } - - @Override - public synchronized void onSettingsChanged(Uri uri) { - mDayTemperature = getDayColorTemperature(); - mNightTemperature = getNightColorTemperature(); - updateColorTemperature(); - } - - @Override - public void onTwilightUpdated(TwilightState twilight) { - super.onTwilightUpdated(twilight); - mHandler.post(mTransitionRunnable); - } - - @Override - public void dump(PrintWriter pw) { - pw.println(); - pw.println("ColorTemperatureController Configuration:"); - pw.println(" mDayTemperature=" + mDayTemperature); - pw.println(" mNightTemperature=" + mNightTemperature); - pw.println(); - pw.println(" ColorTemperatureController State:"); - pw.println(" mColorTemperature=" + mColorTemperature); - if (getTwilight() != null) { - pw.println(" mTwilight=" + getTwilight().toString()); - } - pw.println(" transitioning=" + mHandler.hasCallbacks(mTransitionRunnable)); - } - - private final Runnable mTransitionRunnable = new Runnable() { - @Override - public void run() { - synchronized (ColorTemperatureController.this) { - updateColorTemperature(); - - boolean transition = getMode() == MODE_AUTO && - mColorTemperature != mDayTemperature && - mColorTemperature != mNightTemperature; - - if (transition) { - // fire again in a minute - mHandler.postDelayed(mTransitionRunnable, DateUtils.MINUTE_IN_MILLIS); - } - } - } - }; - - private void updateColorTemperature() { - mHandler.removeCallbacks(mTransitionRunnable); - - int temperature = mDayTemperature; - int mode = getMode(); - - if (mode == MODE_OFF || isLowPowerMode()) { - temperature = OFF_TEMPERATURE; - } else if (mode == MODE_NIGHT) { - temperature = mNightTemperature; - } else if (mode == MODE_AUTO) { - temperature = getTwilightK(); - } - - if (DEBUG) { - Slog.d(TAG, "updateColorTemperatureLocked mode=" + mode + - " temperature=" + temperature + " mColorTemperature=" + mColorTemperature); - } - - if (mAnimator != null) { - mAnimator.cancel(); - mAnimator.removeAllUpdateListeners(); - } - mAnimator = ValueAnimator.ofInt(mColorTemperature, temperature); - mAnimator.setDuration(Math.abs(mColorTemperature - temperature) / 2); - mAnimator.addUpdateListener(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(final ValueAnimator animation) { - mHandler.post(new Runnable() { - @Override - public void run() { - setDisplayTemperature((Integer)animation.getAnimatedValue()); - } - }); - } - }); - mAnimator.start(); - } - - - private synchronized void setDisplayTemperature(int temperature) { - mColorTemperature = temperature; - - final float[] rgb = ColorUtils.temperatureToRGB(temperature); - mDisplayHardware.setAdditionalAdjustment(rgb); - - if (DEBUG) { - Slog.d(TAG, "Adjust display temperature to " + temperature + "K"); - } - } - - /** - * Where is the sun anyway? This calculation determines day or night, and scales - * the value around sunset/sunrise for a smooth transition. - * - * @param now - * @param sunset - * @param sunrise - * @return float between 0 and 1 - */ - private static float adj(long now, long sunset, long sunrise) { - if (sunset < 0 || sunrise < 0 - || now < sunset || now > sunrise) { - return 1.0f; - } - - if (now < sunset + TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, 0.0f, - (float)(now - sunset) / TWILIGHT_ADJUSTMENT_TIME); - } - - if (now > sunrise - TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, 0.0f, - (float)(sunrise - now) / TWILIGHT_ADJUSTMENT_TIME); - } - - return 0.0f; - } - - /** - * Determine the color temperature we should use for the display based on - * the position of the sun. - * - * @return color temperature in Kelvin - */ - private int getTwilightK() { - float adjustment = 1.0f; - final TwilightState twilight = getTwilight(); - - if (twilight != null) { - final long now = System.currentTimeMillis(); - adjustment = adj(now, twilight.getYesterdaySunset(), twilight.getTodaySunrise()) * - adj(now, twilight.getTodaySunset(), twilight.getTomorrowSunrise()); - } - - return (int)MathUtils.lerp(mNightTemperature, mDayTemperature, adjustment); - } } diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/DisplayHardwareController.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/DisplayHardwareController.java index 0189ccd..1977092 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/DisplayHardwareController.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/DisplayHardwareController.java @@ -15,6 +15,9 @@ */ package org.cyanogenmod.platform.internal.display; +import android.animation.FloatArrayEvaluator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.net.Uri; import android.os.Handler; @@ -23,6 +26,7 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; +import android.view.animation.LinearInterpolator; import java.io.PrintWriter; import java.util.ArrayList; @@ -35,28 +39,27 @@ import cyanogenmod.providers.CMSettings; public class DisplayHardwareController extends LiveDisplayFeature { - private CMHardwareManager mHardware; + private final CMHardwareManager mHardware; // hardware capabilities - private boolean mUseAutoContrast; - private boolean mUseColorAdjustment; - private boolean mUseColorEnhancement; - private boolean mUseCABC; + private final boolean mUseAutoContrast; + private final boolean mUseColorAdjustment; + private final boolean mUseColorEnhancement; + private final boolean mUseCABC; // default values - private boolean mDefaultAutoContrast; - private boolean mDefaultColorEnhancement; - private boolean mDefaultCABC; - - // current values - private boolean mAutoContrast; - private boolean mColorEnhancement; - private boolean mCABC; + private final boolean mDefaultAutoContrast; + private final boolean mDefaultColorEnhancement; + private final boolean mDefaultCABC; // color adjustment holders - private final float[] mColorAdjustment = new float[] { 1.0f, 1.0f, 1.0f }; - private final float[] mAdditionalAdjustment = new float[] { 1.0f, 1.0f, 1.0f }; - private final float[] mRGB = new float[] { 1.0f, 1.0f, 1.0f }; + private final float[] mAdditionalAdjustment = getDefaultAdjustment(); + private final float[] mColorAdjustment = getDefaultAdjustment(); + + private ValueAnimator mAnimator; + private boolean mDirty = false; + + private final int mMaxColor; // settings uris private static final Uri DISPLAY_AUTO_CONTRAST = @@ -70,56 +73,54 @@ public class DisplayHardwareController extends LiveDisplayFeature { public DisplayHardwareController(Context context, Handler handler) { super(context, handler); - } - - @Override - public boolean onStart() { - final ArrayList settings = new ArrayList(); mHardware = CMHardwareManager.getInstance(mContext); mUseCABC = mHardware .isSupported(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT); - if (mUseCABC) { - mDefaultCABC = mContext.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_defaultCABC); - mCABC = mHardware.get(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT); - settings.add(DISPLAY_CABC); - } + mDefaultCABC = mContext.getResources().getBoolean( + org.cyanogenmod.platform.internal.R.bool.config_defaultCABC); mUseColorEnhancement = mHardware .isSupported(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT); - if (mUseColorEnhancement) { - mDefaultColorEnhancement = mContext.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_defaultColorEnhancement); - mColorEnhancement = mHardware.get(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT); - settings.add(DISPLAY_COLOR_ENHANCE); - } + mDefaultColorEnhancement = mContext.getResources().getBoolean( + org.cyanogenmod.platform.internal.R.bool.config_defaultColorEnhancement); mUseAutoContrast = mHardware .isSupported(CMHardwareManager.FEATURE_AUTO_CONTRAST); - if (mUseAutoContrast) { - mDefaultAutoContrast = mContext.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_defaultAutoContrast); - mAutoContrast = mHardware.get(CMHardwareManager.FEATURE_AUTO_CONTRAST); - settings.add(DISPLAY_AUTO_CONTRAST); - } + mDefaultAutoContrast = mContext.getResources().getBoolean( + org.cyanogenmod.platform.internal.R.bool.config_defaultAutoContrast); mUseColorAdjustment = mHardware .isSupported(CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION); + mMaxColor = mHardware.getDisplayColorCalibrationMax(); + } + + @Override + public void onStart() { + final ArrayList settings = new ArrayList(); + + if (mUseCABC) { + settings.add(DISPLAY_CABC); + } + if (mUseColorEnhancement) { + settings.add(DISPLAY_COLOR_ENHANCE); + } + if (mUseAutoContrast) { + settings.add(DISPLAY_AUTO_CONTRAST); + } if (mUseColorAdjustment) { settings.add(DISPLAY_COLOR_ADJUSTMENT); } if (settings.size() == 0) { - return false; + return; } registerSettings(settings.toArray(new Uri[settings.size()])); - return true; } @Override - void getCapabilities(final BitSet caps) { + public boolean getCapabilities(final BitSet caps) { if (mUseAutoContrast) { caps.set(LiveDisplayManager.FEATURE_AUTO_CONTRAST); } @@ -132,6 +133,7 @@ public class DisplayHardwareController extends LiveDisplayFeature { if (mUseColorAdjustment) { caps.set(LiveDisplayManager.FEATURE_COLOR_ADJUSTMENT); } + return mUseAutoContrast || mUseColorEnhancement || mUseCABC || mUseColorAdjustment; } @Override @@ -145,19 +147,37 @@ public class DisplayHardwareController extends LiveDisplayFeature { if (uri == null || uri.equals(DISPLAY_COLOR_ENHANCE)) { updateColorEnhancement(); } - if (uri == null || uri.equals(DISPLAY_COLOR_ADJUSTMENT)) { - System.arraycopy( - parseColorAdjustment(getString(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT)), - 0, mColorAdjustment, 0, 3); + if (uri == null || uri.equals(DISPLAY_COLOR_ADJUSTMENT) && + parseColorAdjustment(getString( + CMSettings.System.DISPLAY_COLOR_ADJUSTMENT), mColorAdjustment)) { updateColorAdjustment(); } } + private synchronized void updateHardware() { + if (isScreenOn()) { + updateCABCMode(); + updateAutoContrast(); + updateColorEnhancement(); + } + } + @Override - public synchronized void onLowPowerModeChanged(boolean lowPowerMode) { - updateCABCMode(); - updateAutoContrast(); - updateColorEnhancement(); + protected void onUpdate() { + updateHardware(); + } + + @Override + protected synchronized void onScreenStateChanged() { + if (mUseColorAdjustment) { + if (mAnimator != null && mAnimator.isRunning() && !isScreenOn()) { + mAnimator.cancel(); + mDirty = true; + } else if (mDirty && isScreenOn()) { + updateColorAdjustment(); + mDirty = false; + } + } } @Override @@ -170,106 +190,45 @@ public class DisplayHardwareController extends LiveDisplayFeature { pw.println(" mUseCABC=" + mUseCABC); pw.println(); pw.println(" DisplayHardwareController State:"); - pw.println(" mAutoContrast=" + mAutoContrast); - pw.println(" mColorEnhancement=" + mColorEnhancement); - pw.println(" mCABC=" + mCABC); + pw.println(" mAutoContrast=" + isAutoContrastEnabled()); + pw.println(" mColorEnhancement=" + isColorEnhancementEnabled()); + pw.println(" mCABC=" + isCABCEnabled()); pw.println(" mColorAdjustment=" + Arrays.toString(mColorAdjustment)); pw.println(" mAdditionalAdjustment=" + Arrays.toString(mAdditionalAdjustment)); - pw.println(" mRGB=" + Arrays.toString(mRGB)); - } - - boolean hasColorAdjustment() { - return mUseColorAdjustment; - } - - /** - * Additional adjustments provided by night mode - * - * @param adj - */ - synchronized void setAdditionalAdjustment(float[] adj) { - if (DEBUG) { - Slog.d(TAG, "setAdditionalAdjustment: " + Arrays.toString(adj)); - } - // Sanity check this so we don't mangle the display - if (adj != null && adj.length == 3 && - !(adj[0] <= 0.0f && adj[1] <= 0.0f && adj[2] <= 0.0f)) { - for (int i = 0; i < 3; i++) { - if (adj[i] > 1.0f) { - adj[i] = 1.0f; - } - } - System.arraycopy(adj, 0, mAdditionalAdjustment, 0, 3); - updateColorAdjustment(); - } else { - mAdditionalAdjustment[0] = 1.0f; - mAdditionalAdjustment[1] = 1.0f; - mAdditionalAdjustment[2] = 1.0f; - } - + pw.println(" hardware setting=" + Arrays.toString(mHardware.getDisplayColorCalibration())); } /** * Automatic contrast optimization */ - private synchronized void updateAutoContrast() { + private void updateAutoContrast() { if (!mUseAutoContrast) { return; } - - boolean value = getInt(CMSettings.System.DISPLAY_AUTO_CONTRAST, - (mDefaultAutoContrast ? 1 : 0)) == 1; - - boolean enabled = !isLowPowerMode() && value; - - if (enabled == mAutoContrast) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_AUTO_CONTRAST, enabled); - mAutoContrast = enabled; + mHardware.set(CMHardwareManager.FEATURE_AUTO_CONTRAST, + !isLowPowerMode() && isAutoContrastEnabled()); } /** * Color enhancement is optional */ - private synchronized void updateColorEnhancement() { + private void updateColorEnhancement() { if (!mUseColorEnhancement) { return; } - - boolean value = getInt(CMSettings.System.DISPLAY_COLOR_ENHANCE, - (mDefaultColorEnhancement ? 1 : 0)) == 1; - - boolean enabled = !isLowPowerMode() && value; - - if (enabled == mColorEnhancement) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT, enabled); - mColorEnhancement = enabled; + mHardware.set(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT, + !isLowPowerMode() && isColorEnhancementEnabled()); } /** * Adaptive backlight / low power mode. Turn it off when under very bright light. */ - private synchronized void updateCABCMode() { + private void updateCABCMode() { if (!mUseCABC) { return; } - - boolean value = getInt(CMSettings.System.DISPLAY_CABC, - (mDefaultCABC ? 1 : 0)) == 1; - - boolean enabled = !isLowPowerMode() && value; - - if (enabled == mCABC) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT, value); - mCABC = value; + mHardware.set(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT, + !isLowPowerMode() && isCABCEnabled()); } private synchronized void updateColorAdjustment() { @@ -277,34 +236,76 @@ public class DisplayHardwareController extends LiveDisplayFeature { return; } - final float[] rgb = new float[] { 1.0f, 1.0f, 1.0f }; + final float[] rgb = getDefaultAdjustment(); if (!isLowPowerMode()) { - System.arraycopy(mAdditionalAdjustment, 0, rgb, 0, 3); rgb[0] *= mColorAdjustment[0]; rgb[1] *= mColorAdjustment[1]; rgb[2] *= mColorAdjustment[2]; } - if (rgb[0] == mRGB[0] && rgb[1] == mRGB[1] && rgb[2] == mRGB[2]) { - // no changes - return; - } - if (DEBUG) { Slog.d(TAG, "updateColorAdjustment: " + Arrays.toString(rgb)); } - int max = mHardware.getDisplayColorCalibrationMax(); - mHardware.setDisplayColorCalibration(new int[] { - (int) Math.ceil(rgb[0] * max), - (int) Math.ceil(rgb[1] * max), - (int) Math.ceil(rgb[2] * max) - }); - System.arraycopy(rgb, 0, mRGB, 0, 3); + if (validateColors(rgb)) { + animateDisplayColor(rgb); + } + } - screenRefresh(); + /** + * Smoothly animate the current display colors to the new value. + */ + private synchronized void animateDisplayColor(float[] targetColors) { + + // always start with the current values in the hardware + int[] currentInts = mHardware.getDisplayColorCalibration(); + float[] currentColors = new float[] { + (float)currentInts[0] / (float)mMaxColor, + (float)currentInts[1] / (float)mMaxColor, + (float)currentInts[2] / (float)mMaxColor }; + + if (currentColors[0] == targetColors[0] && + currentColors[1] == targetColors[1] && + currentColors[2] == targetColors[2]) { + return; + } + + // max 500 ms, scaled vs. the largest delta + long duration = (long)(750 * (Math.max(Math.max( + Math.abs(currentColors[0] - targetColors[0]), + Math.abs(currentColors[1] - targetColors[1])), + Math.abs(currentColors[2] - targetColors[2])))); + + if (DEBUG) { + Slog.d(TAG, "animateDisplayColor current=" + Arrays.toString(currentColors) + + " targetColors=" + Arrays.toString(targetColors) + " duration=" + duration); + } + + if (mAnimator != null) { + mAnimator.cancel(); + mAnimator.removeAllUpdateListeners(); + } + + mAnimator = ValueAnimator.ofObject( + new FloatArrayEvaluator(new float[3]), currentColors, targetColors); + mAnimator.setDuration(duration); + mAnimator.setInterpolator(new LinearInterpolator()); + mAnimator.addUpdateListener(new AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(final ValueAnimator animation) { + synchronized (DisplayHardwareController.this) { + float[] value = (float[])animation.getAnimatedValue(); + mHardware.setDisplayColorCalibration(new int[] { + (int)(value[0] * mMaxColor), + (int)(value[1] * mMaxColor), + (int)(value[2] * mMaxColor) }); + screenRefresh(); + } + } + }); + mAnimator.start(); } /** @@ -325,6 +326,75 @@ public class DisplayHardwareController extends LiveDisplayFeature { } } + /** + * Ensure all values are within range + * + * @param colors + * @return true if valid + */ + private boolean validateColors(float[] colors) { + if (colors != null && colors.length == 3 && + !(colors[0] <= 0.0f && colors[1] <= 0.0f && colors[2] <= 0.0f)) { + for (int i = 0; i < 3; i++) { + if (colors[i] > 1.0f) { + colors[i] = 1.0f; + } + } + return true; + } + + colors[0] = 1.0f; + colors[1] = 1.0f; + colors[2] = 1.0f; + return false; + } + + /** + * Parse and sanity check an RGB triplet from a string. + */ + private boolean parseColorAdjustment(String rgbString, float[] dest) { + String[] adj = rgbString == null ? null : rgbString.split(" "); + + if (adj == null || adj.length != 3 || dest == null || dest.length != 3) { + return false; + } + + try { + dest[0] = Float.parseFloat(adj[0]); + dest[1] = Float.parseFloat(adj[1]); + dest[2] = Float.parseFloat(adj[2]); + } catch (NumberFormatException e) { + Slog.e(TAG, e.getMessage(), e); + return false; + } + + // sanity check + return validateColors(dest); + } + + /** + * Additional adjustments provided by night mode + * + * @param adj + */ + synchronized boolean setAdditionalAdjustment(float[] adj) { + if (!mUseColorAdjustment) { + return false; + } + + if (DEBUG) { + Slog.d(TAG, "setAdditionalAdjustment: " + Arrays.toString(adj)); + } + + // Sanity check this so we don't mangle the display + if (validateColors(adj)) { + System.arraycopy(adj, 0, mAdditionalAdjustment, 0, 3); + updateColorAdjustment(); + return true; + } + return false; + } + boolean getDefaultCABC() { return mDefaultCABC; } @@ -339,97 +409,77 @@ public class DisplayHardwareController extends LiveDisplayFeature { boolean isAutoContrastEnabled() { return mUseAutoContrast && - getInt(CMSettings.System.DISPLAY_AUTO_CONTRAST, - (mDefaultAutoContrast ? 1 : 0)) == 1; + getBoolean(CMSettings.System.DISPLAY_AUTO_CONTRAST, mDefaultAutoContrast); } boolean setAutoContrastEnabled(boolean enabled) { if (!mUseAutoContrast) { return false; } - putInt(CMSettings.System.DISPLAY_AUTO_CONTRAST, enabled ? 1 : 0); + putBoolean(CMSettings.System.DISPLAY_AUTO_CONTRAST, enabled); return true; } boolean isCABCEnabled() { return mUseCABC && - getInt(CMSettings.System.DISPLAY_CABC, - (mDefaultCABC ? 1 : 0)) == 1; + getBoolean(CMSettings.System.DISPLAY_CABC, mDefaultCABC); } boolean setCABCEnabled(boolean enabled) { if (!mUseCABC) { return false; } - putInt(CMSettings.System.DISPLAY_CABC, enabled ? 1 : 0); + putBoolean(CMSettings.System.DISPLAY_CABC, enabled); return true; } boolean isColorEnhancementEnabled() { return mUseColorEnhancement && - getInt(CMSettings.System.DISPLAY_COLOR_ENHANCE, - (mDefaultColorEnhancement ? 1 : 0)) == 1; + getBoolean(CMSettings.System.DISPLAY_COLOR_ENHANCE, + mDefaultColorEnhancement); } boolean setColorEnhancementEnabled(boolean enabled) { if (!mUseColorEnhancement) { return false; } - putInt(CMSettings.System.DISPLAY_COLOR_ENHANCE, enabled ? 1 : 0); + putBoolean(CMSettings.System.DISPLAY_COLOR_ENHANCE, enabled); return true; } - float[] getColorAdjustment() { if (!mUseColorAdjustment) { - return new float[] { 1.0f, 1.0f, 1.0f }; + return getDefaultAdjustment(); } - return parseColorAdjustment(getString(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT)); + float[] cur = new float[3]; + if (!parseColorAdjustment(getString(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT), cur)) { + // clear it out if invalid + cur = getDefaultAdjustment(); + saveColorAdjustmentString(cur); + } + return cur; } boolean setColorAdjustment(float[] adj) { // sanity check - if (!mUseColorAdjustment || adj.length != 3 || - adj[0] < 0 || adj[0] > 1.0f || - adj[1] < 0 || adj[1] > 1.0f || - adj[2] < 0 || adj[2] > 1.0f) { + if (!mUseColorAdjustment || !validateColors(adj)) { return false; } - StringBuilder sb = new StringBuilder(); - sb.append(adj[0]).append(" ").append(adj[1]).append(" ").append(adj[2]); - - putString(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT, sb.toString()); + saveColorAdjustmentString(adj); return true; } - /** - * Parse and sanity check an RGB triplet from a string. - */ - private float[] parseColorAdjustment(String rgbString) { - String[] adj = rgbString == null ? null : rgbString.split(" "); - float[] parsed = new float[3]; + private void saveColorAdjustmentString(final float[] adj) { + StringBuilder sb = new StringBuilder(); + sb.append(adj[0]).append(" ").append(adj[1]).append(" ").append(adj[2]); + putString(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT, sb.toString()); + } - if (adj == null || adj.length != 3) { - adj = new String[] { "1.0", "1.0", "1.0" }; - } + boolean hasColorAdjustment() { + return mUseColorAdjustment; + } - try { - parsed[0] = Float.parseFloat(adj[0]); - parsed[1] = Float.parseFloat(adj[1]); - parsed[2] = Float.parseFloat(adj[2]); - } catch (NumberFormatException e) { - Slog.e(TAG, e.getMessage(), e); - parsed[0] = 1.0f; - parsed[1] = 1.0f; - parsed[2] = 1.0f; - } - - // sanity check - for (int i = 0; i < parsed.length; i++) { - if (parsed[i] <= 0.0f || parsed[i] > 1.0f) { - parsed[i] = 1.0f; - } - } - return parsed; + private static float[] getDefaultAdjustment() { + return new float[] { 1.0f, 1.0f, 1.0f }; } } diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayFeature.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayFeature.java index 5b1e33c..fe2c335 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayFeature.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayFeature.java @@ -15,6 +15,11 @@ */ package org.cyanogenmod.platform.internal.display; +import static org.cyanogenmod.platform.internal.display.LiveDisplayService.ALL_CHANGED; +import static org.cyanogenmod.platform.internal.display.LiveDisplayService.DISPLAY_CHANGED; +import static org.cyanogenmod.platform.internal.display.LiveDisplayService.MODE_CHANGED; +import static org.cyanogenmod.platform.internal.display.LiveDisplayService.TWILIGHT_CHANGED; + import android.content.ContentResolver; import android.content.Context; import android.net.Uri; @@ -25,6 +30,8 @@ import android.util.Log; import com.android.server.pm.UserContentObserver; import com.android.server.twilight.TwilightState; +import org.cyanogenmod.platform.internal.display.LiveDisplayService.State; + import java.io.PrintWriter; import java.util.BitSet; @@ -38,50 +45,67 @@ public abstract class LiveDisplayFeature { protected final Context mContext; protected final Handler mHandler; - private TwilightState mTwilight; - private boolean mLowPowerMode = false; - private boolean mScreenOn = false; - private int mMode = 0; - - private final SettingsObserver mSettingsObserver; + private SettingsObserver mSettingsObserver; + private State mState; public LiveDisplayFeature(Context context, Handler handler) { mContext = context; mHandler = handler; - mSettingsObserver = new SettingsObserver(handler); } - public abstract boolean onStart(); + public abstract void onStart(); - public abstract void onSettingsChanged(Uri uri); + protected abstract void onSettingsChanged(Uri uri); - public void onModeChanged(int mode) { - mMode = mode; + public abstract void dump(PrintWriter pw); + + public abstract boolean getCapabilities(final BitSet caps); + + protected abstract void onUpdate(); + + void update(final int flags, final State state) { + mState = state; + if ((flags & DISPLAY_CHANGED) != 0) { + onScreenStateChanged(); + } + if (((flags & TWILIGHT_CHANGED) != 0) && mState.mTwilight != null) { + onTwilightUpdated(); + } + if ((flags & MODE_CHANGED) != 0) { + onUpdate(); + } + if ((flags & ALL_CHANGED) != 0) { + onSettingsChanged(null); + } } - public void onDisplayStateChanged(boolean screenOn) { - mScreenOn = screenOn; - } - - public void onLowPowerModeChanged(boolean lowPowerMode) { - mLowPowerMode = lowPowerMode; - } - - public void onTwilightUpdated(TwilightState twilight) { - mTwilight = twilight; + void start() { + if (mSettingsObserver == null) { + mSettingsObserver = new SettingsObserver(mHandler); + onStart(); + } } public void onDestroy() { mSettingsObserver.unregister(); } - public abstract void dump(PrintWriter pw); + protected void onScreenStateChanged() { } - abstract void getCapabilities(final BitSet caps); + protected void onTwilightUpdated() { } protected final void registerSettings(Uri... settings) { mSettingsObserver.register(settings); - onSettingsChanged(null); + } + + protected final boolean getBoolean(String setting, boolean defaultValue) { + return CMSettings.System.getIntForUser(mContext.getContentResolver(), + setting, (defaultValue ? 1 : 0), UserHandle.USER_CURRENT) == 1; + } + + protected final void putBoolean(String setting, boolean value) { + CMSettings.System.putIntForUser(mContext.getContentResolver(), + setting, (value ? 1 : 0), UserHandle.USER_CURRENT); } protected final int getInt(String setting, int defaultValue) { @@ -105,23 +129,23 @@ public abstract class LiveDisplayFeature { } protected final boolean isLowPowerMode() { - return mLowPowerMode; + return mState.mLowPowerMode; } protected final int getMode() { - return mMode; + return mState.mMode; } protected final boolean isScreenOn() { - return mScreenOn; + return mState.mScreenOn; } protected final TwilightState getTwilight() { - return mTwilight; + return mState.mTwilight; } protected final boolean isNight() { - return mTwilight != null && mTwilight.isNight(); + return mState.mTwilight != null && mState.mTwilight.isNight(); } final class SettingsObserver extends UserContentObserver { diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayService.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayService.java index abd5e79..015025d 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayService.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/LiveDisplayService.java @@ -19,7 +19,6 @@ import static cyanogenmod.hardware.LiveDisplayManager.FEATURE_MANAGED_OUTDOOR_MO import static cyanogenmod.hardware.LiveDisplayManager.MODE_DAY; import static cyanogenmod.hardware.LiveDisplayManager.MODE_FIRST; import static cyanogenmod.hardware.LiveDisplayManager.MODE_LAST; -import static cyanogenmod.hardware.LiveDisplayManager.MODE_OFF; import static cyanogenmod.hardware.LiveDisplayManager.MODE_OUTDOOR; import android.app.Notification; @@ -37,8 +36,6 @@ import android.net.Uri; import android.os.Binder; import android.os.Handler; import android.os.IBinder; -import android.os.Looper; -import android.os.Message; import android.os.PowerManagerInternal; import android.os.Process; import android.os.UserHandle; @@ -85,11 +82,6 @@ public class LiveDisplayService extends SystemService { private static final String TAG = "LiveDisplay"; - private static final int MSG_MODE_CHANGED = 1; - private static final int MSG_DISPLAY_CHANGED = 2; - private static final int MSG_LOW_POWER_MODE_CHANGED = 3; - private static final int MSG_TWILIGHT_UPDATE = 4; - private final Context mContext; private final Handler mHandler; private final ServiceThread mHandlerThread; @@ -98,13 +90,9 @@ public class LiveDisplayService extends SystemService { private ModeObserver mModeObserver; private TwilightManager mTwilightManager; - private boolean mInitialized = false; private boolean mAwaitingNudge = true; private boolean mSunset = false; - private boolean mLowPowerMode; - private int mDisplayState = -1; - private final List mFeatures = new ArrayList(); private ColorTemperatureController mCTC; @@ -121,18 +109,38 @@ public class LiveDisplayService extends SystemService { private int[] mTileEntryIconRes; private static String ACTION_NEXT_MODE = "cyanogenmod.hardware.NEXT_LIVEDISPLAY_MODE"; - private static String EXTRA_NEXT_MODE = "next_mode"; + + static int MODE_CHANGED = 1; + static int DISPLAY_CHANGED = 2; + static int TWILIGHT_CHANGED = 4; + static int ALL_CHANGED = 255; + + static class State { + public boolean mLowPowerMode = false; + public boolean mScreenOn = false; + public int mMode = -1; + public TwilightState mTwilight = null; + + @Override + public String toString() { + return String.format( + "[mLowPowerMode=%b, mScreenOn=%b, mMode=%d, mTwilight=%s", + mLowPowerMode, mScreenOn, mMode, + (mTwilight == null ? "NULL" : mTwilight.toString())); + } + } + + private final State mState = new State(); public LiveDisplayService(Context context) { super(context); mContext = context; - // We want a slightly higher priority thread to handle these requests mHandlerThread = new ServiceThread(TAG, - Process.THREAD_PRIORITY_DISPLAY + 1, false /*allowIo*/); + Process.THREAD_PRIORITY_DEFAULT, false /*allowIo*/); mHandlerThread.start(); - mHandler = new LiveDisplayHandler(mHandlerThread.getLooper()); + mHandler = new Handler(mHandlerThread.getLooper()); updateCustomTileEntries(); } @@ -163,17 +171,16 @@ public class LiveDisplayService extends SystemService { mOMC = new OutdoorModeController(mContext, mHandler); mFeatures.add(mOMC); - // Call onStart of each feature and get it's capabilities + // Get capabilities, throw out any unused features final BitSet capabilities = new BitSet(); for (Iterator it = mFeatures.iterator(); it.hasNext();) { final LiveDisplayFeature feature = it.next(); - if (feature.onStart()) { - feature.getCapabilities(capabilities); - } else { + if (!feature.getCapabilities(capabilities)) { it.remove(); } } + // static config int defaultMode = mContext.getResources().getInteger( org.cyanogenmod.platform.internal.R.integer.config_defaultLiveDisplayMode); @@ -182,34 +189,51 @@ public class LiveDisplayService extends SystemService { mOMC.getDefaultAutoOutdoorMode(), mDHC.getDefaultAutoContrast(), mDHC.getDefaultCABC(), mDHC.getDefaultColorEnhancement()); + // listeners mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mDisplayManager.registerDisplayListener(mDisplayListener, null); - updateDisplayState(mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()); + mState.mScreenOn = mDisplayManager.getDisplay( + Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON; PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class); pmi.registerLowPowerModeObserver(mLowPowerModeListener); + mState.mLowPowerMode = pmi.getLowPowerModeEnabled(); + + mTwilightManager = LocalServices.getService(TwilightManager.class); + if (mTwilightManager != null) { + mTwilightManager.registerListener(mTwilightListener, mHandler); + mState.mTwilight = mTwilightManager.getCurrentState(); + } if (mConfig.hasModeSupport()) { mModeObserver = new ModeObserver(mHandler); - mModeObserver.update(); - + mState.mMode = mModeObserver.getMode(); mContext.registerReceiver(mNextModeReceiver, new IntentFilter(ACTION_NEXT_MODE)); + publishCustomTile(); } - mTwilightManager = LocalServices.getService(TwilightManager.class); - mTwilightManager.registerListener(mTwilightListener, mHandler); - updateTwilight(); - + // start and update all features for (int i = 0; i < mFeatures.size(); i++) { - mFeatures.get(i).onSettingsChanged(null); + mFeatures.get(i).start(); } - mInitialized = true; + updateFeatures(ALL_CHANGED); } } + private void updateFeatures(final int flags) { + mHandler.post(new Runnable() { + @Override + public void run() { + for (int i = 0; i < mFeatures.size(); i++) { + mFeatures.get(i).update(flags, mState); + } + } + }); + } + private void updateCustomTileEntries() { Resources res = mContext.getResources(); mTileEntries = res.getStringArray(R.array.live_display_entries); @@ -305,7 +329,6 @@ public class LiveDisplayService extends SystemService { private PendingIntent getCustomTileNextModePendingIntent() { Intent i = new Intent(ACTION_NEXT_MODE); - i.putExtra(EXTRA_NEXT_MODE, getNextModeIndex()); return PendingIntent.getBroadcastAsUser(mContext, 0, i, PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.CURRENT); } @@ -321,8 +344,7 @@ public class LiveDisplayService extends SystemService { @Override public void onReceive(Context context, Intent intent) { - int mode = intent.getIntExtra(EXTRA_NEXT_MODE, mConfig.getDefaultMode()); - mModeObserver.setMode(mode); + mModeObserver.setMode(getNextModeIndex()); } }; @@ -440,10 +462,9 @@ public class LiveDisplayService extends SystemService { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println(); pw.println("LiveDisplay Service State:"); - pw.println(" mMode=" + mModeObserver.getMode()); - pw.println(" mDisplayState=" + mDisplayState); - pw.println(" mAwaitingNudge=" + mAwaitingNudge); + pw.println(" mState=" + mState.toString()); pw.println(" mConfig=" + mConfig.toString()); + pw.println(" mAwaitingNudge=" + mAwaitingNudge); for (int i = 0; i < mFeatures.size(); i++) { mFeatures.get(i).dump(pw); @@ -465,8 +486,11 @@ public class LiveDisplayService extends SystemService { @Override public void onDisplayChanged(int displayId) { if (displayId == Display.DEFAULT_DISPLAY) { - mHandler.obtainMessage(MSG_DISPLAY_CHANGED, - mDisplayManager.getDisplay(displayId).getState(), 0).sendToTarget(); + boolean screenOn = isScreenOn(); + if (screenOn != mState.mScreenOn) { + mState.mScreenOn = screenOn; + updateFeatures(DISPLAY_CHANGED); + } } } }; @@ -477,10 +501,9 @@ public class LiveDisplayService extends SystemService { new PowerManagerInternal.LowPowerModeListener() { @Override public void onLowPowerModeChanged(boolean lowPowerMode) { - if (lowPowerMode != mLowPowerMode) { - mLowPowerMode = lowPowerMode; - mHandler.obtainMessage(MSG_LOW_POWER_MODE_CHANGED, - (lowPowerMode ? 1 : 0), 0).sendToTarget(); + if (lowPowerMode != mState.mLowPowerMode) { + mState.mLowPowerMode = lowPowerMode; + updateFeatures(MODE_CHANGED); } } }; @@ -502,8 +525,13 @@ public class LiveDisplayService extends SystemService { @Override protected void update() { - mHandler.obtainMessage(MSG_MODE_CHANGED, getMode()).sendToTarget(); - publishCustomTile(); + int mode = getMode(); + if (mode != mState.mMode) { + mState.mMode = mode; + + updateFeatures(MODE_CHANGED); + publishCustomTile(); + } } int getMode() { @@ -514,6 +542,9 @@ public class LiveDisplayService extends SystemService { boolean setMode(int mode) { if (mConfig.hasFeature(mode) && mode >= MODE_FIRST && mode <= MODE_LAST) { putInt(CMSettings.System.DISPLAY_TEMPERATURE_MODE, mode); + if (mode != mConfig.getDefaultMode()) { + stopNudgingMe(); + } return true; } return false; @@ -524,11 +555,17 @@ public class LiveDisplayService extends SystemService { private final TwilightListener mTwilightListener = new TwilightListener() { @Override public void onTwilightStateChanged() { - mHandler.obtainMessage(MSG_TWILIGHT_UPDATE, - mTwilightManager.getCurrentState()).sendToTarget(); + mState.mTwilight = mTwilightManager.getCurrentState(); + updateFeatures(TWILIGHT_CHANGED); + nudge(); } }; + private boolean isScreenOn() { + return mDisplayManager.getDisplay( + Display.DEFAULT_DISPLAY).getState() == Display.STATE_ON; + } + private int getSunsetCounter() { // Counter used to determine when we should tell the user about this feature. // If it's not used after 3 sunsets, we'll show the hint once. @@ -615,68 +652,4 @@ public class LiveDisplayService extends SystemService { CMSettings.System.putIntForUser(mContext.getContentResolver(), setting, value, UserHandle.USER_CURRENT); } - - private synchronized void updateTwilight() { - final TwilightState twilight = mTwilightManager.getCurrentState(); - for (int i = 0; i < mFeatures.size(); i++) { - mFeatures.get(i).onTwilightUpdated(twilight); - } - } - - private synchronized void updateDisplayState(int displayState) { - if (mDisplayState != displayState) { - mDisplayState = displayState; - - for (int i = 0; i < mFeatures.size(); i++) { - mFeatures.get(i).onDisplayStateChanged(displayState == Display.STATE_ON); - } - } - } - - private synchronized void updateMode(int mode) { - for (int i = 0; i < mFeatures.size(); i++) { - mFeatures.get(i).onModeChanged(mode); - } - } - - private synchronized void updateLowPowerMode(boolean lowPowerMode) { - if (mLowPowerMode != lowPowerMode) { - mLowPowerMode = lowPowerMode; - - for (int i = 0; i < mFeatures.size(); i++) { - mFeatures.get(i).onLowPowerModeChanged(mLowPowerMode); - } - } - } - - private final class LiveDisplayHandler extends Handler { - public LiveDisplayHandler(Looper looper) { - super(looper, null, true /*async*/); - } - - @Override - public void handleMessage(Message msg) { - if (!mInitialized) { - return; - } - - switch (msg.what) { - case MSG_DISPLAY_CHANGED: - updateDisplayState(msg.arg1); - break; - case MSG_LOW_POWER_MODE_CHANGED: - updateLowPowerMode(msg.arg1 == 1); - break; - case MSG_TWILIGHT_UPDATE: - updateTwilight(); - nudge(); - break; - case MSG_MODE_CHANGED: - stopNudgingMe(); - int mode = msg.obj == null ? MODE_OFF : (Integer)msg.obj; - updateMode(mode); - break; - } - } - } } diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/OutdoorModeController.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/OutdoorModeController.java index f20979e..797a92e 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/display/OutdoorModeController.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/display/OutdoorModeController.java @@ -23,8 +23,6 @@ import android.content.Context; import android.net.Uri; import android.os.Handler; -import com.android.server.twilight.TwilightState; - import java.io.PrintWriter; import java.util.BitSet; @@ -34,19 +32,16 @@ import cyanogenmod.providers.CMSettings; public class OutdoorModeController extends LiveDisplayFeature { - private CMHardwareManager mHardware; + private final CMHardwareManager mHardware; private AmbientLuxObserver mLuxObserver; // hardware capabilities - private boolean mUseOutdoorMode; - private boolean mSelfManaged; + private final boolean mUseOutdoorMode; // default values - private int mDefaultOutdoorLux; - private boolean mDefaultAutoOutdoorMode; - - // current values - private boolean mAutoOutdoorMode; + private final int mDefaultOutdoorLux; + private final boolean mDefaultAutoOutdoorMode; + private final boolean mSelfManaged; // internal state private boolean mIsOutdoor; @@ -57,23 +52,23 @@ public class OutdoorModeController extends LiveDisplayFeature { public OutdoorModeController(Context context, Handler handler) { super(context, handler); - } - @Override - public boolean onStart() { mHardware = CMHardwareManager.getInstance(mContext); - if (!mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT)) { - return false; - } - - mUseOutdoorMode = true; + mUseOutdoorMode = mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT); + mSelfManaged = mUseOutdoorMode && mHardware.isSunlightEnhancementSelfManaged(); mDefaultOutdoorLux = mContext.getResources().getInteger( org.cyanogenmod.platform.internal.R.integer.config_outdoorAmbientLux); mDefaultAutoOutdoorMode = mContext.getResources().getBoolean( org.cyanogenmod.platform.internal.R.bool.config_defaultAutoOutdoorMode); + } + + @Override + public void onStart() { + if (!mUseOutdoorMode) { + return; + } - mSelfManaged = mHardware.isSunlightEnhancementSelfManaged(); if (!mSelfManaged) { mLuxObserver = new AmbientLuxObserver(mContext, mHandler.getLooper(), mDefaultOutdoorLux, SENSOR_WINDOW_MS); @@ -81,50 +76,48 @@ public class OutdoorModeController extends LiveDisplayFeature { registerSettings( CMSettings.System.getUriFor(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE)); - return true; } @Override - void getCapabilities(final BitSet caps) { + public boolean getCapabilities(final BitSet caps) { if (mUseOutdoorMode) { caps.set(LiveDisplayManager.MODE_OUTDOOR); if (mSelfManaged) { caps.set(LiveDisplayManager.FEATURE_MANAGED_OUTDOOR_MODE); } } + return mUseOutdoorMode; } @Override - public void onModeChanged(int mode) { - super.onModeChanged(mode); + protected void onUpdate() { updateOutdoorMode(); } @Override - public void onDisplayStateChanged(boolean screenOn) { - super.onDisplayStateChanged(screenOn); - if (mSelfManaged) { + protected void onTwilightUpdated() { + updateOutdoorMode(); + } + + @Override + protected synchronized void onScreenStateChanged() { + if (!mUseOutdoorMode) { return; } - updateOutdoorMode(); - } - @Override - public void onLowPowerModeChanged(boolean lowPowerMode) { - super.onLowPowerModeChanged(lowPowerMode); - updateOutdoorMode(); + // toggle the sensor when screen on/off + updateSensorState(); + + // Disable outdoor mode on screen off so that we don't melt the users + // face if they turn it back on in normal conditions + if (!isScreenOn() && !mSelfManaged && getMode() != MODE_OUTDOOR) { + mIsOutdoor = false; + mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, false); + } } @Override public synchronized void onSettingsChanged(Uri uri) { - mAutoOutdoorMode = getInt(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, - (mDefaultAutoOutdoorMode ? 1 : 0)) == 1; - updateOutdoorMode(); - } - - @Override - public void onTwilightUpdated(TwilightState twilight) { - super.onTwilightUpdated(twilight); updateOutdoorMode(); } @@ -137,31 +130,41 @@ public class OutdoorModeController extends LiveDisplayFeature { pw.println(" mDefaultOutdoorLux=" + mDefaultOutdoorLux); pw.println(); pw.println(" OutdoorModeController State:"); - pw.println(" mAutoOutdoorMode=" + mAutoOutdoorMode); + pw.println(" mAutoOutdoorMode=" + isAutomaticOutdoorModeEnabled()); pw.println(" mIsOutdoor=" + mIsOutdoor); pw.println(" mIsNight=" + isNight()); + pw.println(" hardware state=" + + mHardware.get(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT)); } mLuxObserver.dump(pw); } - boolean setAutomaticOutdoorModeEnabled(boolean enabled) { - if (!mUseOutdoorMode) { - return false; + private synchronized void updateSensorState() { + if (!mUseOutdoorMode || mLuxObserver == null || mSelfManaged) { + return; } - putInt(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, (enabled ? 1 : 0)); - return true; - } - boolean isAutomaticOutdoorModeEnabled() { - return mUseOutdoorMode; - } - - boolean getDefaultAutoOutdoorMode() { - return mDefaultAutoOutdoorMode; - } - - private void observeAmbientLuxLocked(boolean observe) { - mLuxObserver.setTransitionListener(observe ? mListener : null); + /* + * Light sensor: + */ + boolean sensorEnabled = false; + // no sensor if low power mode or when the screen is off + if (isScreenOn() && !isLowPowerMode()) { + if (isAutomaticOutdoorModeEnabled()) { + int mode = getMode(); + if (mode == MODE_DAY) { + // always turn it on if day mode is selected + sensorEnabled = true; + } else if (mode == MODE_AUTO && !isNight()) { + // in auto mode we turn it on during actual daytime + sensorEnabled = true; + } + } + } + if (mIsSensorEnabled != sensorEnabled) { + mIsSensorEnabled = sensorEnabled; + mLuxObserver.setTransitionListener(sensorEnabled ? mListener : null); + } } /** @@ -171,30 +174,47 @@ public class OutdoorModeController extends LiveDisplayFeature { * TODO: Use the camera or RGB sensor to determine if it's really sunlight */ private synchronized void updateOutdoorMode() { - /* - * Hardware toggle: - * Enabled if outdoor mode explictly selected - * Enabled if outdoor lux exceeded and day mode or auto mode (if not night) - */ - boolean enabled = !isLowPowerMode() && - (getMode() == MODE_OUTDOOR || - (mAutoOutdoorMode && (mSelfManaged || mIsOutdoor) && - ((getMode() == MODE_AUTO && !isNight()) || getMode() == MODE_DAY))); - mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, enabled); + if (!mUseOutdoorMode) { + return; + } - /* Sensor: - * Enabled in day mode - * Enabled in auto mode if it's not night - * Disabled if outdoor mode explicitly selected - * Disabled in low power mode - * Disabled if screen is off + updateSensorState(); + + /* + * Should we turn on outdoor mode or not? + * + * Do nothing if the screen is off. */ - boolean sensorEnabled = !isLowPowerMode() && isScreenOn() && - getMode() != MODE_OUTDOOR && mAutoOutdoorMode && - ((getMode() == MODE_AUTO && !isNight()) || getMode() == MODE_DAY); - if (mIsSensorEnabled != sensorEnabled) { - mIsSensorEnabled = sensorEnabled; - observeAmbientLuxLocked(sensorEnabled); + if (isScreenOn()) { + boolean enabled = false; + // turn it off in low power mode + if (!isLowPowerMode()) { + int mode = getMode(); + // turn it on if the user manually selected the mode + if (mode == MODE_OUTDOOR) { + enabled = true; + } else if (isAutomaticOutdoorModeEnabled()) { + // self-managed mode means we just flip a switch and an external + // implementation does all the sensing. this allows the user + // to turn on/off the feature. + if (mSelfManaged) { + enabled = true; + } else if (mIsOutdoor) { + // if we're here, the sensor detects extremely bright light. + if (mode == MODE_DAY) { + // if the user manually selected day mode, go ahead and + // melt their face + enabled = true; + } else if (mode == MODE_AUTO && !isNight()) { + // if we're in auto mode, we should also check if it's + // night time, since we don't get much sun at night + // on this planet :) + enabled = true; + } + } + } + } + mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, enabled); } } @@ -214,4 +234,21 @@ public class OutdoorModeController extends LiveDisplayFeature { } }; + boolean setAutomaticOutdoorModeEnabled(boolean enabled) { + if (!mUseOutdoorMode) { + return false; + } + putBoolean(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, enabled); + return true; + } + + boolean isAutomaticOutdoorModeEnabled() { + return mUseOutdoorMode && + getBoolean(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, + getDefaultAutoOutdoorMode()); + } + + boolean getDefaultAutoOutdoorMode() { + return mDefaultAutoOutdoorMode; + } }