diff options
-rw-r--r-- | services/core/java/com/android/server/power/DisplayPowerController.java | 473 |
1 files changed, 326 insertions, 147 deletions
diff --git a/services/core/java/com/android/server/power/DisplayPowerController.java b/services/core/java/com/android/server/power/DisplayPowerController.java index b63f625..c18f284 100644 --- a/services/core/java/com/android/server/power/DisplayPowerController.java +++ b/services/core/java/com/android/server/power/DisplayPowerController.java @@ -36,11 +36,13 @@ import android.os.PowerManager; import android.os.SystemClock; import android.text.format.DateUtils; import android.util.FloatMath; +import android.util.MathUtils; import android.util.Slog; import android.util.Spline; import android.util.TimeUtils; import java.io.PrintWriter; +import java.util.Arrays; /** * Controls the power state of the display. @@ -67,7 +69,7 @@ import java.io.PrintWriter; final class DisplayPowerController { private static final String TAG = "DisplayPowerController"; - private static boolean DEBUG = false; + private static boolean DEBUG = true; private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false; private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false; @@ -110,7 +112,7 @@ final class DisplayPowerController { private static final int MSG_UPDATE_POWER_STATE = 1; private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2; - private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3; + private static final int MSG_UPDATE_AMBIENT_LUX = 3; private static final int PROXIMITY_UNKNOWN = -1; private static final int PROXIMITY_NEGATIVE = 0; @@ -126,31 +128,22 @@ final class DisplayPowerController { // 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; + // Period of time in which to consider light samples in milliseconds. + private static final int AMBIENT_LIGHT_HORIZON = 10000; + + private static final int WEIGHTING_INTERCEPT = AMBIENT_LIGHT_HORIZON; // 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 = 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. - // We can use these filters to assess trends in ambient brightness. - // 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 = 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 that exceeds the hysteresis threshold. - private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000; - private static final long DARKENING_LIGHT_DEBOUNCE = 8000; + // 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 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 @@ -308,18 +301,7 @@ final class DisplayPowerController { // The number of light samples collected since the light sensor was enabled. private int mRecentLightSamples; - // The long-term and short-term filtered light measurements. - 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; + private AmbientLightRingBuffer mAmbientLightRingBuffer; // The screen brightness level that has been chosen by the auto-brightness // algorithm. The actual brightness should ramp towards this value. @@ -398,6 +380,8 @@ final class DisplayPowerController { com.android.internal.R.integer.config_lightSensorWarmupTime); } + mAmbientLightRingBuffer = new AmbientLightRingBuffer(); + mScreenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightnessMinimum); mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON; @@ -916,7 +900,8 @@ final class DisplayPowerController { mLightSensorEnabled = false; mAmbientLuxValid = false; mRecentLightSamples = 0; - mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED); + mAmbientLightRingBuffer.clear(); + mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); mSensorManager.unregisterListener(mLightSensorListener); } } @@ -926,25 +911,16 @@ final class DisplayPowerController { } private void handleLightSensorEvent(long time, float lux) { - mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED); + mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX); applyLightSensorMeasurement(time, lux); updateAmbientLux(time); } private void applyLightSensorMeasurement(long time, float lux) { - // Update our filters. - mRecentLightSamples += 1; - if (mRecentLightSamples == 1) { - mRecentShortTermAverageLux = lux; - mRecentLongTermAverageLux = lux; - } else { - final long timeDelta = time - mLastObservedLuxTime; - mRecentShortTermAverageLux += (lux - mRecentShortTermAverageLux) - * timeDelta / (SHORT_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta); - mRecentLongTermAverageLux += (lux - mRecentLongTermAverageLux) - * timeDelta / (LONG_TERM_AVERAGE_LIGHT_TIME_CONSTANT + timeDelta); - } + mRecentLightSamples++; + mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON); + mAmbientLightRingBuffer.push(time, lux); // Remember this sample value. mLastObservedLux = lux; @@ -957,6 +933,130 @@ final class DisplayPowerController { mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS); } + private float calculateAmbientLux(long now) { + final int N = mAmbientLightRingBuffer.size(); + if (N == 0) { + Slog.e(TAG, "calculateAmbientLux: No ambient light readings available"); + return 0; + } + float sum = 0; + float totalWeight = 0; + long endTime = 1; + for (int i = N - 1; i >= 0; i--) { + long startTime = (mAmbientLightRingBuffer.getTime(i) - now); + float weight = calculateWeight(startTime, endTime); + if (DEBUG) { + Slog.d(TAG, "calculateAmbientLux: [" + + (startTime) + ", " + + (endTime) + "]: " + weight); + } + totalWeight += weight; + sum += mAmbientLightRingBuffer.getLux(i) * weight; + endTime = startTime; + } + if (DEBUG) { + Slog.d(TAG, "calculateAmbientLux: totalWeight=" + totalWeight + + ", newAmbientLux=" + (sum / totalWeight)); + } + return sum / totalWeight; + } + + private static float calculateWeight(long startDelta, long endDelta) { + return weightIntegral(endDelta) - weightIntegral(startDelta); + } + + // Calculates the integral of y = x + WEIGHTING_INTERCEPT from 0 to x + private static float weightIntegral(long x) { + return x * (x * 0.5f + WEIGHTING_INTERCEPT); + } + + private long nextAmbientLightBrighteningTransition(long time) { + final int N = mAmbientLightRingBuffer.size(); + for (int i = 0; i < N; i++) { + if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) { + long nextCheck; + if (i + 1 < N) { + nextCheck = mAmbientLightRingBuffer.getTime(i+1) + AMBIENT_LIGHT_HORIZON; + } else { + nextCheck = time + BRIGHTENING_LIGHT_DEBOUNCE; + } + if (DEBUG) { + Slog.e(TAG, "{lux= " + mAmbientLightRingBuffer.getLux(i) + + ", time= " + mAmbientLightRingBuffer.getTime(i) + + "} is below brightening threshold, checking again in " + + TimeUtils.formatUptime(nextCheck)); + } + return nextCheck; + } + } + if (N == 0) { + long nextCheck = time + BRIGHTENING_LIGHT_DEBOUNCE; + if (DEBUG) { + Slog.e(TAG, "No data, checking again in " + TimeUtils.formatUptime(nextCheck)); + } + return nextCheck; + } + + if (time - mAmbientLightRingBuffer.getTime(0) < BRIGHTENING_LIGHT_DEBOUNCE) { + long nextCheck = mAmbientLightRingBuffer.getTime(0) + BRIGHTENING_LIGHT_DEBOUNCE; + if (DEBUG) { + Slog.e(TAG, "{lux= " + mAmbientLightRingBuffer.getLux(0) + + ", time= " + mAmbientLightRingBuffer.getTime(0) + + "} hasn't passed debounce threshold, checking again in " + + TimeUtils.formatUptime(nextCheck)); + } + return nextCheck; + } + + return 0; + } + + private long nextAmbientLightDarkeningTransition(long time) { + final int N = mAmbientLightRingBuffer.size(); + for (int i = 0; i < N; i ++) { + if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) { + long nextCheck; + if (i + 1 < N) { + nextCheck = mAmbientLightRingBuffer.getTime(i+1) + AMBIENT_LIGHT_HORIZON; + } else { + nextCheck = time + DARKENING_LIGHT_DEBOUNCE; + } + if (DEBUG) { + Slog.e(TAG, "{lux= " + mAmbientLightRingBuffer.getLux(i) + + ", time= " + mAmbientLightRingBuffer.getTime(i) + + "} is above darkening threshold, checking again in " + + TimeUtils.formatUptime(nextCheck)); + } + return nextCheck; + } + } + if (N == 0) { + long nextCheck = time + DARKENING_LIGHT_DEBOUNCE; + if (DEBUG) { + Slog.e(TAG, "No data, checking again in " + TimeUtils.formatUptime(nextCheck)); + } + return nextCheck; + } + + if (time - mAmbientLightRingBuffer.getTime(0) < DARKENING_LIGHT_DEBOUNCE) { + long nextCheck = mAmbientLightRingBuffer.getTime(0) + DARKENING_LIGHT_DEBOUNCE; + if (DEBUG) { + Slog.e(TAG, "{lux= " + mAmbientLightRingBuffer.getLux(0) + + ", time= " + mAmbientLightRingBuffer.getTime(0) + + "} hasn't passed debounce threshold, checking again in " + + TimeUtils.formatUptime(nextCheck)); + } + return nextCheck; + } + return 0; + } + + private void updateAmbientLux() { + long time = SystemClock.uptimeMillis(); + mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON); + updateAmbientLux(time); + } + private void updateAmbientLux(long time) { // If the light sensor was just turned on then immediately update our initial // estimate of the current ambient light level. @@ -964,121 +1064,56 @@ final class DisplayPowerController { final long timeWhenSensorWarmedUp = mLightSensorWarmUpTimeConfig + mLightSensorEnableTime; if (time < timeWhenSensorWarmedUp) { - mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, + if (DEBUG) { + Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: " + + "time=" + time + + ", timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp); + } + mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, timeWhenSensorWarmedUp); return; } - setAmbientLux(mRecentShortTermAverageLux); + setAmbientLux(calculateAmbientLux(time)); mAmbientLuxValid = true; - mDebounceLuxDirection = 0; - mDebounceLuxTime = time; if (DEBUG) { Slog.d(TAG, "updateAmbientLux: Initializing: " - + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux - + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux + + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", mAmbientLux=" + mAmbientLux); } updateAutoBrightness(true); - } else if (mRecentShortTermAverageLux > mBrighteningLuxThreshold - && mRecentLongTermAverageLux > mBrighteningLuxThreshold) { - // The ambient environment appears to be brightening. - if (mDebounceLuxDirection <= 0) { - mDebounceLuxDirection = 1; - mDebounceLuxTime = time; - if (DEBUG) { - Slog.d(TAG, "updateAmbientLux: Possibly brightened, waiting for " - + BRIGHTENING_LIGHT_DEBOUNCE + " ms: " - + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold - + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux - + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux - + ", mAmbientLux=" + mAmbientLux); - } - } - long debounceTime = mDebounceLuxTime + BRIGHTENING_LIGHT_DEBOUNCE; - if (time < debounceTime) { - mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime); - return; - } - setAmbientLux(mRecentShortTermAverageLux); + } + + long nextBrightenTransition = nextAmbientLightBrighteningTransition(time); + long nextDarkenTransition = nextAmbientLightDarkeningTransition(time); + + if (nextBrightenTransition == 0) { + setAmbientLux(calculateAmbientLux(time)); if (DEBUG) { Slog.d(TAG, "updateAmbientLux: Brightened: " + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold - + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux - + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux + + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", mAmbientLux=" + mAmbientLux); } updateAutoBrightness(true); - } else if (mRecentShortTermAverageLux < mDarkeningLuxThreshold - && mRecentLongTermAverageLux < mDarkeningLuxThreshold) { - // The ambient environment appears to be darkening. - if (mDebounceLuxDirection >= 0) { - mDebounceLuxDirection = -1; - mDebounceLuxTime = time; - if (DEBUG) { - Slog.d(TAG, "updateAmbientLux: Possibly darkened, waiting for " - + DARKENING_LIGHT_DEBOUNCE + " ms: " - + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold - + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux - + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux - + ", mAmbientLux=" + mAmbientLux); - } - } - long debounceTime = mDebounceLuxTime + DARKENING_LIGHT_DEBOUNCE; - if (time < debounceTime) { - mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, debounceTime); - return; - } - // Be conservative about reducing the brightness, only reduce it a little bit - // at a time to avoid having to bump it up again soon. - setAmbientLux(Math.max(mRecentShortTermAverageLux, mRecentLongTermAverageLux)); + nextBrightenTransition = nextAmbientLightBrighteningTransition(time); + } else if (nextDarkenTransition == 0) { + setAmbientLux(calculateAmbientLux(time)); if (DEBUG) { Slog.d(TAG, "updateAmbientLux: Darkened: " + "mDarkeningLuxThreshold=" + mDarkeningLuxThreshold - + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux - + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux + + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer + ", mAmbientLux=" + mAmbientLux); } updateAutoBrightness(true); - } else if (mDebounceLuxDirection != 0) { - // No change or change is within the hysteresis thresholds. - mDebounceLuxDirection = 0; - mDebounceLuxTime = time; - if (DEBUG) { - Slog.d(TAG, "updateAmbientLux: Canceled debounce: " - + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold - + ", mDarkeningLuxThreshold=" + mDarkeningLuxThreshold - + ", mRecentShortTermAverageLux=" + mRecentShortTermAverageLux - + ", mRecentLongTermAverageLux=" + mRecentLongTermAverageLux - + ", mAmbientLux=" + mAmbientLux); - } + nextDarkenTransition = nextAmbientLightDarkeningTransition(time); } - - // Now that we've done all of that, we haven't yet posted a debounce - // message. So consider the case where current lux is beyond the - // threshold. It's possible that the light sensor may not report values - // if the light level does not change, so we need to occasionally - // synthesize sensor readings in order to make sure the brightness is - // adjusted accordingly. Note these thresholds may have changed since - // we entered the function because we called setAmbientLux and - // updateAutoBrightness along the way. - if (mLastObservedLux > mBrighteningLuxThreshold - || mLastObservedLux < mDarkeningLuxThreshold) { - mHandler.sendEmptyMessageAtTime(MSG_LIGHT_SENSOR_DEBOUNCED, - time + SYNTHETIC_LIGHT_SENSOR_RATE_MILLIS); - } - } - - private void debounceLightSensor() { - 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); + long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition); + if (nextTransitionTime > time) { + if (DEBUG) { + Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for " + + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime)); } - updateAmbientLux(time); + mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime); } } @@ -1092,7 +1127,7 @@ final class DisplayPowerController { if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT && mPowerRequest.screenAutoBrightnessAdjustment != 0.0f) { - final float adjGamma = FloatMath.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA, + final float adjGamma = MathUtils.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA, Math.min(1.0f, Math.max(-1.0f, -mPowerRequest.screenAutoBrightnessAdjustment))); gamma *= adjGamma; @@ -1260,10 +1295,7 @@ final class DisplayPowerController { 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(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer); pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness); pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness); pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma); @@ -1330,8 +1362,8 @@ final class DisplayPowerController { debounceProximitySensor(); break; - case MSG_LIGHT_SENSOR_DEBOUNCED: - debounceLightSensor(); + case MSG_UPDATE_AMBIENT_LUX: + updateAmbientLux(); break; } } @@ -1377,4 +1409,151 @@ final class DisplayPowerController { updatePowerState(); } }; + + private static class AmbientLightRingBuffer{ + // Proportional extra capacity of the buffer beyond the expected number of light samples + // in the horizon + private static final float BUFFER_SLACK = 1.5f; + private float[] mRingLux; + private long[] mRingTime; + private int mCapacity; + + // The first valid element and the next open slot. + // Note that if mCount is zero then there are no valid elements. + private int mStart; + private int mEnd; + private int mCount; + + public AmbientLightRingBuffer() { + this((int) (AMBIENT_LIGHT_HORIZON / LIGHT_SENSOR_RATE_MILLIS * BUFFER_SLACK)); + } + + public AmbientLightRingBuffer(int initialCapacity) { + mCapacity = initialCapacity; + mRingLux = new float[mCapacity]; + mRingTime = new long[mCapacity]; + mStart = 0; + mEnd = 0; + mCount = 0; + } + + public float getLux(int index) { + if (index >= size() || index < 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + index += mStart; + if (index >= mCapacity) { + index -= mCapacity; + } + return mRingLux[index]; + } + + public long getTime(int index) { + if (index >= size() || index < 0) { + throw new ArrayIndexOutOfBoundsException(index); + } + index += mStart; + if (index >= mCapacity) { + index -= mCapacity; + } + return mRingTime[index]; + } + + public void push(long time, float lux) { + int next = mEnd; + if (mCount == mCapacity) { + int newSize = mCapacity * 2; + + float[] newRingLux = new float[newSize]; + long[] newRingTime = new long[newSize]; + int length = mCapacity - mStart; + System.arraycopy(mRingLux, mStart, newRingLux, 0, length); + System.arraycopy(mRingTime, mStart, newRingTime, 0, length); + if (mStart != 0) { + System.arraycopy(mRingLux, 0, newRingLux, length, mCapacity - length); + System.arraycopy(mRingTime, 0, newRingTime, length, mCapacity - length); + } + mRingLux = newRingLux; + mRingTime = newRingTime; + + next = mCapacity; + mCapacity = newSize; + mStart = 0; + } + mRingTime[next] = time; + mRingLux[next] = lux; + mEnd = next + 1; + if (mEnd == mCapacity) { + mEnd = 0; + } + mCount++; + } + + public void prune(long horizon) { + int removalCount = 0; + while(removalCount < size() && getTime(removalCount) <= horizon) { + removalCount++; + } + + if (removalCount > 0) { + // Some light sensors only produce data upon a change in the ambient light levels, + // so we need to consider the previous measurement as the ambient light level for + // all points in time up until we receive a new measurement. Thus, we always want + // to keep the youngest element that would be removed from the buffer and just set + // its measurement time to the horizon time since at that point it is the ambient + // light level, and to remove it would be to drop a valid data point within our + // horizon. + removalCount--; + + mCount -= removalCount; + mStart += removalCount; + if (mStart >= mCapacity) { + mStart -= mCapacity; + } + + if (getTime(0) < horizon) { + mRingTime[mStart] = horizon; + } + } + } + + public int size() { + return mCount; + } + + public boolean isEmpty() { + return mCount == 0; + } + + public void clear() { + mStart = 0; + mEnd = 0; + mCount = 0; + } + + @Override + public String toString() { + final int length = mCapacity - mStart; + float[] lux = new float[mCount]; + long[] time = new long[mCount]; + + if (mCount <= length) { + System.arraycopy(mRingLux, mStart, lux, 0, mCount); + System.arraycopy(mRingTime, mStart, time, 0, mCount); + } else { + System.arraycopy(mRingLux, mStart, lux, 0, length); + System.arraycopy(mRingLux, 0, lux, length, mCount - length); + + System.arraycopy(mRingTime, mStart, time, 0, length); + System.arraycopy(mRingTime, 0, time, length, mCount - length); + } + return "AmbientLightRingBuffer{mCapacity=" + mCapacity + + ", mStart=" + mStart + + ", mEnd=" + mEnd + + ", mCount=" + mCount + + ", mRingLux=" + Arrays.toString(lux) + + ", mRingTime=" + Arrays.toString(time) + + "}"; + } + } } |