Merge "Add throwing InvalidDisplayException from addView." into jb-mr1-dev
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 59d0f7a..ed51818 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -16,6 +16,8 @@
package android.os;
+import android.util.Log;
+
/**
* Writes trace events to the kernel trace buffer. These trace events can be
* collected using the "atrace" program for offline analysis.
@@ -27,6 +29,8 @@
* @hide
*/
public final class Trace {
+ private static final String TAG = "Trace";
+
// These tags must be kept in sync with frameworks/native/include/utils/Trace.h.
public static final long TRACE_TAG_NEVER = 0;
public static final long TRACE_TAG_ALWAYS = 1L << 0;
@@ -49,7 +53,11 @@
public static final String PROPERTY_TRACE_TAG_ENABLEFLAGS = "debug.atrace.tags.enableflags";
- private static long sEnabledTags = nativeGetEnabledTags();
+ // This works as a "not ready" flag because TRACE_TAG_ALWAYS is always set.
+ private static final long TRACE_FLAGS_NOT_READY = 0;
+
+ // Must be volatile to avoid word tearing.
+ private static volatile long sEnabledTags = TRACE_FLAGS_NOT_READY;
private static native long nativeGetEnabledTags();
private static native void nativeTraceCounter(long tag, String name, int value);
@@ -57,9 +65,17 @@
private static native void nativeTraceEnd(long tag);
static {
+ // We configure two separate change callbacks, one in Trace.cpp and one here. The
+ // native callback reads the tags from the system property, and this callback
+ // reads the value that the native code retrieved. It's essential that the native
+ // callback executes first.
+ //
+ // The system provides ordering through a priority level. Callbacks made through
+ // SystemProperties.addChangeCallback currently have a negative priority, while
+ // our native code is using a priority of zero.
SystemProperties.addChangeCallback(new Runnable() {
@Override public void run() {
- sEnabledTags = nativeGetEnabledTags();
+ cacheEnabledTags();
}
});
}
@@ -68,13 +84,41 @@
}
/**
+ * Caches a copy of the enabled-tag bits. The "master" copy is held by the native code,
+ * and comes from the PROPERTY_TRACE_TAG_ENABLEFLAGS property.
+ * <p>
+ * If the native code hasn't yet read the property, we will cause it to do one-time
+ * initialization. We don't want to do this during class init, because this class is
+ * preloaded, so all apps would be stuck with whatever the zygote saw. (The zygote
+ * doesn't see the system-property update broadcasts.)
+ * <p>
+ * We want to defer initialization until the first use by an app, post-zygote.
+ * <p>
+ * We're okay if multiple threads call here simultaneously -- the native state is
+ * synchronized, and sEnabledTags is volatile (prevents word tearing).
+ */
+ private static long cacheEnabledTags() {
+ long tags = nativeGetEnabledTags();
+ if (tags == TRACE_FLAGS_NOT_READY) {
+ Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags);
+ // keep going
+ }
+ sEnabledTags = tags;
+ return tags;
+ }
+
+ /**
* Returns true if a trace tag is enabled.
*
* @param traceTag The trace tag to check.
* @return True if the trace tag is valid.
*/
public static boolean isTagEnabled(long traceTag) {
- return (sEnabledTags & traceTag) != 0;
+ long tags = sEnabledTags;
+ if (tags == TRACE_FLAGS_NOT_READY) {
+ tags = cacheEnabledTags();
+ }
+ return (tags & traceTag) != 0;
}
/**
@@ -85,7 +129,7 @@
* @param counterValue The counter value.
*/
public static void traceCounter(long traceTag, String counterName, int counterValue) {
- if ((sEnabledTags & traceTag) != 0) {
+ if (isTagEnabled(traceTag)) {
nativeTraceCounter(traceTag, counterName, counterValue);
}
}
@@ -98,7 +142,7 @@
* @param methodName The method name to appear in the trace.
*/
public static void traceBegin(long traceTag, String methodName) {
- if ((sEnabledTags & traceTag) != 0) {
+ if (isTagEnabled(traceTag)) {
nativeTraceBegin(traceTag, methodName);
}
}
@@ -110,7 +154,7 @@
* @param traceTag The trace tag.
*/
public static void traceEnd(long traceTag) {
- if ((sEnabledTags & traceTag) != 0) {
+ if (isTagEnabled(traceTag)) {
nativeTraceEnd(traceTag);
}
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 183b012..550a740 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -758,6 +758,7 @@
public float density;
public float xDpi;
public float yDpi;
+ public boolean secure;
public PhysicalDisplayInfo() {
}
@@ -778,7 +779,8 @@
&& refreshRate == other.refreshRate
&& density == other.density
&& xDpi == other.xDpi
- && yDpi == other.yDpi;
+ && yDpi == other.yDpi
+ && secure == other.secure;
}
@Override
@@ -793,13 +795,15 @@
density = other.density;
xDpi = other.xDpi;
yDpi = other.yDpi;
+ secure = other.secure;
}
// For debugging purposes
@Override
public String toString() {
return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
- + "density " + density + ", " + xDpi + " x " + yDpi + " dpi}";
+ + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
+ + "}";
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index aa54a29..a3360bc 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -29,14 +29,12 @@
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
@@ -859,7 +857,7 @@
if (dirty == null) {
invalidate();
return null;
- } else if (dirty.isEmpty()) {
+ } else if (dirty.isEmpty() && !mIsAnimating) {
return null;
}
@@ -888,14 +886,14 @@
// Intersect with the bounds of the window to skip
// updates that lie outside of the visible region
final float appScale = mAttachInfo.mApplicationScale;
- if (localDirty.intersect(0, 0,
- (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f))) {
- if (!mWillDrawSoon) {
- scheduleTraversals();
- }
- } else {
+ final boolean intersected = localDirty.intersect(0, 0,
+ (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
+ if (!intersected) {
localDirty.setEmpty();
}
+ if (!mWillDrawSoon && (intersected || mIsAnimating)) {
+ scheduleTraversals();
+ }
return null;
}
@@ -1438,7 +1436,13 @@
mTranslator.translateCanvas(layerCanvas);
}
- mView.draw(layerCanvas);
+ DisplayList displayList = mView.mDisplayList;
+ if (displayList != null) {
+ layerCanvas.drawDisplayList(displayList, null,
+ DisplayList.FLAG_CLIP_CHILDREN);
+ } else {
+ mView.draw(layerCanvas);
+ }
drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 8a2c88c..2767e94 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -89,6 +89,7 @@
jfieldID density;
jfieldID xDpi;
jfieldID yDpi;
+ jfieldID secure;
} gPhysicalDisplayInfoClassInfo;
@@ -714,6 +715,7 @@
env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
+ env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
return JNI_TRUE;
}
@@ -907,6 +909,7 @@
gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
+ gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
return err;
}
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 81e68bd..7a38b40 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -763,16 +763,17 @@
}
}
if (mAlpha < 1 && !mCaching) {
- // TODO: should be able to store the size of a DL at record time and not
- // have to pass it into this call. In fact, this information might be in the
- // location/size info that we store with the new native transform data.
- int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
- if (mClipChildren) {
- flags |= SkCanvas::kClipToLayer_SaveFlag;
+ if (!mHasOverlappingRendering) {
+ ALOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
+ } else {
+ int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+ if (mClipChildren) {
+ flags |= SkCanvas::kClipToLayer_SaveFlag;
+ }
+ ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
+ (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+ mMultipliedAlpha, flags);
}
- ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
- (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
- mMultipliedAlpha, flags);
}
if (mClipChildren) {
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
diff --git a/packages/SystemUI/res/drawable-sw600dp/status_bar_recents_background.xml b/packages/SystemUI/res/drawable-sw600dp/status_bar_recents_background.xml
deleted file mode 100644
index 363efeb..0000000
--- a/packages/SystemUI/res/drawable-sw600dp/status_bar_recents_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright 2011, The Android Open Source 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.
- */
--->
-<color xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="#e6000000"
-/>
diff --git a/packages/SystemUI/res/drawable/status_bar_recents_background.xml b/packages/SystemUI/res/drawable/status_bar_recents_background.xml
index 7831db0..ea0b75c 100644
--- a/packages/SystemUI/res/drawable/status_bar_recents_background.xml
+++ b/packages/SystemUI/res/drawable/status_bar_recents_background.xml
@@ -18,8 +18,8 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient name="status_bar_recents_background"
- android:startColor="#e6000000"
- android:endColor="#c0000000"
+ android:startColor="#E0000000"
+ android:endColor="#99000000"
android:angle="@integer/status_bar_recents_bg_gradient_degrees"
/>
</shape>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b5be2ac2..e9ac98f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -183,9 +183,9 @@
<string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Carica"</string>
<string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> dispositivi)"</string>
- <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth non attivo"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth spento"</string>
<string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosità"</string>
- <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotazione automatica"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotazione autom."</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotazione bloccata"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodo di immissione"</string>
<string name="quick_settings_location_label" msgid="3292451598267467545">"Posizione in uso"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 9bdcf5e..f526f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -121,7 +121,9 @@
}
public void cancelExpandHelper() {
- mExpandHelper.cancel();
+ if (mExpandHelper != null) {
+ mExpandHelper.cancel();
+ }
}
}
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
index ba5a475..4abd8f5 100644
--- a/services/java/com/android/server/power/DisplayPowerController.java
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -125,12 +125,18 @@
// Trigger proximity if distance is less than 5 cm.
private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
- // Light sensor event rate in microseconds.
- private static final int LIGHT_SENSOR_RATE = 500 * 1000;
+ // Light sensor event rate in milliseconds.
+ private static final int LIGHT_SENSOR_RATE_MILLIS = 1000;
+
+ // A rate for generating synthetic light sensor events in the case where the light
+ // sensor hasn't reported any new data in a while and we need it to update the
+ // debounce filter. We only synthesize light sensor measurements when needed.
+ private static final int SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS =
+ LIGHT_SENSOR_RATE_MILLIS * 2;
// Brightness animation ramp rate in brightness units per second.
private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
- private static final int BRIGHTNESS_RAMP_RATE_SLOW = 30;
+ private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
// IIR filter time constants in milliseconds for computing two moving averages of
// the light samples. One is a long-term average and the other is a short-term average.
@@ -138,15 +144,15 @@
// The short term average gives us a filtered but relatively low latency measurement.
// The long term average informs us about the overall trend.
private static final long SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 1000;
- private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 8000;
+ private static final long LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT = 5000;
// Stability requirements in milliseconds for accepting a new brightness
// level. This is used for debouncing the light sensor. Different constants
// are used to debounce the light sensor when adapting to brighter or darker environments.
// This parameter controls how quickly brightness changes occur in response to
- // an observed change in light level following a previous change in the opposite direction.
- private static final long BRIGHTENING_LIGHT_DEBOUNCE = 5000;
- private static final long DARKENING_LIGHT_DEBOUNCE = 15000;
+ // an observed change in light level that exceeds the hysteresis threshold.
+ private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000;
+ private static final long DARKENING_LIGHT_DEBOUNCE = 8000;
// Hysteresis constraints for brightening or darkening.
// The recent lux must have changed by at least this fraction relative to the
@@ -290,10 +296,6 @@
// True if mAmbientLux holds a valid value.
private boolean mAmbientLuxValid;
- // The time when the ambient lux was last brightened or darkened.
- private long mLastAmbientBrightenTime;
- private long mLastAmbientDarkenTime;
-
// The most recent light sample.
private float mLastObservedLux;
@@ -307,6 +309,15 @@
private float mRecentShortTermAverageLux;
private float mRecentLongTermAverageLux;
+ // The direction in which the average lux is moving relative to the current ambient lux.
+ // 0 if not changing or within hysteresis threshold.
+ // 1 if brightening beyond hysteresis threshold.
+ // -1 if darkening beyond hysteresis threshold.
+ private int mDebounceLuxDirection;
+
+ // The time when the average lux last changed direction.
+ private long mDebounceLuxTime;
+
// The screen brightness level that has been chosen by the auto-brightness
// algorithm. The actual brightness should ramp towards this value.
// We preserve this value even when we stop using the light sensor so
@@ -547,6 +558,7 @@
final boolean mustNotify;
boolean mustInitialize = false;
boolean updateAutoBrightness = mTwilightChanged;
+ boolean wasDim = false;
mTwilightChanged = false;
synchronized (mLock) {
@@ -566,6 +578,7 @@
!= mPendingRequestLocked.screenAutoBrightnessAdjustment) {
updateAutoBrightness = true;
}
+ wasDim = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM);
mPowerRequest.copyFrom(mPendingRequestLocked);
mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
mPendingWaitForNegativeProximityLocked = false;
@@ -635,9 +648,12 @@
mUsingScreenAutoBrightness = false;
}
if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
- // Screen is dimmed. Sets an upper bound on everything else.
+ // Dim slowly by at least some minimum amount.
target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig);
+ slow = true;
+ } else if (wasDim) {
+ // Brighten quickly.
slow = false;
}
animateScreenBrightness(clampScreenBrightness(target),
@@ -852,7 +868,7 @@
mLightSensorEnabled = true;
mLightSensorEnableTime = SystemClock.uptimeMillis();
mSensorManager.registerListener(mLightSensorListener, mLightSensor,
- LIGHT_SENSOR_RATE, mHandler);
+ LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
}
} else {
if (mLightSensorEnabled) {
@@ -869,6 +885,13 @@
}
private void handleLightSensorEvent(long time, float lux) {
+ mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+
+ applyLightSensorMeasurement(time, lux);
+ updateAmbientLux(time);
+ }
+
+ private void applyLightSensorMeasurement(long time, float lux) {
// Update our filters.
mRecentLightSamples += 1;
if (mRecentLightSamples == 1) {
@@ -885,10 +908,6 @@
// Remember this sample value.
mLastObservedLux = lux;
mLastObservedLuxTime = time;
-
- // Update the ambient lux level.
- mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
- updateAmbientLux(time);
}
private void updateAmbientLux(long time) {
@@ -896,34 +915,46 @@
// estimate of the current ambient light level.
if (!mAmbientLuxValid
|| (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
- if (DEBUG) {
- Slog.d(TAG, "updateAmbientLux: Initializing, "
- + "mAmbientLux=" + (mAmbientLuxValid ? mAmbientLux : -1)
- + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
- + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
- }
mAmbientLux = mRecentShortTermAverageLux;
mAmbientLuxValid = true;
- mLastAmbientBrightenTime = time;
- mLastAmbientDarkenTime = time;
+ mDebounceLuxDirection = 0;
+ mDebounceLuxTime = time;
+ if (DEBUG) {
+ Slog.d(TAG, "updateAmbientLux: Initializing: "
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+ + ", mAmbientLux=" + mAmbientLux);
+ }
updateAutoBrightness(true);
return;
}
// Determine whether the ambient environment appears to be brightening.
- float minAmbientLux = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
- if (mRecentShortTermAverageLux > minAmbientLux
- && mRecentLongTermAverageLux > minAmbientLux) {
- long debounceTime = mLastAmbientDarkenTime + BRIGHTENING_LIGHT_DEBOUNCE;
+ float brighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
+ if (mRecentShortTermAverageLux > brighteningLuxThreshold
+ && mRecentLongTermAverageLux > brighteningLuxThreshold) {
+ if (mDebounceLuxDirection <= 0) {
+ mDebounceLuxDirection = 1;
+ mDebounceLuxTime = time;
+ if (DEBUG) {
+ Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for "
+ + BRIGHTENING_LIGHT_DEBOUNCE + " ms: "
+ + "brighteningLuxThreshold=" + brighteningLuxThreshold
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+ + ", mAmbientLux=" + mAmbientLux);
+ }
+ }
+ long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE;
if (time >= debounceTime) {
+ mAmbientLux = mRecentShortTermAverageLux;
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Brightened: "
- + "mAmbientLux=" + mAmbientLux
+ + "brighteningLuxThreshold=" + brighteningLuxThreshold
+ ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
- + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+ + ", mAmbientLux=" + mAmbientLux);
}
- mLastAmbientBrightenTime = time;
- mAmbientLux = mRecentShortTermAverageLux;
updateAutoBrightness(true);
} else {
mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
@@ -932,28 +963,78 @@
}
// Determine whether the ambient environment appears to be darkening.
- float maxAmbientLux = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
- if (mRecentShortTermAverageLux < maxAmbientLux
- && mRecentLongTermAverageLux < maxAmbientLux) {
- long debounceTime = mLastAmbientBrightenTime + DARKENING_LIGHT_DEBOUNCE;
+ float darkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
+ if (mRecentShortTermAverageLux < darkeningLuxThreshold
+ && mRecentLongTermAverageLux < darkeningLuxThreshold) {
+ if (mDebounceLuxDirection >= 0) {
+ mDebounceLuxDirection = -1;
+ mDebounceLuxTime = time;
+ if (DEBUG) {
+ Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for "
+ + DARKENING_LIGHT_DEBOUNCE + " ms: "
+ + "darkeningLuxThreshold=" + darkeningLuxThreshold
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+ + ", mAmbientLux=" + mAmbientLux);
+ }
+ }
+ long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE;
if (time >= debounceTime) {
+ // Be conservative about reducing the brightness, only reduce it a little bit
+ // at a time to avoid having to bump it up again soon.
+ mAmbientLux = Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux);
if (DEBUG) {
Slog.d(TAG, "updateAmbientLux: Darkened: "
- + "mAmbientLux=" + mAmbientLux
+ + "darkeningLuxThreshold=" + darkeningLuxThreshold
+ ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
- + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+ + ", mAmbientLux=" + mAmbientLux);
}
- mLastAmbientDarkenTime = time;
- mAmbientLux = mRecentShortTermAverageLux;
updateAutoBrightness(true);
} else {
mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime);
}
+ return;
+ }
+
+ // No change or change is within the hysteresis thresholds.
+ if (mDebounceLuxDirection != 0) {
+ mDebounceLuxDirection = 0;
+ mDebounceLuxTime = time;
+ if (DEBUG) {
+ Slog.d(TAG, "updateAmbientLux: Canceled debounce: "
+ + "brighteningLuxThreshold=" + brighteningLuxThreshold
+ + ", darkeningLuxThreshold=" + darkeningLuxThreshold
+ + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux
+ + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux
+ + ", mAmbientLux=" + mAmbientLux);
+ }
+ }
+
+ // If the light level does not change, then the sensor may not report
+ // a new value. This can cause problems for the auto-brightness algorithm
+ // because the filters might not be updated. To work around it, we want to
+ // make sure to update the filters whenever the observed light level could
+ // possibly exceed one of the hysteresis thresholds.
+ if (mLastObservedLux > brighteningLuxThreshold
+ || mLastObservedLux < darkeningLuxThreshold) {
+ mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED,
+ time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS);
}
}
private void debounceLightSensor() {
- updateAmbientLux(SystemClock.uptimeMillis());
+ if (mLightSensorEnabled) {
+ long time = SystemClock.uptimeMillis();
+ if (time >= mLastObservedLuxTime + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS) {
+ if (DEBUG) {
+ Slog.d(TAG, "debounceLightSensor: Synthesizing light sensor measurement "
+ + "after " + (time - mLastObservedLuxTime) + " ms.");
+ }
+ applyLightSensorMeasurement(time, mLastObservedLux);
+ }
+ updateAmbientLux(time);
+ }
}
private void updateAutoBrightness(boolean sendUpdate) {
@@ -1124,16 +1205,14 @@
+ TimeUtils.formatUptime(mLightSensorEnableTime));
pw.println(" mAmbientLux=" + mAmbientLux);
pw.println(" mAmbientLuxValid=" + mAmbientLuxValid);
- pw.println(" mLastAmbientBrightenTime="
- + TimeUtils.formatUptime(mLastAmbientBrightenTime));
- pw.println(" mLastAmbientDimTime="
- + TimeUtils.formatUptime(mLastAmbientDarkenTime));
pw.println(" mLastObservedLux=" + mLastObservedLux);
pw.println(" mLastObservedLuxTime="
+ TimeUtils.formatUptime(mLastObservedLuxTime));
pw.println(" mRecentLightSamples=" + mRecentLightSamples);
pw.println(" mRecentShortTermAverageLux=" + mRecentShortTermAverageLux);
pw.println(" mRecentLongTermAverageLux=" + mRecentLongTermAverageLux);
+ pw.println(" mDebounceLuxDirection=" + mDebounceLuxDirection);
+ pw.println(" mDebounceLuxTime=" + TimeUtils.formatUptime(mDebounceLuxTime));
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);