Merge "Pipe through color sampling to BrightnessChangeEvent"
This commit is contained in:
@@ -1843,7 +1843,9 @@ package android.hardware.display {
|
||||
field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessChangeEvent> CREATOR;
|
||||
field public final float batteryLevel;
|
||||
field public final float brightness;
|
||||
field public final long colorSampleDuration;
|
||||
field public final int colorTemperature;
|
||||
field @Nullable public final long[] colorValueBuckets;
|
||||
field public final boolean isDefaultBrightnessConfig;
|
||||
field public final boolean isUserSetBrightness;
|
||||
field public final float lastBrightness;
|
||||
|
||||
@@ -660,7 +660,9 @@ package android.hardware.display {
|
||||
field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessChangeEvent> CREATOR;
|
||||
field public final float batteryLevel;
|
||||
field public final float brightness;
|
||||
field public final long colorSampleDuration;
|
||||
field public final int colorTemperature;
|
||||
field @Nullable public final long[] colorValueBuckets;
|
||||
field public final boolean isDefaultBrightnessConfig;
|
||||
field public final boolean isUserSetBrightness;
|
||||
field public final float lastBrightness;
|
||||
|
||||
@@ -16,11 +16,15 @@
|
||||
|
||||
package android.hardware.display;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Data about a brightness settings change.
|
||||
*
|
||||
@@ -72,12 +76,29 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
/** Whether brightness curve includes a user brightness point */
|
||||
public final boolean isUserSetBrightness;
|
||||
|
||||
/**
|
||||
* Histogram counting how many times a pixel of a given value was displayed onscreen for the
|
||||
* Value component of HSV if the device supports color sampling, if the device does not support
|
||||
* color sampling the value will be null.
|
||||
* The buckets of the histogram are evenly weighted, the number of buckets is device specific.
|
||||
* For example if we had {10, 6, 4, 1} this means that 10 pixels were in the range
|
||||
* [0x00,0x3f], 6 pixels were in the range [0x40,0x7f] etc.
|
||||
*/
|
||||
@Nullable
|
||||
public final long[] colorValueBuckets;
|
||||
|
||||
/**
|
||||
* How many milliseconds of data are contained in the colorValueBuckets.
|
||||
*/
|
||||
public final long colorSampleDuration;
|
||||
|
||||
|
||||
/** @hide */
|
||||
private BrightnessChangeEvent(float brightness, long timeStamp, String packageName,
|
||||
int userId, float[] luxValues, long[] luxTimestamps, float batteryLevel,
|
||||
float powerBrightnessFactor, boolean nightMode, int colorTemperature,
|
||||
float lastBrightness, boolean isDefaultBrightnessConfig, boolean isUserSetBrightness) {
|
||||
float lastBrightness, boolean isDefaultBrightnessConfig, boolean isUserSetBrightness,
|
||||
long[] colorValueBuckets, long colorSampleDuration) {
|
||||
this.brightness = brightness;
|
||||
this.timeStamp = timeStamp;
|
||||
this.packageName = packageName;
|
||||
@@ -91,6 +112,8 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
this.lastBrightness = lastBrightness;
|
||||
this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
|
||||
this.isUserSetBrightness = isUserSetBrightness;
|
||||
this.colorValueBuckets = colorValueBuckets;
|
||||
this.colorSampleDuration = colorSampleDuration;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@@ -108,6 +131,8 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
this.lastBrightness = other.lastBrightness;
|
||||
this.isDefaultBrightnessConfig = other.isDefaultBrightnessConfig;
|
||||
this.isUserSetBrightness = other.isUserSetBrightness;
|
||||
this.colorValueBuckets = other.colorValueBuckets;
|
||||
this.colorSampleDuration = other.colorSampleDuration;
|
||||
}
|
||||
|
||||
private BrightnessChangeEvent(Parcel source) {
|
||||
@@ -124,6 +149,8 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
lastBrightness = source.readFloat();
|
||||
isDefaultBrightnessConfig = source.readBoolean();
|
||||
isUserSetBrightness = source.readBoolean();
|
||||
colorValueBuckets = source.createLongArray();
|
||||
colorSampleDuration = source.readLong();
|
||||
}
|
||||
|
||||
public static final Creator<BrightnessChangeEvent> CREATOR =
|
||||
@@ -156,6 +183,8 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
dest.writeFloat(lastBrightness);
|
||||
dest.writeBoolean(isDefaultBrightnessConfig);
|
||||
dest.writeBoolean(isUserSetBrightness);
|
||||
dest.writeLongArray(colorValueBuckets);
|
||||
dest.writeLong(colorSampleDuration);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@@ -173,6 +202,8 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
private float mLastBrightness;
|
||||
private boolean mIsDefaultBrightnessConfig;
|
||||
private boolean mIsUserSetBrightness;
|
||||
private long[] mColorValueBuckets;
|
||||
private long mColorSampleDuration;
|
||||
|
||||
/** {@see BrightnessChangeEvent#brightness} */
|
||||
public Builder setBrightness(float brightness) {
|
||||
@@ -252,12 +283,21 @@ public final class BrightnessChangeEvent implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@see BrightnessChangeEvent#valueBuckets} */
|
||||
public Builder setColorValues(@NonNull long[] colorValueBuckets, long colorSampleDuration) {
|
||||
Objects.requireNonNull(colorValueBuckets);
|
||||
mColorValueBuckets = colorValueBuckets;
|
||||
mColorSampleDuration = colorSampleDuration;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds a BrightnessChangeEvent */
|
||||
public BrightnessChangeEvent build() {
|
||||
return new BrightnessChangeEvent(mBrightness, mTimeStamp,
|
||||
mPackageName, mUserId, mLuxValues, mLuxTimestamps, mBatteryLevel,
|
||||
mPowerBrightnessFactor, mNightMode, mColorTemperature, mLastBrightness,
|
||||
mIsDefaultBrightnessConfig, mIsUserSetBrightness);
|
||||
mIsDefaultBrightnessConfig, mIsUserSetBrightness, mColorValueBuckets,
|
||||
mColorSampleDuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@ public class PixelFormat {
|
||||
public static final int RGBA_F16 = 0x16;
|
||||
public static final int RGBA_1010102 = 0x2B;
|
||||
|
||||
/** @hide */
|
||||
public static final int HSV_888 = 0x37;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link android.graphics.ImageFormat#JPEG
|
||||
* ImageFormat.JPEG} instead.
|
||||
@@ -109,6 +112,7 @@ public class PixelFormat {
|
||||
info.bytesPerPixel = 4;
|
||||
break;
|
||||
case RGB_888:
|
||||
case HSV_888:
|
||||
info.bitsPerPixel = 24;
|
||||
info.bytesPerPixel = 3;
|
||||
break;
|
||||
@@ -227,6 +231,8 @@ public class PixelFormat {
|
||||
return "RGBA_F16";
|
||||
case RGBA_1010102:
|
||||
return "RGBA_1010102";
|
||||
case HSV_888:
|
||||
return "HSV_888";
|
||||
case JPEG:
|
||||
return "JPEG";
|
||||
default:
|
||||
|
||||
@@ -27,12 +27,17 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.display.AmbientBrightnessDayStats;
|
||||
import android.hardware.display.BrightnessChangeEvent;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayManagerInternal;
|
||||
import android.hardware.display.DisplayedContentSample;
|
||||
import android.hardware.display.DisplayedContentSamplingAttributes;
|
||||
import android.net.Uri;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Environment;
|
||||
@@ -48,6 +53,7 @@ import android.provider.Settings;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
import android.view.Display;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -55,6 +61,7 @@ import com.android.internal.app.ColorDisplayController;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.RingBuffer;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
@@ -111,6 +118,8 @@ public class BrightnessTracker {
|
||||
private static final String ATTR_DEFAULT_CONFIG = "defaultConfig";
|
||||
private static final String ATTR_POWER_SAVE = "powerSaveFactor";
|
||||
private static final String ATTR_USER_POINT = "userPoint";
|
||||
private static final String ATTR_COLOR_SAMPLE_DURATION = "colorSampleDuration";
|
||||
private static final String ATTR_COLOR_VALUE_BUCKETS = "colorValueBuckets";
|
||||
|
||||
private static final int MSG_BACKGROUND_START = 0;
|
||||
private static final int MSG_BRIGHTNESS_CHANGED = 1;
|
||||
@@ -119,6 +128,10 @@ public class BrightnessTracker {
|
||||
|
||||
private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
|
||||
|
||||
private static final long COLOR_SAMPLE_DURATION = TimeUnit.SECONDS.toSeconds(10);
|
||||
// Sample chanel 2 of HSV which is the Value component.
|
||||
private static final int COLOR_SAMPLE_COMPONENT_MASK = 0x1 << 2;
|
||||
|
||||
// Lock held while accessing mEvents, is held while writing events to flash.
|
||||
private final Object mEventsLock = new Object();
|
||||
@GuardedBy("mEventsLock")
|
||||
@@ -136,12 +149,16 @@ public class BrightnessTracker {
|
||||
private final ContentResolver mContentResolver;
|
||||
private final Handler mBgHandler;
|
||||
|
||||
// mBroadcastReceiver, mSensorListener, mSettingsObserver and mSensorRegistered
|
||||
// should only be used on the mBgHandler thread.
|
||||
// These members should only be accessed on the mBgHandler thread.
|
||||
private BroadcastReceiver mBroadcastReceiver;
|
||||
private SensorListener mSensorListener;
|
||||
private SettingsObserver mSettingsObserver;
|
||||
private DisplayListener mDisplayListener;
|
||||
private boolean mSensorRegistered;
|
||||
private boolean mColorSamplingEnabled;
|
||||
private int mNoFramesToSample;
|
||||
private float mFrameRate;
|
||||
// End of block of members that should only be accessed on the mBgHandler thread.
|
||||
|
||||
private @UserIdInt int mCurrentUserId = UserHandle.USER_NULL;
|
||||
|
||||
@@ -208,6 +225,7 @@ public class BrightnessTracker {
|
||||
mLastBrightness = initialBrightness;
|
||||
mStarted = true;
|
||||
}
|
||||
enableColorSampling();
|
||||
}
|
||||
|
||||
/** Stop listening for events */
|
||||
@@ -226,6 +244,7 @@ public class BrightnessTracker {
|
||||
synchronized (mDataCollectionLock) {
|
||||
mStarted = false;
|
||||
}
|
||||
disableColorSampling();
|
||||
}
|
||||
|
||||
public void onSwitchUser(@UserIdInt int newUserId) {
|
||||
@@ -367,6 +386,17 @@ public class BrightnessTracker {
|
||||
builder.setColorTemperature(mInjector.getColorTemperature(mContext,
|
||||
UserHandle.USER_CURRENT));
|
||||
|
||||
if (mColorSamplingEnabled) {
|
||||
DisplayedContentSample sample = mInjector.sampleColor(mNoFramesToSample);
|
||||
if (sample != null && sample.getSampleComponent(
|
||||
DisplayedContentSample.ColorComponent.CHANNEL2) != null) {
|
||||
float numMillis = (sample.getNumFrames() / mFrameRate) * 1000.0f;
|
||||
builder.setColorValues(
|
||||
sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL2),
|
||||
Math.round(numMillis));
|
||||
}
|
||||
}
|
||||
|
||||
BrightnessChangeEvent event = builder.build();
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Event " + event.brightness + " " + event.packageName);
|
||||
@@ -541,6 +571,19 @@ public class BrightnessTracker {
|
||||
}
|
||||
out.attribute(null, ATTR_LUX, luxValues.toString());
|
||||
out.attribute(null, ATTR_LUX_TIMESTAMPS, luxTimestamps.toString());
|
||||
if (toWrite[i].colorValueBuckets != null
|
||||
&& toWrite[i].colorValueBuckets.length > 0) {
|
||||
out.attribute(null, ATTR_COLOR_SAMPLE_DURATION,
|
||||
Long.toString(toWrite[i].colorSampleDuration));
|
||||
StringBuilder buckets = new StringBuilder();
|
||||
for (int j = 0; j < toWrite[i].colorValueBuckets.length; ++j) {
|
||||
if (j > 0) {
|
||||
buckets.append(',');
|
||||
}
|
||||
buckets.append(Long.toString(toWrite[i].colorValueBuckets[j]));
|
||||
}
|
||||
out.attribute(null, ATTR_COLOR_VALUE_BUCKETS, buckets.toString());
|
||||
}
|
||||
out.endTag(null, TAG_EVENT);
|
||||
}
|
||||
}
|
||||
@@ -628,6 +671,20 @@ public class BrightnessTracker {
|
||||
builder.setUserBrightnessPoint(Boolean.parseBoolean(userPoint));
|
||||
}
|
||||
|
||||
String colorSampleDurationString =
|
||||
parser.getAttributeValue(null, ATTR_COLOR_SAMPLE_DURATION);
|
||||
String colorValueBucketsString =
|
||||
parser.getAttributeValue(null, ATTR_COLOR_VALUE_BUCKETS);
|
||||
if (colorSampleDurationString != null && colorValueBucketsString != null) {
|
||||
long colorSampleDuration = Long.parseLong(colorSampleDurationString);
|
||||
String[] buckets = colorValueBucketsString.split(",");
|
||||
long[] bucketValues = new long[buckets.length];
|
||||
for (int i = 0; i < bucketValues.length; ++i) {
|
||||
bucketValues[i] = Long.parseLong(buckets[i]);
|
||||
}
|
||||
builder.setColorValues(bucketValues, colorSampleDuration);
|
||||
}
|
||||
|
||||
BrightnessChangeEvent event = builder.build();
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Read event " + event.brightness
|
||||
@@ -695,6 +752,73 @@ public class BrightnessTracker {
|
||||
|
||||
private void dumpLocal(PrintWriter pw) {
|
||||
pw.println(" mSensorRegistered=" + mSensorRegistered);
|
||||
pw.println(" mColorSamplingEnabled=" + mColorSamplingEnabled);
|
||||
pw.println(" mNoFramesToSample=" + mNoFramesToSample);
|
||||
pw.println(" mFrameRate=" + mFrameRate);
|
||||
}
|
||||
|
||||
private void enableColorSampling() {
|
||||
if (!mInjector.isBrightnessModeAutomatic(mContentResolver)
|
||||
|| !mInjector.isInteractive(mContext)
|
||||
|| mColorSamplingEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
mFrameRate = mInjector.getFrameRate(mContext);
|
||||
if (mFrameRate <= 0) {
|
||||
Slog.wtf(TAG, "Default display has a zero or negative framerate.");
|
||||
return;
|
||||
}
|
||||
mNoFramesToSample = (int) (mFrameRate * COLOR_SAMPLE_DURATION);
|
||||
|
||||
DisplayedContentSamplingAttributes attributes = mInjector.getSamplingAttributes();
|
||||
if (DEBUG && attributes != null) {
|
||||
Slog.d(TAG, "Color sampling"
|
||||
+ " mask=0x" + Integer.toHexString(attributes.getComponentMask())
|
||||
+ " dataSpace=0x" + Integer.toHexString(attributes.getDataspace())
|
||||
+ " pixelFormat=0x" + Integer.toHexString(attributes.getPixelFormat()));
|
||||
}
|
||||
// Do we support sampling the Value component of HSV
|
||||
if (attributes != null && attributes.getPixelFormat() == PixelFormat.HSV_888
|
||||
&& (attributes.getComponentMask() & COLOR_SAMPLE_COMPONENT_MASK) != 0) {
|
||||
|
||||
mColorSamplingEnabled = mInjector.enableColorSampling(/* enable= */true,
|
||||
mNoFramesToSample);
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "turning on color sampling for "
|
||||
+ mNoFramesToSample + " frames, success=" + mColorSamplingEnabled);
|
||||
}
|
||||
}
|
||||
if (mColorSamplingEnabled && mDisplayListener == null) {
|
||||
mDisplayListener = new DisplayListener();
|
||||
mInjector.registerDisplayListener(mContext, mDisplayListener, mBgHandler);
|
||||
}
|
||||
}
|
||||
|
||||
private void disableColorSampling() {
|
||||
if (!mColorSamplingEnabled) {
|
||||
return;
|
||||
}
|
||||
mInjector.enableColorSampling(/* enable= */ false, /* noFrames= */ 0);
|
||||
mColorSamplingEnabled = false;
|
||||
if (mDisplayListener != null) {
|
||||
mInjector.unRegisterDisplayListener(mContext, mDisplayListener);
|
||||
mDisplayListener = null;
|
||||
}
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "turning off color sampling");
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColorSampling() {
|
||||
if (!mColorSamplingEnabled) {
|
||||
return;
|
||||
}
|
||||
float frameRate = mInjector.getFrameRate(mContext);
|
||||
if (frameRate != mFrameRate) {
|
||||
disableColorSampling();
|
||||
enableColorSampling();
|
||||
}
|
||||
}
|
||||
|
||||
public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId) {
|
||||
@@ -768,6 +892,26 @@ public class BrightnessTracker {
|
||||
}
|
||||
}
|
||||
|
||||
private final class DisplayListener implements DisplayManager.DisplayListener {
|
||||
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayChanged(int displayId) {
|
||||
if (displayId == Display.DEFAULT_DISPLAY) {
|
||||
updateColorSampling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class SettingsObserver extends ContentObserver {
|
||||
public SettingsObserver(Handler handler) {
|
||||
super(handler);
|
||||
@@ -828,9 +972,11 @@ public class BrightnessTracker {
|
||||
break;
|
||||
case MSG_START_SENSOR_LISTENER:
|
||||
startSensorListener();
|
||||
enableColorSampling();
|
||||
break;
|
||||
case MSG_STOP_SENSOR_LISTENER:
|
||||
stopSensorListener();
|
||||
disableColorSampling();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -957,5 +1103,44 @@ public class BrightnessTracker {
|
||||
public boolean isNightModeActive(Context context, int userId) {
|
||||
return new ColorDisplayController(context, userId).isActivated();
|
||||
}
|
||||
|
||||
public DisplayedContentSample sampleColor(int noFramesToSample) {
|
||||
final DisplayManagerInternal displayManagerInternal =
|
||||
LocalServices.getService(DisplayManagerInternal.class);
|
||||
return displayManagerInternal.getDisplayedContentSample(
|
||||
Display.DEFAULT_DISPLAY, noFramesToSample, 0);
|
||||
}
|
||||
|
||||
public float getFrameRate(Context context) {
|
||||
final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
|
||||
Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
|
||||
return display.getRefreshRate();
|
||||
}
|
||||
|
||||
public DisplayedContentSamplingAttributes getSamplingAttributes() {
|
||||
final DisplayManagerInternal displayManagerInternal =
|
||||
LocalServices.getService(DisplayManagerInternal.class);
|
||||
return displayManagerInternal.getDisplayedContentSamplingAttributes(
|
||||
Display.DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
public boolean enableColorSampling(boolean enable, int noFrames) {
|
||||
final DisplayManagerInternal displayManagerInternal =
|
||||
LocalServices.getService(DisplayManagerInternal.class);
|
||||
return displayManagerInternal.setDisplayedContentSamplingEnabled(
|
||||
Display.DEFAULT_DISPLAY, enable, COLOR_SAMPLE_COMPONENT_MASK, noFrames);
|
||||
}
|
||||
|
||||
public void registerDisplayListener(Context context,
|
||||
DisplayManager.DisplayListener listener, Handler handler) {
|
||||
final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
|
||||
displayManager.registerDisplayListener(listener, handler);
|
||||
}
|
||||
|
||||
public void unRegisterDisplayListener(Context context,
|
||||
DisplayManager.DisplayListener listener) {
|
||||
final DisplayManager displayManager = context.getSystemService(DisplayManager.class);
|
||||
displayManager.unregisterDisplayListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,9 @@ import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.display.AmbientBrightnessDayStats;
|
||||
import android.hardware.display.BrightnessChangeEvent;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.display.DisplayedContentSample;
|
||||
import android.hardware.display.DisplayedContentSamplingAttributes;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
@@ -47,6 +50,7 @@ import android.os.SystemClock;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.util.AtomicFile;
|
||||
import android.view.Display;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -116,28 +120,81 @@ public class BrightnessTrackerTest {
|
||||
assertTrue(mInjector.mIdleScheduled);
|
||||
mInjector.sendScreenChange(/*screen on */ true);
|
||||
assertNotNull(mInjector.mSensorListener);
|
||||
assertTrue(mInjector.mColorSamplingEnabled);
|
||||
|
||||
mInjector.sendScreenChange(/*screen on */ false);
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
|
||||
// Turn screen on while brightness mode is manual
|
||||
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ false);
|
||||
mInjector.sendScreenChange(/*screen on */ true);
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
|
||||
// Set brightness mode to automatic while screen is off.
|
||||
mInjector.sendScreenChange(/*screen on */ false);
|
||||
mInjector.setBrightnessMode(/* isBrightnessModeAutomatic */ true);
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
|
||||
// Turn on screen while brightness mode is automatic.
|
||||
mInjector.sendScreenChange(/*screen on */ true);
|
||||
assertNotNull(mInjector.mSensorListener);
|
||||
assertTrue(mInjector.mColorSamplingEnabled);
|
||||
|
||||
mTracker.stop();
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertNull(mInjector.mBroadcastReceiver);
|
||||
assertFalse(mInjector.mIdleScheduled);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoColorSampling_WrongPixelFormat() {
|
||||
mInjector.mDefaultSamplingAttributes =
|
||||
new DisplayedContentSamplingAttributes(
|
||||
0x23,
|
||||
mInjector.mDefaultSamplingAttributes.getDataspace(),
|
||||
mInjector.mDefaultSamplingAttributes.getComponentMask());
|
||||
startTracker(mTracker);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoColorSampling_MissingComponent() {
|
||||
mInjector.mDefaultSamplingAttributes =
|
||||
new DisplayedContentSamplingAttributes(
|
||||
mInjector.mDefaultSamplingAttributes.getPixelFormat(),
|
||||
mInjector.mDefaultSamplingAttributes.getDataspace(),
|
||||
0x2);
|
||||
startTracker(mTracker);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoColorSampling_NoSupport() {
|
||||
mInjector.mDefaultSamplingAttributes = null;
|
||||
startTracker(mTracker);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColorSampling_FrameRateChange() {
|
||||
startTracker(mTracker);
|
||||
assertTrue(mInjector.mColorSamplingEnabled);
|
||||
assertNotNull(mInjector.mDisplayListener);
|
||||
int noFramesSampled = mInjector.mNoColorSamplingFrames;
|
||||
mInjector.mFrameRate = 120.0f;
|
||||
// Wrong display
|
||||
mInjector.mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY + 10);
|
||||
assertEquals(noFramesSampled, mInjector.mNoColorSamplingFrames);
|
||||
// Correct display
|
||||
mInjector.mDisplayListener.onDisplayChanged(Display.DEFAULT_DISPLAY);
|
||||
assertEquals(noFramesSampled * 2, mInjector.mNoColorSamplingFrames);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -149,26 +206,41 @@ public class BrightnessTrackerTest {
|
||||
assertNotNull(mInjector.mBroadcastReceiver);
|
||||
assertNotNull(mInjector.mContentObserver);
|
||||
assertTrue(mInjector.mIdleScheduled);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
|
||||
mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
|
||||
assertNotNull(mInjector.mSensorListener);
|
||||
assertTrue(mInjector.mColorSamplingEnabled);
|
||||
assertNotNull(mInjector.mDisplayListener);
|
||||
|
||||
SensorEventListener listener = mInjector.mSensorListener;
|
||||
DisplayManager.DisplayListener displayListener = mInjector.mDisplayListener;
|
||||
mInjector.mSensorListener = null;
|
||||
mInjector.mColorSamplingEnabled = false;
|
||||
mInjector.mDisplayListener = null;
|
||||
// Duplicate notification
|
||||
mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ true);
|
||||
// Sensor shouldn't have been registered as it was already registered.
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
mInjector.mSensorListener = listener;
|
||||
mInjector.mDisplayListener = displayListener;
|
||||
mInjector.mColorSamplingEnabled = true;
|
||||
|
||||
mInjector.setBrightnessMode(/*isBrightnessModeAutomatic*/ false);
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
|
||||
mTracker.stop();
|
||||
assertNull(mInjector.mSensorListener);
|
||||
assertNull(mInjector.mBroadcastReceiver);
|
||||
assertNull(mInjector.mContentObserver);
|
||||
assertFalse(mInjector.mIdleScheduled);
|
||||
assertFalse(mInjector.mColorSamplingEnabled);
|
||||
assertNull(mInjector.mDisplayListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -229,6 +301,8 @@ public class BrightnessTrackerTest {
|
||||
assertEquals(3333, event.colorTemperature);
|
||||
assertEquals("a.package", event.packageName);
|
||||
assertEquals(0, event.userId);
|
||||
assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
|
||||
assertEquals(10000, event.colorSampleDuration);
|
||||
|
||||
assertEquals(1, eventsNoPackage.size());
|
||||
assertNull(eventsNoPackage.get(0).packageName);
|
||||
@@ -342,7 +416,8 @@ public class BrightnessTrackerTest {
|
||||
+ "lastNits=\"32\" "
|
||||
+ "batteryLevel=\"0.5\" nightMode=\"true\" colorTemperature=\"3235\"\n"
|
||||
+ "lux=\"132.2,131.1\" luxTimestamps=\""
|
||||
+ Long.toString(someTimeAgo) + "," + Long.toString(someTimeAgo) + "\"/>"
|
||||
+ Long.toString(someTimeAgo) + "," + Long.toString(someTimeAgo) + "\""
|
||||
+ "colorSampleDuration=\"3456\" colorValueBuckets=\"123,598,23,19\"/>"
|
||||
// Event that is too old so shouldn't show up.
|
||||
+ "<event nits=\"142\" timestamp=\""
|
||||
+ Long.toString(twoMonthsAgo) + "\" packageName=\""
|
||||
@@ -368,6 +443,7 @@ public class BrightnessTrackerTest {
|
||||
assertTrue(event.isDefaultBrightnessConfig);
|
||||
assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
|
||||
assertTrue(event.isUserSetBrightness);
|
||||
assertNull(event.colorValueBuckets);
|
||||
|
||||
events = tracker.getEvents(1, true).getList();
|
||||
assertEquals(1, events.size());
|
||||
@@ -386,6 +462,8 @@ public class BrightnessTrackerTest {
|
||||
assertFalse(event.isDefaultBrightnessConfig);
|
||||
assertEquals(1.0, event.powerBrightnessFactor, FLOAT_DELTA);
|
||||
assertFalse(event.isUserSetBrightness);
|
||||
assertEquals(3456L, event.colorSampleDuration);
|
||||
assertArrayEquals(new long[] {123L, 598L, 23L, 19L}, event.colorValueBuckets);
|
||||
|
||||
// Pretend user 1 is a profile of user 0.
|
||||
mInjector.mProfiles = new int[]{0, 1};
|
||||
@@ -481,6 +559,8 @@ public class BrightnessTrackerTest {
|
||||
assertEquals(0.5f, event.powerBrightnessFactor, FLOAT_DELTA);
|
||||
assertTrue(event.isUserSetBrightness);
|
||||
assertFalse(event.isDefaultBrightnessConfig);
|
||||
assertArrayEquals(new long[] {1, 10, 100, 1000, 300, 30, 10, 1}, event.colorValueBuckets);
|
||||
assertEquals(10000, event.colorSampleDuration);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -546,6 +626,7 @@ public class BrightnessTrackerTest {
|
||||
builder.setNightMode(false);
|
||||
builder.setColorTemperature(345);
|
||||
builder.setLastBrightness(50f);
|
||||
builder.setColorValues(new long[] {23, 34, 45}, 1000L);
|
||||
BrightnessChangeEvent event = builder.build();
|
||||
|
||||
event.writeToParcel(parcel, 0);
|
||||
@@ -568,6 +649,8 @@ public class BrightnessTrackerTest {
|
||||
assertEquals(event.nightMode, event2.nightMode);
|
||||
assertEquals(event.colorTemperature, event2.colorTemperature);
|
||||
assertEquals(event.lastBrightness, event2.lastBrightness, FLOAT_DELTA);
|
||||
assertArrayEquals(event.colorValueBuckets, event2.colorValueBuckets);
|
||||
assertEquals(event.colorSampleDuration, event2.colorSampleDuration);
|
||||
|
||||
parcel = Parcel.obtain();
|
||||
builder.setBatteryLevel(Float.NaN);
|
||||
@@ -714,6 +797,7 @@ public class BrightnessTrackerTest {
|
||||
private class TestInjector extends BrightnessTracker.Injector {
|
||||
SensorEventListener mSensorListener;
|
||||
BroadcastReceiver mBroadcastReceiver;
|
||||
DisplayManager.DisplayListener mDisplayListener;
|
||||
Map<String, Integer> mSecureIntSettings = new HashMap<>();
|
||||
long mCurrentTimeMillis = System.currentTimeMillis();
|
||||
long mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
|
||||
@@ -723,6 +807,12 @@ public class BrightnessTrackerTest {
|
||||
int[] mProfiles;
|
||||
ContentObserver mContentObserver;
|
||||
boolean mIsBrightnessModeAutomatic = true;
|
||||
boolean mColorSamplingEnabled = false;
|
||||
DisplayedContentSamplingAttributes mDefaultSamplingAttributes =
|
||||
new DisplayedContentSamplingAttributes(0x37, 0, 0x4);
|
||||
float mFrameRate = 60.0f;
|
||||
int mNoColorSamplingFrames;
|
||||
|
||||
|
||||
public TestInjector(Handler handler) {
|
||||
mHandler = handler;
|
||||
@@ -882,5 +972,43 @@ public class BrightnessTrackerTest {
|
||||
return mSecureIntSettings.getOrDefault(Settings.Secure.NIGHT_DISPLAY_ACTIVATED,
|
||||
0) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayedContentSample sampleColor(int noFramesToSample) {
|
||||
return new DisplayedContentSample(600L,
|
||||
null,
|
||||
null,
|
||||
new long[] {1, 10, 100, 1000, 300, 30, 10, 1},
|
||||
null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFrameRate(Context context) {
|
||||
return mFrameRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisplayedContentSamplingAttributes getSamplingAttributes() {
|
||||
return mDefaultSamplingAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean enableColorSampling(boolean enable, int noFrames) {
|
||||
mColorSamplingEnabled = enable;
|
||||
mNoColorSamplingFrames = noFrames;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDisplayListener(Context context,
|
||||
DisplayManager.DisplayListener listener, Handler handler) {
|
||||
mDisplayListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unRegisterDisplayListener(Context context,
|
||||
DisplayManager.DisplayListener listener) {
|
||||
mDisplayListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user