Merge changes from topic "r3_flicker_high_brightness" into rvc-qpr-dev
* changes: Allow DeviceConfig to change display settings for high zone Set fixed fps when ambient or display brightness is high Add FakeSettingsProviderRule class
This commit is contained in:
committed by
Android (Google) Code Review
commit
11bee77de6
@@ -875,12 +875,52 @@ public final class DisplayManager {
|
|||||||
public interface DeviceConfig {
|
public interface DeviceConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key for refresh rate in the zone defined by thresholds.
|
* Key for refresh rate in the low zone defined by thresholds.
|
||||||
*
|
*
|
||||||
|
* Note that the name and value don't match because they were added before we had a high
|
||||||
|
* zone to consider.
|
||||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||||
* @see android.R.integer#config_defaultZoneBehavior
|
* @see android.R.integer#config_defaultZoneBehavior
|
||||||
*/
|
*/
|
||||||
String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";
|
String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key for accessing the low display brightness thresholds for the configured refresh
|
||||||
|
* rate zone.
|
||||||
|
* The value will be a pair of comma separated integers representing the minimum and maximum
|
||||||
|
* thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
|
||||||
|
*
|
||||||
|
* Note that the name and value don't match because they were added before we had a high
|
||||||
|
* zone to consider.
|
||||||
|
*
|
||||||
|
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||||
|
* @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS =
|
||||||
|
"peak_refresh_rate_brightness_thresholds";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key for accessing the low ambient brightness thresholds for the configured refresh
|
||||||
|
* rate zone. The value will be a pair of comma separated integers representing the minimum
|
||||||
|
* and maximum thresholds of the zone, respectively, in lux.
|
||||||
|
*
|
||||||
|
* Note that the name and value don't match because they were added before we had a high
|
||||||
|
* zone to consider.
|
||||||
|
*
|
||||||
|
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||||
|
* @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||||
|
"peak_refresh_rate_ambient_thresholds";
|
||||||
|
/**
|
||||||
|
* Key for refresh rate in the high zone defined by thresholds.
|
||||||
|
*
|
||||||
|
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||||
|
* @see android.R.integer#config_fixedRefreshRateInHighZone
|
||||||
|
*/
|
||||||
|
String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key for accessing the display brightness thresholds for the configured refresh rate zone.
|
* Key for accessing the display brightness thresholds for the configured refresh rate zone.
|
||||||
@@ -888,11 +928,11 @@ public final class DisplayManager {
|
|||||||
* thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
|
* thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
|
||||||
*
|
*
|
||||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||||
* @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
|
* @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
|
String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS =
|
||||||
"peak_refresh_rate_brightness_thresholds";
|
"fixed_refresh_rate_high_display_brightness_thresholds";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
|
* Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
|
||||||
@@ -900,12 +940,11 @@ public final class DisplayManager {
|
|||||||
* thresholds of the zone, respectively, in lux.
|
* thresholds of the zone, respectively, in lux.
|
||||||
*
|
*
|
||||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||||
* @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
|
* @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||||
"peak_refresh_rate_ambient_thresholds";
|
"fixed_refresh_rate_high_ambient_brightness_thresholds";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Key for default peak refresh rate
|
* Key for default peak refresh rate
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4138,6 +4138,35 @@
|
|||||||
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
||||||
<integer name="config_defaultRefreshRateInZone">0</integer>
|
<integer name="config_defaultRefreshRateInZone">0</integer>
|
||||||
|
|
||||||
|
<!-- The display uses different gamma curves for different refresh rates. It's hard for panel
|
||||||
|
vendor to tune the curves to have exact same brightness for different refresh rate. So
|
||||||
|
flicker could be observed at switch time. The issue can be observed on the screen with
|
||||||
|
even full white content at the high brightness. To prevent flickering, we support fixed
|
||||||
|
refresh rates if the display and ambient brightness are equal to or above the provided
|
||||||
|
thresholds. You can define multiple threshold levels as higher brightness environments
|
||||||
|
may have lower display brightness requirements for the flickering is visible. And the
|
||||||
|
high brightness environment could have higher threshold.
|
||||||
|
For example, fixed refresh rate if
|
||||||
|
display brightness >= disp0 && ambient brightness >= amb0
|
||||||
|
|| display brightness >= disp1 && ambient brightness >= amb1 -->
|
||||||
|
<integer-array translatable="false" name="config_highDisplayBrightnessThresholdsOfFixedRefreshRate">
|
||||||
|
<!--
|
||||||
|
<item>disp0</item>
|
||||||
|
<item>disp1</item>
|
||||||
|
-->
|
||||||
|
</integer-array>
|
||||||
|
|
||||||
|
<integer-array translatable="false" name="config_highAmbientBrightnessThresholdsOfFixedRefreshRate">
|
||||||
|
<!--
|
||||||
|
<item>amb0</item>
|
||||||
|
<item>amb1</item>
|
||||||
|
-->
|
||||||
|
</integer-array>
|
||||||
|
|
||||||
|
<!-- Default refresh rate in the high zone defined by brightness and ambient thresholds.
|
||||||
|
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
||||||
|
<integer name="config_fixedRefreshRateInHighZone">0</integer>
|
||||||
|
|
||||||
<!-- The type of the light sensor to be used by the display framework for things like
|
<!-- The type of the light sensor to be used by the display framework for things like
|
||||||
auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
|
auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
|
||||||
<string name="config_displayLightSensorType" translatable="false" />
|
<string name="config_displayLightSensorType" translatable="false" />
|
||||||
|
|||||||
@@ -3783,6 +3783,11 @@
|
|||||||
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
|
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
|
||||||
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
|
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
|
||||||
|
|
||||||
|
<!-- For fixed refresh rate displays in high brightness-->
|
||||||
|
<java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
|
||||||
|
<java-symbol type="array" name="config_highDisplayBrightnessThresholdsOfFixedRefreshRate" />
|
||||||
|
<java-symbol type="array" name="config_highAmbientBrightnessThresholdsOfFixedRefreshRate" />
|
||||||
|
|
||||||
<!-- For Auto-Brightness -->
|
<!-- For Auto-Brightness -->
|
||||||
<java-symbol type="string" name="config_displayLightSensorType" />
|
<java-symbol type="string" name="config_displayLightSensorType" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
filegroup {
|
||||||
|
name: "services.core-sources-deviceconfig-interface",
|
||||||
|
srcs: [
|
||||||
|
"java/com/android/server/utils/DeviceConfigInterface.java"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
filegroup {
|
filegroup {
|
||||||
name: "services.core-sources",
|
name: "services.core-sources",
|
||||||
srcs: ["java/**/*.java"],
|
srcs: ["java/**/*.java"],
|
||||||
|
|||||||
@@ -46,8 +46,10 @@ import android.view.DisplayInfo;
|
|||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.os.BackgroundThread;
|
import com.android.internal.os.BackgroundThread;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.server.display.utils.AmbientFilter;
|
import com.android.server.display.utils.AmbientFilter;
|
||||||
import com.android.server.display.utils.AmbientFilterFactory;
|
import com.android.server.display.utils.AmbientFilterFactory;
|
||||||
|
import com.android.server.utils.DeviceConfigInterface;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -64,9 +66,11 @@ public class DisplayModeDirector {
|
|||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private static final int MSG_REFRESH_RATE_RANGE_CHANGED = 1;
|
private static final int MSG_REFRESH_RATE_RANGE_CHANGED = 1;
|
||||||
private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
|
private static final int MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
|
||||||
private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
|
private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
|
||||||
private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;
|
private static final int MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED = 4;
|
||||||
|
private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5;
|
||||||
|
private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6;
|
||||||
|
|
||||||
// Special ID used to indicate that given vote is to be applied globally, rather than to a
|
// Special ID used to indicate that given vote is to be applied globally, rather than to a
|
||||||
// specific display.
|
// specific display.
|
||||||
@@ -79,6 +83,13 @@ public class DisplayModeDirector {
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
private final DisplayModeDirectorHandler mHandler;
|
private final DisplayModeDirectorHandler mHandler;
|
||||||
|
private final Injector mInjector;
|
||||||
|
|
||||||
|
private final AppRequestObserver mAppRequestObserver;
|
||||||
|
private final SettingsObserver mSettingsObserver;
|
||||||
|
private final DisplayObserver mDisplayObserver;
|
||||||
|
private final DeviceConfigInterface mDeviceConfig;
|
||||||
|
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
||||||
|
|
||||||
// A map from the display ID to the collection of votes and their priority. The latter takes
|
// A map from the display ID to the collection of votes and their priority. The latter takes
|
||||||
// the form of another map from the priority to the vote itself so that each priority is
|
// the form of another map from the priority to the vote itself so that each priority is
|
||||||
@@ -89,17 +100,19 @@ public class DisplayModeDirector {
|
|||||||
// A map from the display ID to the default mode of that display.
|
// A map from the display ID to the default mode of that display.
|
||||||
private SparseArray<Display.Mode> mDefaultModeByDisplay;
|
private SparseArray<Display.Mode> mDefaultModeByDisplay;
|
||||||
|
|
||||||
private final AppRequestObserver mAppRequestObserver;
|
|
||||||
private final SettingsObserver mSettingsObserver;
|
|
||||||
private final DisplayObserver mDisplayObserver;
|
|
||||||
private BrightnessObserver mBrightnessObserver;
|
private BrightnessObserver mBrightnessObserver;
|
||||||
|
|
||||||
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
|
||||||
private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
|
private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
|
||||||
|
|
||||||
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
|
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
|
||||||
|
this(context, handler, new RealInjector());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
|
||||||
|
@NonNull Injector injector) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mHandler = new DisplayModeDirectorHandler(handler.getLooper());
|
mHandler = new DisplayModeDirectorHandler(handler.getLooper());
|
||||||
|
mInjector = injector;
|
||||||
mVotesByDisplay = new SparseArray<>();
|
mVotesByDisplay = new SparseArray<>();
|
||||||
mSupportedModesByDisplay = new SparseArray<>();
|
mSupportedModesByDisplay = new SparseArray<>();
|
||||||
mDefaultModeByDisplay = new SparseArray<>();
|
mDefaultModeByDisplay = new SparseArray<>();
|
||||||
@@ -108,6 +121,7 @@ public class DisplayModeDirector {
|
|||||||
mDisplayObserver = new DisplayObserver(context, handler);
|
mDisplayObserver = new DisplayObserver(context, handler);
|
||||||
mBrightnessObserver = new BrightnessObserver(context, handler);
|
mBrightnessObserver = new BrightnessObserver(context, handler);
|
||||||
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
|
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
|
||||||
|
mDeviceConfig = injector.getDeviceConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -348,6 +362,23 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the Vote for the given display and priority. Intended only for testing purposes.
|
||||||
|
*
|
||||||
|
* @param displayId the display to query for
|
||||||
|
* @param priority the priority of the vote to return
|
||||||
|
* @return the vote corresponding to the given {@code displayId} and {@code priority},
|
||||||
|
* or {@code null} if there isn't one
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
@Nullable
|
||||||
|
Vote getVote(int displayId, int priority) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
SparseArray<Vote> votes = getVotesLocked(displayId);
|
||||||
|
return votes.get(priority);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Print the object's state and debug information into the given stream.
|
* Print the object's state and debug information into the given stream.
|
||||||
*
|
*
|
||||||
@@ -465,6 +496,17 @@ public class DisplayModeDirector {
|
|||||||
mBrightnessObserver = brightnessObserver;
|
mBrightnessObserver = brightnessObserver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
BrightnessObserver getBrightnessObserver() {
|
||||||
|
return mBrightnessObserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
SettingsObserver getSettingsObserver() {
|
||||||
|
return mSettingsObserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
|
DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
|
||||||
float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
|
float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
|
||||||
@@ -493,16 +535,35 @@ public class DisplayModeDirector {
|
|||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case MSG_BRIGHTNESS_THRESHOLDS_CHANGED:
|
case MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED: {
|
||||||
|
Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
|
||||||
|
mBrightnessObserver.onDeviceConfigLowBrightnessThresholdsChanged(
|
||||||
|
thresholds.first, thresholds.second);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED: {
|
||||||
|
int refreshRateInZone = msg.arg1;
|
||||||
|
mBrightnessObserver.onDeviceConfigRefreshRateInLowZoneChanged(
|
||||||
|
refreshRateInZone);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED: {
|
||||||
Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
|
Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
|
||||||
|
|
||||||
if (thresholds != null) {
|
mBrightnessObserver.onDeviceConfigHighBrightnessThresholdsChanged(
|
||||||
mBrightnessObserver.onDeviceConfigThresholdsChanged(
|
thresholds.first, thresholds.second);
|
||||||
thresholds.first, thresholds.second);
|
|
||||||
} else {
|
|
||||||
mBrightnessObserver.onDeviceConfigThresholdsChanged(null, null);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED: {
|
||||||
|
int refreshRateInZone = msg.arg1;
|
||||||
|
mBrightnessObserver.onDeviceConfigRefreshRateInHighZoneChanged(
|
||||||
|
refreshRateInZone);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED:
|
case MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED:
|
||||||
Float defaultPeakRefreshRate = (Float) msg.obj;
|
Float defaultPeakRefreshRate = (Float) msg.obj;
|
||||||
@@ -510,12 +571,6 @@ public class DisplayModeDirector {
|
|||||||
defaultPeakRefreshRate);
|
defaultPeakRefreshRate);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_REFRESH_RATE_IN_ZONE_CHANGED:
|
|
||||||
int refreshRateInZone = msg.arg1;
|
|
||||||
mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
|
|
||||||
refreshRateInZone);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MSG_REFRESH_RATE_RANGE_CHANGED:
|
case MSG_REFRESH_RATE_RANGE_CHANGED:
|
||||||
DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener =
|
DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener =
|
||||||
(DesiredDisplayModeSpecsListener) msg.obj;
|
(DesiredDisplayModeSpecsListener) msg.obj;
|
||||||
@@ -685,10 +740,11 @@ public class DisplayModeDirector {
|
|||||||
// by all other considerations. It acts to set a default frame rate for a device.
|
// by all other considerations. It acts to set a default frame rate for a device.
|
||||||
public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;
|
public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;
|
||||||
|
|
||||||
// LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null.
|
// FLICKER votes for a single refresh rate like [60,60], [90,90] or null.
|
||||||
// If the higher voters result is a range, it will fix the rate to a single choice.
|
// If the higher voters result is a range, it will fix the rate to a single choice.
|
||||||
// It's used to avoid rate switch in certain conditions.
|
// It's used to avoid refresh rate switches in certain conditions which may result in the
|
||||||
public static final int PRIORITY_LOW_BRIGHTNESS = 1;
|
// user seeing the display flickering when the switches occur.
|
||||||
|
public static final int PRIORITY_FLICKER = 1;
|
||||||
|
|
||||||
// SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
|
// SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
|
||||||
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
|
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
|
||||||
@@ -761,8 +817,8 @@ public class DisplayModeDirector {
|
|||||||
switch (priority) {
|
switch (priority) {
|
||||||
case PRIORITY_DEFAULT_REFRESH_RATE:
|
case PRIORITY_DEFAULT_REFRESH_RATE:
|
||||||
return "PRIORITY_DEFAULT_REFRESH_RATE";
|
return "PRIORITY_DEFAULT_REFRESH_RATE";
|
||||||
case PRIORITY_LOW_BRIGHTNESS:
|
case PRIORITY_FLICKER:
|
||||||
return "PRIORITY_LOW_BRIGHTNESS";
|
return "PRIORITY_FLICKER";
|
||||||
case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
|
case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
|
||||||
return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
|
return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
|
||||||
case PRIORITY_APP_REQUEST_REFRESH_RATE:
|
case PRIORITY_APP_REQUEST_REFRESH_RATE:
|
||||||
@@ -787,7 +843,8 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class SettingsObserver extends ContentObserver {
|
@VisibleForTesting
|
||||||
|
final class SettingsObserver extends ContentObserver {
|
||||||
private final Uri mPeakRefreshRateSetting =
|
private final Uri mPeakRefreshRateSetting =
|
||||||
Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
|
Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
|
||||||
private final Uri mMinRefreshRateSetting =
|
private final Uri mMinRefreshRateSetting =
|
||||||
@@ -810,8 +867,7 @@ public class DisplayModeDirector {
|
|||||||
|
|
||||||
public void observe() {
|
public void observe() {
|
||||||
final ContentResolver cr = mContext.getContentResolver();
|
final ContentResolver cr = mContext.getContentResolver();
|
||||||
cr.registerContentObserver(mPeakRefreshRateSetting, false /*notifyDescendants*/, this,
|
mInjector.registerPeakRefreshRateObserver(cr, this);
|
||||||
UserHandle.USER_SYSTEM);
|
|
||||||
cr.registerContentObserver(mMinRefreshRateSetting, false /*notifyDescendants*/, this,
|
cr.registerContentObserver(mMinRefreshRateSetting, false /*notifyDescendants*/, this,
|
||||||
UserHandle.USER_SYSTEM);
|
UserHandle.USER_SYSTEM);
|
||||||
cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
|
cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this,
|
||||||
@@ -829,6 +885,13 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDefaultRefreshRate(float refreshRate) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mDefaultRefreshRate = refreshRate;
|
||||||
|
updateRefreshRateSettingLocked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate) {
|
public void onDeviceConfigDefaultPeakRefreshRateChanged(Float defaultPeakRefreshRate) {
|
||||||
if (defaultPeakRefreshRate == null) {
|
if (defaultPeakRefreshRate == null) {
|
||||||
defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
|
defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
|
||||||
@@ -1033,6 +1096,7 @@ public class DisplayModeDirector {
|
|||||||
@Override
|
@Override
|
||||||
public void onDisplayChanged(int displayId) {
|
public void onDisplayChanged(int displayId) {
|
||||||
updateDisplayModes(displayId);
|
updateDisplayModes(displayId);
|
||||||
|
// TODO: Break the coupling between DisplayObserver and BrightnessObserver.
|
||||||
mBrightnessObserver.onDisplayChanged(displayId);
|
mBrightnessObserver.onDisplayChanged(displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1071,15 +1135,16 @@ public class DisplayModeDirector {
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public class BrightnessObserver extends ContentObserver {
|
public class BrightnessObserver extends ContentObserver {
|
||||||
// TODO: brightnessfloat: change this to the float setting
|
|
||||||
private final Uri mDisplayBrightnessSetting =
|
|
||||||
Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
|
|
||||||
private final static int LIGHT_SENSOR_RATE_MS = 250;
|
private final static int LIGHT_SENSOR_RATE_MS = 250;
|
||||||
private int[] mDisplayBrightnessThresholds;
|
private int[] mLowDisplayBrightnessThresholds;
|
||||||
private int[] mAmbientBrightnessThresholds;
|
private int[] mLowAmbientBrightnessThresholds;
|
||||||
|
private int[] mHighDisplayBrightnessThresholds;
|
||||||
|
private int[] mHighAmbientBrightnessThresholds;
|
||||||
// valid threshold if any item from the array >= 0
|
// valid threshold if any item from the array >= 0
|
||||||
private boolean mShouldObserveDisplayChange;
|
private boolean mShouldObserveDisplayLowChange;
|
||||||
private boolean mShouldObserveAmbientChange;
|
private boolean mShouldObserveAmbientLowChange;
|
||||||
|
private boolean mShouldObserveDisplayHighChange;
|
||||||
|
private boolean mShouldObserveAmbientHighChange;
|
||||||
|
|
||||||
private SensorManager mSensorManager;
|
private SensorManager mSensorManager;
|
||||||
private Sensor mLightSensor;
|
private Sensor mLightSensor;
|
||||||
@@ -1087,46 +1152,122 @@ public class DisplayModeDirector {
|
|||||||
// Take it as low brightness before valid sensor data comes
|
// Take it as low brightness before valid sensor data comes
|
||||||
private float mAmbientLux = -1.0f;
|
private float mAmbientLux = -1.0f;
|
||||||
private AmbientFilter mAmbientFilter;
|
private AmbientFilter mAmbientFilter;
|
||||||
|
private int mBrightness = -1;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
// Enable light sensor only when mShouldObserveAmbientChange is true, screen is on, peak
|
// Enable light sensor only when mShouldObserveAmbientLowChange is true or
|
||||||
// refresh rate changeable and low power mode off. After initialization, these states will
|
// mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate
|
||||||
|
// changeable and low power mode off. After initialization, these states will
|
||||||
// be updated from the same handler thread.
|
// be updated from the same handler thread.
|
||||||
private boolean mScreenOn = false;
|
private boolean mDefaultDisplayOn = false;
|
||||||
private boolean mRefreshRateChangeable = false;
|
private boolean mRefreshRateChangeable = false;
|
||||||
private boolean mLowPowerModeEnabled = false;
|
private boolean mLowPowerModeEnabled = false;
|
||||||
|
|
||||||
private int mRefreshRateInZone;
|
private int mRefreshRateInLowZone;
|
||||||
|
private int mRefreshRateInHighZone;
|
||||||
|
|
||||||
BrightnessObserver(Context context, Handler handler) {
|
BrightnessObserver(Context context, Handler handler) {
|
||||||
super(handler);
|
super(handler);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mDisplayBrightnessThresholds = context.getResources().getIntArray(
|
mLowDisplayBrightnessThresholds = context.getResources().getIntArray(
|
||||||
R.array.config_brightnessThresholdsOfPeakRefreshRate);
|
R.array.config_brightnessThresholdsOfPeakRefreshRate);
|
||||||
mAmbientBrightnessThresholds = context.getResources().getIntArray(
|
mLowAmbientBrightnessThresholds = context.getResources().getIntArray(
|
||||||
R.array.config_ambientThresholdsOfPeakRefreshRate);
|
R.array.config_ambientThresholdsOfPeakRefreshRate);
|
||||||
|
|
||||||
if (mDisplayBrightnessThresholds.length != mAmbientBrightnessThresholds.length) {
|
if (mLowDisplayBrightnessThresholds.length != mLowAmbientBrightnessThresholds.length) {
|
||||||
throw new RuntimeException("display brightness threshold array and ambient "
|
throw new RuntimeException("display low brightness threshold array and ambient "
|
||||||
+ "brightness threshold array have different length");
|
+ "brightness threshold array have different length: "
|
||||||
|
+ "displayBrightnessThresholds="
|
||||||
|
+ Arrays.toString(mLowDisplayBrightnessThresholds)
|
||||||
|
+ ", ambientBrightnessThresholds="
|
||||||
|
+ Arrays.toString(mLowAmbientBrightnessThresholds));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mHighDisplayBrightnessThresholds = context.getResources().getIntArray(
|
||||||
|
R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate);
|
||||||
|
mHighAmbientBrightnessThresholds = context.getResources().getIntArray(
|
||||||
|
R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate);
|
||||||
|
if (mHighDisplayBrightnessThresholds.length
|
||||||
|
!= mHighAmbientBrightnessThresholds.length) {
|
||||||
|
throw new RuntimeException("display high brightness threshold array and ambient "
|
||||||
|
+ "brightness threshold array have different length: "
|
||||||
|
+ "displayBrightnessThresholds="
|
||||||
|
+ Arrays.toString(mHighDisplayBrightnessThresholds)
|
||||||
|
+ ", ambientBrightnessThresholds="
|
||||||
|
+ Arrays.toString(mHighAmbientBrightnessThresholds));
|
||||||
|
}
|
||||||
|
mRefreshRateInHighZone = context.getResources().getInteger(
|
||||||
|
R.integer.config_fixedRefreshRateInHighZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the refresh to lock to when in a low brightness zone
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
int getRefreshRateInLowZone() {
|
||||||
|
return mRefreshRateInLowZone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the display brightness thresholds for the low brightness zones
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
int[] getLowDisplayBrightnessThresholds() {
|
||||||
|
return mLowDisplayBrightnessThresholds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the ambient brightness thresholds for the low brightness zones
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
int[] getLowAmbientBrightnessThresholds() {
|
||||||
|
return mLowAmbientBrightnessThresholds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerLightSensor(SensorManager sensorManager, Sensor lightSensor) {
|
||||||
|
mSensorManager = sensorManager;
|
||||||
|
mLightSensor = lightSensor;
|
||||||
|
|
||||||
|
mSensorManager.registerListener(mLightSensorListener,
|
||||||
|
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void observe(SensorManager sensorManager) {
|
public void observe(SensorManager sensorManager) {
|
||||||
mSensorManager = sensorManager;
|
mSensorManager = sensorManager;
|
||||||
|
final ContentResolver cr = mContext.getContentResolver();
|
||||||
|
mBrightness = Settings.System.getIntForUser(cr,
|
||||||
|
Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
|
||||||
|
|
||||||
// DeviceConfig is accessible after system ready.
|
// DeviceConfig is accessible after system ready.
|
||||||
int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
|
int[] lowDisplayBrightnessThresholds =
|
||||||
int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
|
mDeviceConfigDisplaySettings.getLowDisplayBrightnessThresholds();
|
||||||
|
int[] lowAmbientBrightnessThresholds =
|
||||||
|
mDeviceConfigDisplaySettings.getLowAmbientBrightnessThresholds();
|
||||||
|
|
||||||
if (brightnessThresholds != null && ambientThresholds != null
|
if (lowDisplayBrightnessThresholds != null && lowAmbientBrightnessThresholds != null
|
||||||
&& brightnessThresholds.length == ambientThresholds.length) {
|
&& lowDisplayBrightnessThresholds.length
|
||||||
mDisplayBrightnessThresholds = brightnessThresholds;
|
== lowAmbientBrightnessThresholds.length) {
|
||||||
mAmbientBrightnessThresholds = ambientThresholds;
|
mLowDisplayBrightnessThresholds = lowDisplayBrightnessThresholds;
|
||||||
|
mLowAmbientBrightnessThresholds = lowAmbientBrightnessThresholds;
|
||||||
}
|
}
|
||||||
|
|
||||||
mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone();
|
|
||||||
|
int[] highDisplayBrightnessThresholds =
|
||||||
|
mDeviceConfigDisplaySettings.getHighDisplayBrightnessThresholds();
|
||||||
|
int[] highAmbientBrightnessThresholds =
|
||||||
|
mDeviceConfigDisplaySettings.getHighAmbientBrightnessThresholds();
|
||||||
|
|
||||||
|
if (highDisplayBrightnessThresholds != null && highAmbientBrightnessThresholds != null
|
||||||
|
&& highDisplayBrightnessThresholds.length
|
||||||
|
== highAmbientBrightnessThresholds.length) {
|
||||||
|
mHighDisplayBrightnessThresholds = highDisplayBrightnessThresholds;
|
||||||
|
mHighAmbientBrightnessThresholds = highAmbientBrightnessThresholds;
|
||||||
|
}
|
||||||
|
|
||||||
|
mRefreshRateInLowZone = mDeviceConfigDisplaySettings.getRefreshRateInLowZone();
|
||||||
|
mRefreshRateInHighZone = mDeviceConfigDisplaySettings.getRefreshRateInHighZone();
|
||||||
|
|
||||||
restartObserver();
|
restartObserver();
|
||||||
mDeviceConfigDisplaySettings.startListening();
|
mDeviceConfigDisplaySettings.startListening();
|
||||||
}
|
}
|
||||||
@@ -1138,7 +1279,7 @@ public class DisplayModeDirector {
|
|||||||
updateSensorStatus();
|
updateSensorStatus();
|
||||||
if (!changeable) {
|
if (!changeable) {
|
||||||
// Revoke previous vote from BrightnessObserver
|
// Revoke previous vote from BrightnessObserver
|
||||||
updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, null);
|
updateVoteLocked(Vote.PRIORITY_FLICKER, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1150,25 +1291,48 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDeviceConfigThresholdsChanged(int[] brightnessThresholds,
|
public void onDeviceConfigLowBrightnessThresholdsChanged(int[] displayThresholds,
|
||||||
int[] ambientThresholds) {
|
int[] ambientThresholds) {
|
||||||
if (brightnessThresholds != null && ambientThresholds != null
|
if (displayThresholds != null && ambientThresholds != null
|
||||||
&& brightnessThresholds.length == ambientThresholds.length) {
|
&& displayThresholds.length == ambientThresholds.length) {
|
||||||
mDisplayBrightnessThresholds = brightnessThresholds;
|
mLowDisplayBrightnessThresholds = displayThresholds;
|
||||||
mAmbientBrightnessThresholds = ambientThresholds;
|
mLowAmbientBrightnessThresholds = ambientThresholds;
|
||||||
} else {
|
} else {
|
||||||
// Invalid or empty. Use device default.
|
// Invalid or empty. Use device default.
|
||||||
mDisplayBrightnessThresholds = mContext.getResources().getIntArray(
|
mLowDisplayBrightnessThresholds = mContext.getResources().getIntArray(
|
||||||
R.array.config_brightnessThresholdsOfPeakRefreshRate);
|
R.array.config_brightnessThresholdsOfPeakRefreshRate);
|
||||||
mAmbientBrightnessThresholds = mContext.getResources().getIntArray(
|
mLowAmbientBrightnessThresholds = mContext.getResources().getIntArray(
|
||||||
R.array.config_ambientThresholdsOfPeakRefreshRate);
|
R.array.config_ambientThresholdsOfPeakRefreshRate);
|
||||||
}
|
}
|
||||||
restartObserver();
|
restartObserver();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDeviceConfigRefreshRateInZoneChanged(int refreshRate) {
|
public void onDeviceConfigRefreshRateInLowZoneChanged(int refreshRate) {
|
||||||
if (refreshRate != mRefreshRateInZone) {
|
if (refreshRate != mRefreshRateInLowZone) {
|
||||||
mRefreshRateInZone = refreshRate;
|
mRefreshRateInLowZone = refreshRate;
|
||||||
|
restartObserver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDeviceConfigHighBrightnessThresholdsChanged(int[] displayThresholds,
|
||||||
|
int[] ambientThresholds) {
|
||||||
|
if (displayThresholds != null && ambientThresholds != null
|
||||||
|
&& displayThresholds.length == ambientThresholds.length) {
|
||||||
|
mHighDisplayBrightnessThresholds = displayThresholds;
|
||||||
|
mHighAmbientBrightnessThresholds = ambientThresholds;
|
||||||
|
} else {
|
||||||
|
// Invalid or empty. Use device default.
|
||||||
|
mHighDisplayBrightnessThresholds = mContext.getResources().getIntArray(
|
||||||
|
R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate);
|
||||||
|
mHighAmbientBrightnessThresholds = mContext.getResources().getIntArray(
|
||||||
|
R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate);
|
||||||
|
}
|
||||||
|
restartObserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDeviceConfigRefreshRateInHighZoneChanged(int refreshRate) {
|
||||||
|
if (refreshRate != mRefreshRateInHighZone) {
|
||||||
|
mRefreshRateInHighZone = refreshRate;
|
||||||
restartObserver();
|
restartObserver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1176,48 +1340,95 @@ public class DisplayModeDirector {
|
|||||||
public void dumpLocked(PrintWriter pw) {
|
public void dumpLocked(PrintWriter pw) {
|
||||||
pw.println(" BrightnessObserver");
|
pw.println(" BrightnessObserver");
|
||||||
pw.println(" mAmbientLux: " + mAmbientLux);
|
pw.println(" mAmbientLux: " + mAmbientLux);
|
||||||
pw.println(" mRefreshRateInZone: " + mRefreshRateInZone);
|
pw.println(" mBrightness: " + mBrightness);
|
||||||
|
pw.println(" mDefaultDisplayOn: " + mDefaultDisplayOn);
|
||||||
|
pw.println(" mLowPowerModeEnabled: " + mLowPowerModeEnabled);
|
||||||
|
pw.println(" mRefreshRateChangeable: " + mRefreshRateChangeable);
|
||||||
|
pw.println(" mShouldObserveDisplayLowChange: " + mShouldObserveDisplayLowChange);
|
||||||
|
pw.println(" mShouldObserveAmbientLowChange: " + mShouldObserveAmbientLowChange);
|
||||||
|
pw.println(" mRefreshRateInLowZone: " + mRefreshRateInLowZone);
|
||||||
|
|
||||||
for (int d: mDisplayBrightnessThresholds) {
|
for (int d : mLowDisplayBrightnessThresholds) {
|
||||||
pw.println(" mDisplayBrightnessThreshold: " + d);
|
pw.println(" mDisplayLowBrightnessThreshold: " + d);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int d: mAmbientBrightnessThresholds) {
|
for (int d : mLowAmbientBrightnessThresholds) {
|
||||||
pw.println(" mAmbientBrightnessThreshold: " + d);
|
pw.println(" mAmbientLowBrightnessThreshold: " + d);
|
||||||
|
}
|
||||||
|
|
||||||
|
pw.println(" mShouldObserveDisplayHighChange: " + mShouldObserveDisplayHighChange);
|
||||||
|
pw.println(" mShouldObserveAmbientHighChange: " + mShouldObserveAmbientHighChange);
|
||||||
|
pw.println(" mRefreshRateInHighZone: " + mRefreshRateInHighZone);
|
||||||
|
|
||||||
|
for (int d : mHighDisplayBrightnessThresholds) {
|
||||||
|
pw.println(" mDisplayHighBrightnessThresholds: " + d);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int d : mHighAmbientBrightnessThresholds) {
|
||||||
|
pw.println(" mAmbientHighBrightnessThresholds: " + d);
|
||||||
}
|
}
|
||||||
|
|
||||||
mLightSensorListener.dumpLocked(pw);
|
mLightSensorListener.dumpLocked(pw);
|
||||||
|
|
||||||
|
if (mAmbientFilter != null) {
|
||||||
|
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
|
||||||
|
ipw.setIndent(" ");
|
||||||
|
mAmbientFilter.dump(ipw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDisplayChanged(int displayId) {
|
public void onDisplayChanged(int displayId) {
|
||||||
if (displayId == Display.DEFAULT_DISPLAY) {
|
if (displayId == Display.DEFAULT_DISPLAY) {
|
||||||
onScreenOn(isDefaultDisplayOn());
|
updateDefaultDisplayState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onChange(boolean selfChange, Uri uri, int userId) {
|
public void onChange(boolean selfChange, Uri uri, int userId) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
onBrightnessChangedLocked();
|
final ContentResolver cr = mContext.getContentResolver();
|
||||||
|
int brightness = Settings.System.getIntForUser(cr,
|
||||||
|
Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
|
||||||
|
if (brightness != mBrightness) {
|
||||||
|
mBrightness = brightness;
|
||||||
|
onBrightnessChangedLocked();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restartObserver() {
|
private void restartObserver() {
|
||||||
mShouldObserveDisplayChange = checkShouldObserve(mDisplayBrightnessThresholds);
|
|
||||||
mShouldObserveAmbientChange = checkShouldObserve(mAmbientBrightnessThresholds);
|
|
||||||
|
|
||||||
final ContentResolver cr = mContext.getContentResolver();
|
final ContentResolver cr = mContext.getContentResolver();
|
||||||
if (mShouldObserveDisplayChange) {
|
|
||||||
// Content Service does not check if an listener has already been registered.
|
if (mRefreshRateInLowZone > 0) {
|
||||||
// To ensure only one listener is registered, force an unregistration first.
|
mShouldObserveDisplayLowChange = hasValidThreshold(
|
||||||
cr.unregisterContentObserver(this);
|
mLowDisplayBrightnessThresholds);
|
||||||
cr.registerContentObserver(mDisplayBrightnessSetting,
|
mShouldObserveAmbientLowChange = hasValidThreshold(
|
||||||
false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM);
|
mLowAmbientBrightnessThresholds);
|
||||||
} else {
|
} else {
|
||||||
cr.unregisterContentObserver(this);
|
mShouldObserveDisplayLowChange = false;
|
||||||
|
mShouldObserveAmbientLowChange = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mShouldObserveAmbientChange) {
|
if (mRefreshRateInHighZone > 0) {
|
||||||
|
mShouldObserveDisplayHighChange = hasValidThreshold(
|
||||||
|
mHighDisplayBrightnessThresholds);
|
||||||
|
mShouldObserveAmbientHighChange = hasValidThreshold(
|
||||||
|
mHighAmbientBrightnessThresholds);
|
||||||
|
} else {
|
||||||
|
mShouldObserveDisplayHighChange = false;
|
||||||
|
mShouldObserveAmbientHighChange = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShouldObserveDisplayLowChange || mShouldObserveDisplayHighChange) {
|
||||||
|
// Content Service does not check if an listener has already been registered.
|
||||||
|
// To ensure only one listener is registered, force an unregistration first.
|
||||||
|
mInjector.unregisterBrightnessObserver(cr, this);
|
||||||
|
mInjector.registerBrightnessObserver(cr, this);
|
||||||
|
} else {
|
||||||
|
mInjector.unregisterBrightnessObserver(cr, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
|
||||||
Resources resources = mContext.getResources();
|
Resources resources = mContext.getResources();
|
||||||
String lightSensorType = resources.getString(
|
String lightSensorType = resources.getString(
|
||||||
com.android.internal.R.string.config_displayLightSensorType);
|
com.android.internal.R.string.config_displayLightSensorType);
|
||||||
@@ -1243,8 +1454,6 @@ public class DisplayModeDirector {
|
|||||||
|
|
||||||
mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res);
|
mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res);
|
||||||
mLightSensor = lightSensor;
|
mLightSensor = lightSensor;
|
||||||
|
|
||||||
onScreenOn(isDefaultDisplayOn());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mAmbientFilter = null;
|
mAmbientFilter = null;
|
||||||
@@ -1263,11 +1472,7 @@ public class DisplayModeDirector {
|
|||||||
* Checks to see if at least one value is positive, in which case it is necessary to listen
|
* Checks to see if at least one value is positive, in which case it is necessary to listen
|
||||||
* to value changes.
|
* to value changes.
|
||||||
*/
|
*/
|
||||||
private boolean checkShouldObserve(int[] a) {
|
private boolean hasValidThreshold(int[] a) {
|
||||||
if (mRefreshRateInZone <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int d: a) {
|
for (int d: a) {
|
||||||
if (d >= 0) {
|
if (d >= 0) {
|
||||||
return true;
|
return true;
|
||||||
@@ -1277,13 +1482,13 @@ public class DisplayModeDirector {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInsideZone(int brightness, float lux) {
|
private boolean isInsideLowZone(int brightness, float lux) {
|
||||||
for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
|
for (int i = 0; i < mLowDisplayBrightnessThresholds.length; i++) {
|
||||||
int disp = mDisplayBrightnessThresholds[i];
|
int disp = mLowDisplayBrightnessThresholds[i];
|
||||||
int ambi = mAmbientBrightnessThresholds[i];
|
int ambi = mLowAmbientBrightnessThresholds[i];
|
||||||
|
|
||||||
if (disp >= 0 && ambi >= 0) {
|
if (disp >= 0 && ambi >= 0) {
|
||||||
if (brightness <= disp && mAmbientLux <= ambi) {
|
if (brightness <= disp && lux <= ambi) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (disp >= 0) {
|
} else if (disp >= 0) {
|
||||||
@@ -1291,7 +1496,7 @@ public class DisplayModeDirector {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (ambi >= 0) {
|
} else if (ambi >= 0) {
|
||||||
if (mAmbientLux <= ambi) {
|
if (lux <= ambi) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1299,27 +1504,77 @@ public class DisplayModeDirector {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO: brightnessfloat: make it use float not int
|
|
||||||
private void onBrightnessChangedLocked() {
|
|
||||||
int brightness = Settings.System.getInt(mContext.getContentResolver(),
|
|
||||||
Settings.System.SCREEN_BRIGHTNESS, -1);
|
|
||||||
|
|
||||||
|
private boolean isInsideHighZone(int brightness, float lux) {
|
||||||
|
for (int i = 0; i < mHighDisplayBrightnessThresholds.length; i++) {
|
||||||
|
int disp = mHighDisplayBrightnessThresholds[i];
|
||||||
|
int ambi = mHighAmbientBrightnessThresholds[i];
|
||||||
|
|
||||||
|
if (disp >= 0 && ambi >= 0) {
|
||||||
|
if (brightness >= disp && lux >= ambi) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (disp >= 0) {
|
||||||
|
if (brightness >= disp) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (ambi >= 0) {
|
||||||
|
if (lux >= ambi) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private void onBrightnessChangedLocked() {
|
||||||
Vote vote = null;
|
Vote vote = null;
|
||||||
boolean insideZone = isInsideZone(brightness, mAmbientLux);
|
|
||||||
if (insideZone) {
|
if (mBrightness < 0) {
|
||||||
vote = Vote.forRefreshRates(mRefreshRateInZone, mRefreshRateInZone);
|
// Either the setting isn't available or we shouldn't be observing yet anyways.
|
||||||
|
// Either way, just bail out since there's nothing we can do here.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean insideLowZone = hasValidLowZone() && isInsideLowZone(mBrightness, mAmbientLux);
|
||||||
|
if (insideLowZone) {
|
||||||
|
vote = Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean insideHighZone = hasValidHighZone()
|
||||||
|
&& isInsideHighZone(mBrightness, mAmbientLux);
|
||||||
|
if (insideHighZone) {
|
||||||
|
vote = Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " + mAmbientLux +
|
Slog.d(TAG, "Display brightness " + mBrightness + ", ambient lux " + mAmbientLux
|
||||||
", Vote " + vote);
|
+ ", Vote " + vote);
|
||||||
}
|
}
|
||||||
updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
|
updateVoteLocked(Vote.PRIORITY_FLICKER, vote);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onScreenOn(boolean on) {
|
private boolean hasValidLowZone() {
|
||||||
if (mScreenOn != on) {
|
return mRefreshRateInLowZone > 0
|
||||||
mScreenOn = on;
|
&& (mShouldObserveDisplayLowChange || mShouldObserveAmbientLowChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasValidHighZone() {
|
||||||
|
return mRefreshRateInHighZone > 0
|
||||||
|
&& (mShouldObserveDisplayHighChange || mShouldObserveAmbientHighChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDefaultDisplayState() {
|
||||||
|
Display display = mContext.getSystemService(DisplayManager.class)
|
||||||
|
.getDisplay(Display.DEFAULT_DISPLAY);
|
||||||
|
boolean defaultDisplayOn = display != null && display.getState() != Display.STATE_OFF;
|
||||||
|
setDefaultDisplayState(defaultDisplayOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public void setDefaultDisplayState(boolean on) {
|
||||||
|
if (mDefaultDisplayOn != on) {
|
||||||
|
mDefaultDisplayOn = on;
|
||||||
updateSensorStatus();
|
updateSensorStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1329,8 +1584,8 @@ public class DisplayModeDirector {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mShouldObserveAmbientChange && mScreenOn && !mLowPowerModeEnabled
|
if ((mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange)
|
||||||
&& mRefreshRateChangeable) {
|
&& isDeviceActive() && !mLowPowerModeEnabled && mRefreshRateChangeable) {
|
||||||
mSensorManager.registerListener(mLightSensorListener,
|
mSensorManager.registerListener(mLightSensorListener,
|
||||||
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
|
mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
|
||||||
} else {
|
} else {
|
||||||
@@ -1339,11 +1594,8 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDefaultDisplayOn() {
|
private boolean isDeviceActive() {
|
||||||
final Display display = mContext.getSystemService(DisplayManager.class)
|
return mDefaultDisplayOn && mInjector.isDeviceInteractive(mContext);
|
||||||
.getDisplay(Display.DEFAULT_DISPLAY);
|
|
||||||
return display.getState() != Display.STATE_OFF
|
|
||||||
&& mContext.getSystemService(PowerManager.class).isInteractive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class LightSensorEventListener implements SensorEventListener {
|
private final class LightSensorEventListener implements SensorEventListener {
|
||||||
@@ -1361,23 +1613,33 @@ public class DisplayModeDirector {
|
|||||||
Slog.d(TAG, "On sensor changed: " + mLastSensorData);
|
Slog.d(TAG, "On sensor changed: " + mLastSensorData);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean zoneChanged = isDifferentZone(mLastSensorData, mAmbientLux);
|
boolean lowZoneChanged = isDifferentZone(mLastSensorData, mAmbientLux,
|
||||||
if (zoneChanged && mLastSensorData < mAmbientLux) {
|
mLowAmbientBrightnessThresholds);
|
||||||
// Easier to see flicker at lower brightness environment. Forget the history to
|
boolean highZoneChanged = isDifferentZone(mLastSensorData, mAmbientLux,
|
||||||
// get immediate response.
|
mHighAmbientBrightnessThresholds);
|
||||||
mAmbientFilter.clear();
|
if ((lowZoneChanged && mLastSensorData < mAmbientLux)
|
||||||
|
|| (highZoneChanged && mLastSensorData > mAmbientLux)) {
|
||||||
|
// Easier to see flicker at lower brightness environment or high brightness
|
||||||
|
// environment. Forget the history to get immediate response.
|
||||||
|
if (mAmbientFilter != null) {
|
||||||
|
mAmbientFilter.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long now = SystemClock.uptimeMillis();
|
long now = SystemClock.uptimeMillis();
|
||||||
mAmbientFilter.addValue(now, mLastSensorData);
|
if (mAmbientFilter != null) {
|
||||||
|
mAmbientFilter.addValue(now, mLastSensorData);
|
||||||
|
}
|
||||||
|
|
||||||
mHandler.removeCallbacks(mInjectSensorEventRunnable);
|
mHandler.removeCallbacks(mInjectSensorEventRunnable);
|
||||||
processSensorData(now);
|
processSensorData(now);
|
||||||
|
|
||||||
if (zoneChanged && mLastSensorData > mAmbientLux) {
|
if ((lowZoneChanged && mLastSensorData > mAmbientLux)
|
||||||
|
|| (highZoneChanged && mLastSensorData < mAmbientLux)) {
|
||||||
// Sensor may not report new event if there is no brightness change.
|
// Sensor may not report new event if there is no brightness change.
|
||||||
// Need to keep querying the temporal filter for the latest estimation,
|
// Need to keep querying the temporal filter for the latest estimation,
|
||||||
// until enter in higher lux zone or is interrupted by a new sensor event.
|
// until sensor readout and filter estimation are in the same zone or
|
||||||
|
// is interrupted by a new sensor event.
|
||||||
mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
|
mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1392,17 +1654,19 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void processSensorData(long now) {
|
private void processSensorData(long now) {
|
||||||
mAmbientLux = mAmbientFilter.getEstimate(now);
|
if (mAmbientFilter != null) {
|
||||||
|
mAmbientLux = mAmbientFilter.getEstimate(now);
|
||||||
|
} else {
|
||||||
|
mAmbientLux = mLastSensorData;
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
onBrightnessChangedLocked();
|
onBrightnessChangedLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isDifferentZone(float lux1, float lux2) {
|
private boolean isDifferentZone(float lux1, float lux2, int[] luxThresholds) {
|
||||||
for (int z = 0; z < mAmbientBrightnessThresholds.length; z++) {
|
for (final float boundary : luxThresholds) {
|
||||||
final float boundary = mAmbientBrightnessThresholds[z];
|
|
||||||
|
|
||||||
// Test each boundary. See if the current value and the new value are at
|
// Test each boundary. See if the current value and the new value are at
|
||||||
// different sides.
|
// different sides.
|
||||||
if ((lux1 <= boundary && lux2 > boundary)
|
if ((lux1 <= boundary && lux2 > boundary)
|
||||||
@@ -1422,7 +1686,10 @@ public class DisplayModeDirector {
|
|||||||
processSensorData(now);
|
processSensorData(now);
|
||||||
|
|
||||||
// Inject next event if there is a possible zone change.
|
// Inject next event if there is a possible zone change.
|
||||||
if (isDifferentZone(mLastSensorData, mAmbientLux)) {
|
if (isDifferentZone(mLastSensorData, mAmbientLux,
|
||||||
|
mLowAmbientBrightnessThresholds)
|
||||||
|
|| isDifferentZone(mLastSensorData, mAmbientLux,
|
||||||
|
mHighAmbientBrightnessThresholds)) {
|
||||||
mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
|
mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1435,33 +1702,75 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void startListening() {
|
public void startListening() {
|
||||||
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
BackgroundThread.getExecutor(), this);
|
BackgroundThread.getExecutor(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return null if no such property or wrong format (not comma separated integers).
|
* Return null if no such property or wrong format (not comma separated integers).
|
||||||
*/
|
*/
|
||||||
public int[] getBrightnessThresholds() {
|
public int[] getLowDisplayBrightnessThresholds() {
|
||||||
return getIntArrayProperty(
|
return getIntArrayProperty(
|
||||||
DisplayManager.DeviceConfig.
|
DisplayManager.DeviceConfig.
|
||||||
KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS);
|
KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return null if no such property or wrong format (not comma separated integers).
|
* Return null if no such property or wrong format (not comma separated integers).
|
||||||
*/
|
*/
|
||||||
public int[] getAmbientThresholds() {
|
public int[] getLowAmbientBrightnessThresholds() {
|
||||||
return getIntArrayProperty(
|
return getIntArrayProperty(
|
||||||
DisplayManager.DeviceConfig.
|
DisplayManager.DeviceConfig.
|
||||||
KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS);
|
KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRefreshRateInLowZone() {
|
||||||
|
int defaultRefreshRateInZone = mContext.getResources().getInteger(
|
||||||
|
R.integer.config_defaultRefreshRateInZone);
|
||||||
|
|
||||||
|
int refreshRate = mDeviceConfig.getInt(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
|
DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE,
|
||||||
|
defaultRefreshRateInZone);
|
||||||
|
|
||||||
|
return refreshRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return null if no such property or wrong format (not comma separated integers).
|
||||||
|
*/
|
||||||
|
public int[] getHighDisplayBrightnessThresholds() {
|
||||||
|
return getIntArrayProperty(
|
||||||
|
DisplayManager.DeviceConfig
|
||||||
|
.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return null if no such property or wrong format (not comma separated integers).
|
||||||
|
*/
|
||||||
|
public int[] getHighAmbientBrightnessThresholds() {
|
||||||
|
return getIntArrayProperty(
|
||||||
|
DisplayManager.DeviceConfig
|
||||||
|
.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRefreshRateInHighZone() {
|
||||||
|
int defaultRefreshRateInZone = mContext.getResources().getInteger(
|
||||||
|
R.integer.config_fixedRefreshRateInHighZone);
|
||||||
|
|
||||||
|
int refreshRate = mDeviceConfig.getInt(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
|
DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE,
|
||||||
|
defaultRefreshRateInZone);
|
||||||
|
|
||||||
|
return refreshRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return null if no such property
|
* Return null if no such property
|
||||||
*/
|
*/
|
||||||
public Float getDefaultPeakRefreshRate() {
|
public Float getDefaultPeakRefreshRate() {
|
||||||
float defaultPeakRefreshRate = DeviceConfig.getFloat(
|
float defaultPeakRefreshRate = mDeviceConfig.getFloat(
|
||||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);
|
DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);
|
||||||
|
|
||||||
@@ -1471,36 +1780,35 @@ public class DisplayModeDirector {
|
|||||||
return defaultPeakRefreshRate;
|
return defaultPeakRefreshRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRefreshRateInZone() {
|
|
||||||
int defaultRefreshRateInZone = mContext.getResources().getInteger(
|
|
||||||
R.integer.config_defaultRefreshRateInZone);
|
|
||||||
|
|
||||||
int refreshRate = DeviceConfig.getInt(
|
|
||||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
|
||||||
DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE,
|
|
||||||
defaultRefreshRateInZone);
|
|
||||||
|
|
||||||
return refreshRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
|
public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
|
||||||
int[] brightnessThresholds = getBrightnessThresholds();
|
|
||||||
int[] ambientThresholds = getAmbientThresholds();
|
|
||||||
Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
|
Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
|
||||||
int refreshRateInZone = getRefreshRateInZone();
|
|
||||||
|
|
||||||
mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
|
|
||||||
new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
|
|
||||||
.sendToTarget();
|
|
||||||
mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
|
mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
|
||||||
defaultPeakRefreshRate).sendToTarget();
|
defaultPeakRefreshRate).sendToTarget();
|
||||||
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_ZONE_CHANGED, refreshRateInZone,
|
|
||||||
0).sendToTarget();
|
int[] lowDisplayBrightnessThresholds = getLowDisplayBrightnessThresholds();
|
||||||
|
int[] lowAmbientBrightnessThresholds = getLowAmbientBrightnessThresholds();
|
||||||
|
int refreshRateInLowZone = getRefreshRateInLowZone();
|
||||||
|
|
||||||
|
mHandler.obtainMessage(MSG_LOW_BRIGHTNESS_THRESHOLDS_CHANGED,
|
||||||
|
new Pair<>(lowDisplayBrightnessThresholds, lowAmbientBrightnessThresholds))
|
||||||
|
.sendToTarget();
|
||||||
|
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED, refreshRateInLowZone, 0)
|
||||||
|
.sendToTarget();
|
||||||
|
|
||||||
|
int[] highDisplayBrightnessThresholds = getHighDisplayBrightnessThresholds();
|
||||||
|
int[] highAmbientBrightnessThresholds = getHighAmbientBrightnessThresholds();
|
||||||
|
int refreshRateInHighZone = getRefreshRateInHighZone();
|
||||||
|
|
||||||
|
mHandler.obtainMessage(MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED,
|
||||||
|
new Pair<>(highDisplayBrightnessThresholds, highAmbientBrightnessThresholds))
|
||||||
|
.sendToTarget();
|
||||||
|
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
|
||||||
|
.sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int[] getIntArrayProperty(String prop) {
|
private int[] getIntArrayProperty(String prop) {
|
||||||
String strArray = DeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
|
String strArray = mDeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
|
||||||
null);
|
null);
|
||||||
|
|
||||||
if (strArray != null) {
|
if (strArray != null) {
|
||||||
@@ -1527,4 +1835,59 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Injector {
|
||||||
|
// TODO: brightnessfloat: change this to the float setting
|
||||||
|
Uri DISPLAY_BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
|
||||||
|
Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
DeviceConfigInterface getDeviceConfig();
|
||||||
|
|
||||||
|
void registerBrightnessObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer);
|
||||||
|
|
||||||
|
void unregisterBrightnessObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer);
|
||||||
|
|
||||||
|
void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer);
|
||||||
|
|
||||||
|
boolean isDeviceInteractive(@NonNull Context context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static class RealInjector implements Injector {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NonNull
|
||||||
|
public DeviceConfigInterface getDeviceConfig() {
|
||||||
|
return DeviceConfigInterface.REAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerBrightnessObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer) {
|
||||||
|
cr.registerContentObserver(DISPLAY_BRIGHTNESS_URI, false /*notifyDescendants*/,
|
||||||
|
observer, UserHandle.USER_SYSTEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer) {
|
||||||
|
cr.unregisterContentObserver(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer) {
|
||||||
|
cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/,
|
||||||
|
observer, UserHandle.USER_SYSTEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDeviceInteractive(@NonNull Context ctx) {
|
||||||
|
return ctx.getSystemService(PowerManager.class).isInteractive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.server.wm.utils;
|
package com.android.server.utils;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -53,6 +53,11 @@ public interface DeviceConfigInterface {
|
|||||||
*/
|
*/
|
||||||
boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue);
|
boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see DeviceConfig#getFloat
|
||||||
|
*/
|
||||||
|
float getFloat(@NonNull String namespace, @NonNull String name, float defaultValue);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see DeviceConfig#addOnPropertiesChangedListener
|
* @see DeviceConfig#addOnPropertiesChangedListener
|
||||||
*/
|
*/
|
||||||
@@ -95,6 +100,12 @@ public interface DeviceConfigInterface {
|
|||||||
return DeviceConfig.getBoolean(namespace, name, defaultValue);
|
return DeviceConfig.getBoolean(namespace, name, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFloat(@NonNull String namespace, @NonNull String name,
|
||||||
|
float defaultValue) {
|
||||||
|
return DeviceConfig.getFloat(namespace, name, defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addOnPropertiesChangedListener(String namespace, Executor executor,
|
public void addOnPropertiesChangedListener(String namespace, Executor executor,
|
||||||
DeviceConfig.OnPropertiesChangedListener listener) {
|
DeviceConfig.OnPropertiesChangedListener listener) {
|
||||||
@@ -27,7 +27,7 @@ import android.util.ArraySet;
|
|||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.os.BackgroundThread;
|
import com.android.internal.os.BackgroundThread;
|
||||||
import com.android.server.wm.utils.DeviceConfigInterface;
|
import com.android.server.utils.DeviceConfigInterface;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import android.provider.AndroidDeviceConfig;
|
|||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.server.wm.utils.DeviceConfigInterface;
|
import com.android.server.utils.DeviceConfigInterface;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|||||||
@@ -282,8 +282,8 @@ import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
|
|||||||
import com.android.server.power.ShutdownThread;
|
import com.android.server.power.ShutdownThread;
|
||||||
import com.android.server.protolog.ProtoLogImpl;
|
import com.android.server.protolog.ProtoLogImpl;
|
||||||
import com.android.server.protolog.common.ProtoLog;
|
import com.android.server.protolog.common.ProtoLog;
|
||||||
|
import com.android.server.utils.DeviceConfigInterface;
|
||||||
import com.android.server.utils.PriorityDump;
|
import com.android.server.utils.PriorityDump;
|
||||||
import com.android.server.wm.utils.DeviceConfigInterface;
|
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ android_test {
|
|||||||
// TODO: remove once Android migrates to JUnit 4.12,
|
// TODO: remove once Android migrates to JUnit 4.12,
|
||||||
// which provides assertThrows
|
// which provides assertThrows
|
||||||
"testng",
|
"testng",
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
aidl: {
|
aidl: {
|
||||||
@@ -110,6 +109,7 @@ java_library {
|
|||||||
"utils/**/*.java",
|
"utils/**/*.java",
|
||||||
"utils/**/*.kt",
|
"utils/**/*.kt",
|
||||||
"utils-mockito/**/*.kt",
|
"utils-mockito/**/*.kt",
|
||||||
|
":services.core-sources-deviceconfig-interface",
|
||||||
],
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"junit",
|
"junit",
|
||||||
@@ -126,6 +126,7 @@ java_library {
|
|||||||
"utils/**/*.java",
|
"utils/**/*.java",
|
||||||
"utils/**/*.kt",
|
"utils/**/*.kt",
|
||||||
"utils-mockito/**/*.kt",
|
"utils-mockito/**/*.kt",
|
||||||
|
":services.core-sources-deviceconfig-interface",
|
||||||
],
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"junit",
|
"junit",
|
||||||
|
|||||||
@@ -16,49 +16,99 @@
|
|||||||
|
|
||||||
package com.android.server.display;
|
package com.android.server.display;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
|
||||||
import static org.mockito.Mockito.verify;
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
|
||||||
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS;
|
||||||
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS;
|
||||||
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
|
||||||
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
|
||||||
|
|
||||||
|
import static com.android.server.display.DisplayModeDirector.Vote.PRIORITY_FLICKER;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.any;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.database.ContentObserver;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.internal.util.Preconditions;
|
||||||
|
import com.android.internal.util.test.FakeSettingsProvider;
|
||||||
|
import com.android.internal.util.test.FakeSettingsProviderRule;
|
||||||
import com.android.server.display.DisplayModeDirector.BrightnessObserver;
|
import com.android.server.display.DisplayModeDirector.BrightnessObserver;
|
||||||
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
|
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
|
||||||
import com.android.server.display.DisplayModeDirector.Vote;
|
import com.android.server.display.DisplayModeDirector.Vote;
|
||||||
|
import com.android.server.testutils.FakeDeviceConfigInterface;
|
||||||
|
|
||||||
import com.google.common.truth.Truth;
|
import com.google.common.truth.Truth;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public class DisplayModeDirectorTest {
|
public class DisplayModeDirectorTest {
|
||||||
// The tolerance within which we consider something approximately equals.
|
// The tolerance within which we consider something approximately equals.
|
||||||
|
private static final String TAG = "DisplayModeDirectorTest";
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
private static final float FLOAT_TOLERANCE = 0.01f;
|
private static final float FLOAT_TOLERANCE = 0.01f;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private FakesInjector mInjector;
|
||||||
|
private Handler mHandler;
|
||||||
|
@Rule
|
||||||
|
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
|
||||||
|
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
|
||||||
|
when(mContext.getContentResolver()).thenReturn(resolver);
|
||||||
|
mInjector = new FakesInjector();
|
||||||
|
mHandler = new Handler(Looper.getMainLooper());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DisplayModeDirector createDirectorFromRefreshRateArray(
|
private DisplayModeDirector createDirectorFromRefreshRateArray(
|
||||||
float[] refreshRates, int baseModeId) {
|
float[] refreshRates, int baseModeId) {
|
||||||
DisplayModeDirector director =
|
DisplayModeDirector director =
|
||||||
new DisplayModeDirector(mContext, new Handler(Looper.getMainLooper()));
|
new DisplayModeDirector(mContext, mHandler, mInjector);
|
||||||
int displayId = 0;
|
int displayId = 0;
|
||||||
Display.Mode[] modes = new Display.Mode[refreshRates.length];
|
Display.Mode[] modes = new Display.Mode[refreshRates.length];
|
||||||
for (int i = 0; i < refreshRates.length; i++) {
|
for (int i = 0; i < refreshRates.length; i++) {
|
||||||
@@ -159,9 +209,9 @@ public class DisplayModeDirectorTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBrightnessHasLowerPriorityThanUser() {
|
public void testFlickerHasLowerPriorityThanUser() {
|
||||||
assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
|
assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
|
||||||
assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_SIZE);
|
assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_SIZE);
|
||||||
|
|
||||||
int displayId = 0;
|
int displayId = 0;
|
||||||
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
|
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
|
||||||
@@ -169,7 +219,7 @@ public class DisplayModeDirectorTest {
|
|||||||
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
||||||
votesByDisplay.put(displayId, votes);
|
votesByDisplay.put(displayId, votes);
|
||||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
|
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
|
||||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
|
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
|
||||||
director.injectVotesByDisplay(votesByDisplay);
|
director.injectVotesByDisplay(votesByDisplay);
|
||||||
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
||||||
@@ -177,7 +227,7 @@ public class DisplayModeDirectorTest {
|
|||||||
|
|
||||||
votes.clear();
|
votes.clear();
|
||||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
|
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
|
||||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
|
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
|
||||||
director.injectVotesByDisplay(votesByDisplay);
|
director.injectVotesByDisplay(votesByDisplay);
|
||||||
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
|
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
|
||||||
@@ -185,7 +235,7 @@ public class DisplayModeDirectorTest {
|
|||||||
|
|
||||||
votes.clear();
|
votes.clear();
|
||||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
|
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
|
||||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
|
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
|
||||||
director.injectVotesByDisplay(votesByDisplay);
|
director.injectVotesByDisplay(votesByDisplay);
|
||||||
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
|
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
|
||||||
@@ -193,7 +243,7 @@ public class DisplayModeDirectorTest {
|
|||||||
|
|
||||||
votes.clear();
|
votes.clear();
|
||||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
|
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
|
||||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
|
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
|
||||||
director.injectVotesByDisplay(votesByDisplay);
|
director.injectVotesByDisplay(votesByDisplay);
|
||||||
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
||||||
@@ -202,10 +252,10 @@ public class DisplayModeDirectorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAppRequestRefreshRateRange() {
|
public void testAppRequestRefreshRateRange() {
|
||||||
// Confirm that the app request range doesn't include low brightness or min refresh rate
|
// Confirm that the app request range doesn't include flicker or min refresh rate settings,
|
||||||
// settings, but does include everything else.
|
// but does include everything else.
|
||||||
assertTrue(
|
assertTrue(
|
||||||
Vote.PRIORITY_LOW_BRIGHTNESS < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
PRIORITY_FLICKER < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
||||||
assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
|
assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
|
||||||
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
||||||
assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE
|
assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE
|
||||||
@@ -216,7 +266,7 @@ public class DisplayModeDirectorTest {
|
|||||||
SparseArray<Vote> votes = new SparseArray<>();
|
SparseArray<Vote> votes = new SparseArray<>();
|
||||||
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
||||||
votesByDisplay.put(displayId, votes);
|
votesByDisplay.put(displayId, votes);
|
||||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
|
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
|
||||||
director.injectVotesByDisplay(votesByDisplay);
|
director.injectVotesByDisplay(votesByDisplay);
|
||||||
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
||||||
@@ -302,4 +352,343 @@ public class DisplayModeDirectorTest {
|
|||||||
verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
|
verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
|
||||||
verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
|
verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBrightnessObserverGetsUpdatedRefreshRatesForZone() {
|
||||||
|
DisplayModeDirector director =
|
||||||
|
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
|
||||||
|
SensorManager sensorManager = createMockSensorManager(createLightSensor());
|
||||||
|
|
||||||
|
final int initialRefreshRate = 60;
|
||||||
|
mInjector.getDeviceConfig().setRefreshRateInLowZone(initialRefreshRate);
|
||||||
|
director.start(sensorManager);
|
||||||
|
assertThat(director.getBrightnessObserver().getRefreshRateInLowZone())
|
||||||
|
.isEqualTo(initialRefreshRate);
|
||||||
|
|
||||||
|
final int updatedRefreshRate = 90;
|
||||||
|
mInjector.getDeviceConfig().setRefreshRateInLowZone(updatedRefreshRate);
|
||||||
|
// Need to wait for the property change to propagate to the main thread.
|
||||||
|
waitForIdleSync();
|
||||||
|
assertThat(director.getBrightnessObserver().getRefreshRateInLowZone())
|
||||||
|
.isEqualTo(updatedRefreshRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBrightnessObserverThresholdsInZone() {
|
||||||
|
DisplayModeDirector director =
|
||||||
|
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
|
||||||
|
SensorManager sensorManager = createMockSensorManager(createLightSensor());
|
||||||
|
|
||||||
|
final int[] initialDisplayThresholds = { 10 };
|
||||||
|
final int[] initialAmbientThresholds = { 20 };
|
||||||
|
|
||||||
|
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||||
|
config.setLowDisplayBrightnessThresholds(initialDisplayThresholds);
|
||||||
|
config.setLowAmbientBrightnessThresholds(initialAmbientThresholds);
|
||||||
|
director.start(sensorManager);
|
||||||
|
|
||||||
|
assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds())
|
||||||
|
.isEqualTo(initialDisplayThresholds);
|
||||||
|
assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds())
|
||||||
|
.isEqualTo(initialAmbientThresholds);
|
||||||
|
|
||||||
|
final int[] updatedDisplayThresholds = { 9, 14 };
|
||||||
|
final int[] updatedAmbientThresholds = { -1, 19 };
|
||||||
|
config.setLowDisplayBrightnessThresholds(updatedDisplayThresholds);
|
||||||
|
config.setLowAmbientBrightnessThresholds(updatedAmbientThresholds);
|
||||||
|
// Need to wait for the property change to propagate to the main thread.
|
||||||
|
waitForIdleSync();
|
||||||
|
assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds())
|
||||||
|
.isEqualTo(updatedDisplayThresholds);
|
||||||
|
assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds())
|
||||||
|
.isEqualTo(updatedAmbientThresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLockFpsForLowZone() throws Exception {
|
||||||
|
DisplayModeDirector director =
|
||||||
|
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
|
||||||
|
setPeakRefreshRate(90);
|
||||||
|
director.getSettingsObserver().setDefaultRefreshRate(90);
|
||||||
|
director.getBrightnessObserver().setDefaultDisplayState(true);
|
||||||
|
|
||||||
|
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||||
|
config.setRefreshRateInLowZone(90);
|
||||||
|
config.setLowDisplayBrightnessThresholds(new int[] { 10 });
|
||||||
|
config.setLowAmbientBrightnessThresholds(new int[] { 20 });
|
||||||
|
|
||||||
|
Sensor lightSensor = createLightSensor();
|
||||||
|
SensorManager sensorManager = createMockSensorManager(lightSensor);
|
||||||
|
|
||||||
|
director.start(sensorManager);
|
||||||
|
|
||||||
|
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||||
|
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||||
|
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
|
||||||
|
.registerListener(
|
||||||
|
listenerCaptor.capture(),
|
||||||
|
eq(lightSensor),
|
||||||
|
anyInt(),
|
||||||
|
any(Handler.class));
|
||||||
|
SensorEventListener listener = listenerCaptor.getValue();
|
||||||
|
|
||||||
|
setBrightness(10);
|
||||||
|
// Sensor reads 20 lux,
|
||||||
|
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
|
||||||
|
|
||||||
|
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||||
|
assertVoteForRefreshRateLocked(vote, 90 /*fps*/);
|
||||||
|
|
||||||
|
setBrightness(125);
|
||||||
|
// Sensor reads 1000 lux,
|
||||||
|
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
|
||||||
|
|
||||||
|
vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||||
|
assertThat(vote).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLockFpsForHighZone() throws Exception {
|
||||||
|
DisplayModeDirector director =
|
||||||
|
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
|
||||||
|
setPeakRefreshRate(90 /*fps*/);
|
||||||
|
director.getSettingsObserver().setDefaultRefreshRate(90);
|
||||||
|
director.getBrightnessObserver().setDefaultDisplayState(true);
|
||||||
|
|
||||||
|
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||||
|
config.setRefreshRateInHighZone(60);
|
||||||
|
config.setHighDisplayBrightnessThresholds(new int[] { 255 });
|
||||||
|
config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
|
||||||
|
|
||||||
|
Sensor lightSensor = createLightSensor();
|
||||||
|
SensorManager sensorManager = createMockSensorManager(lightSensor);
|
||||||
|
|
||||||
|
director.start(sensorManager);
|
||||||
|
|
||||||
|
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||||
|
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||||
|
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
|
||||||
|
.registerListener(
|
||||||
|
listenerCaptor.capture(),
|
||||||
|
eq(lightSensor),
|
||||||
|
anyInt(),
|
||||||
|
any(Handler.class));
|
||||||
|
SensorEventListener listener = listenerCaptor.getValue();
|
||||||
|
|
||||||
|
setBrightness(100);
|
||||||
|
// Sensor reads 2000 lux,
|
||||||
|
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
|
||||||
|
|
||||||
|
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||||
|
assertThat(vote).isNull();
|
||||||
|
|
||||||
|
setBrightness(255);
|
||||||
|
// Sensor reads 9000 lux,
|
||||||
|
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
|
||||||
|
|
||||||
|
vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||||
|
assertVoteForRefreshRateLocked(vote, 60 /*fps*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertVoteForRefreshRateLocked(Vote vote, float refreshRate) {
|
||||||
|
assertThat(vote).isNotNull();
|
||||||
|
final DisplayModeDirector.RefreshRateRange expectedRange =
|
||||||
|
new DisplayModeDirector.RefreshRateRange(refreshRate, refreshRate);
|
||||||
|
assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class FakeDeviceConfig extends FakeDeviceConfigInterface {
|
||||||
|
@Override
|
||||||
|
public String getProperty(String namespace, String name) {
|
||||||
|
Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
|
||||||
|
return super.getProperty(namespace, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addOnPropertiesChangedListener(
|
||||||
|
String namespace,
|
||||||
|
Executor executor,
|
||||||
|
DeviceConfig.OnPropertiesChangedListener listener) {
|
||||||
|
Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
|
||||||
|
super.addOnPropertiesChangedListener(namespace, executor, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRefreshRateInLowZone(int fps) {
|
||||||
|
putPropertyAndNotify(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_LOW_ZONE,
|
||||||
|
String.valueOf(fps));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||||
|
String thresholds = toPropertyValue(brightnessThresholds);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.e(TAG, "Brightness Thresholds = " + thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
putPropertyAndNotify(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
|
KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS,
|
||||||
|
thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLowAmbientBrightnessThresholds(int[] ambientThresholds) {
|
||||||
|
String thresholds = toPropertyValue(ambientThresholds);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.e(TAG, "Ambient Thresholds = " + thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
putPropertyAndNotify(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
|
KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS,
|
||||||
|
thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRefreshRateInHighZone(int fps) {
|
||||||
|
putPropertyAndNotify(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_HIGH_ZONE,
|
||||||
|
String.valueOf(fps));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||||
|
String thresholds = toPropertyValue(brightnessThresholds);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.e(TAG, "Brightness Thresholds = " + thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
putPropertyAndNotify(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
|
KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS,
|
||||||
|
thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHighAmbientBrightnessThresholds(int[] ambientThresholds) {
|
||||||
|
String thresholds = toPropertyValue(ambientThresholds);
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.e(TAG, "Ambient Thresholds = " + thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
putPropertyAndNotify(
|
||||||
|
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||||
|
KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS,
|
||||||
|
thresholds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static String toPropertyValue(@NonNull int[] intArray) {
|
||||||
|
return Arrays.stream(intArray)
|
||||||
|
.mapToObj(Integer::toString)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBrightness(int brightness) {
|
||||||
|
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,
|
||||||
|
brightness);
|
||||||
|
mInjector.notifyBrightnessChanged();
|
||||||
|
waitForIdleSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPeakRefreshRate(float fps) {
|
||||||
|
Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE,
|
||||||
|
fps);
|
||||||
|
mInjector.notifyPeakRefreshRateChanged();
|
||||||
|
waitForIdleSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SensorManager createMockSensorManager(Sensor... sensors) {
|
||||||
|
SensorManager sensorManager = Mockito.mock(SensorManager.class);
|
||||||
|
when(sensorManager.getSensorList(anyInt())).then((invocation) -> {
|
||||||
|
List<Sensor> requestedSensors = new ArrayList<>();
|
||||||
|
int type = invocation.getArgument(0);
|
||||||
|
for (Sensor sensor : sensors) {
|
||||||
|
if (sensor.getType() == type || type == Sensor.TYPE_ALL) {
|
||||||
|
requestedSensors.add(sensor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestedSensors;
|
||||||
|
});
|
||||||
|
|
||||||
|
when(sensorManager.getDefaultSensor(anyInt())).then((invocation) -> {
|
||||||
|
int type = invocation.getArgument(0);
|
||||||
|
for (Sensor sensor : sensors) {
|
||||||
|
if (sensor.getType() == type) {
|
||||||
|
return sensor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return sensorManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Sensor createLightSensor() {
|
||||||
|
try {
|
||||||
|
return TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// There's nothing we can do if this fails, just throw a RuntimeException so that we
|
||||||
|
// don't have to mark every function that might call this as throwing Exception
|
||||||
|
throw new RuntimeException("Failed to create a light sensor", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void waitForIdleSync() {
|
||||||
|
mHandler.runWithScissors(() -> { }, 500 /*timeout*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FakesInjector implements DisplayModeDirector.Injector {
|
||||||
|
private final FakeDeviceConfig mDeviceConfig;
|
||||||
|
private ContentObserver mBrightnessObserver;
|
||||||
|
private ContentObserver mPeakRefreshRateObserver;
|
||||||
|
|
||||||
|
FakesInjector() {
|
||||||
|
mDeviceConfig = new FakeDeviceConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public FakeDeviceConfig getDeviceConfig() {
|
||||||
|
return mDeviceConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerBrightnessObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer) {
|
||||||
|
if (mBrightnessObserver != null) {
|
||||||
|
throw new IllegalStateException("Tried to register a second brightness observer");
|
||||||
|
}
|
||||||
|
mBrightnessObserver = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer) {
|
||||||
|
mBrightnessObserver = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyBrightnessChanged() {
|
||||||
|
if (mBrightnessObserver != null) {
|
||||||
|
mBrightnessObserver.dispatchChange(false /*selfChange*/, DISPLAY_BRIGHTNESS_URI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
|
||||||
|
@NonNull ContentObserver observer) {
|
||||||
|
mPeakRefreshRateObserver = observer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void notifyPeakRefreshRateChanged() {
|
||||||
|
if (mPeakRefreshRateObserver != null) {
|
||||||
|
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
|
||||||
|
PEAK_REFRESH_RATE_URI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDeviceInteractive(@NonNull Context context) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.server.wm.utils;
|
package com.android.server.testutils;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
@@ -22,6 +22,7 @@ import android.util.ArrayMap;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
import com.android.server.utils.DeviceConfigInterface;
|
||||||
|
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -121,6 +122,19 @@ public class FakeDeviceConfigInterface implements DeviceConfigInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFloat(String namespace, String name, float defaultValue) {
|
||||||
|
String value = getProperty(namespace, name);
|
||||||
|
if (value == null) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Float.parseFloat(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getBoolean(String namespace, String name, boolean defaultValue) {
|
public boolean getBoolean(String namespace, String name, boolean defaultValue) {
|
||||||
String value = getProperty(namespace, name);
|
String value = getProperty(namespace, name);
|
||||||
@@ -31,7 +31,7 @@ import androidx.test.filters.SmallTest;
|
|||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.server.wm.utils.FakeDeviceConfigInterface;
|
import com.android.server.testutils.FakeDeviceConfigInterface;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import android.platform.test.annotations.Presubmit;
|
|||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.server.wm.utils.FakeDeviceConfigInterface;
|
import com.android.server.testutils.FakeDeviceConfigInterface;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|||||||
@@ -91,6 +91,14 @@ public class FakeSettingsProvider extends MockContentProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link org.junit.rules.TestRule} that makes sure {@link #clearSettingsProvider()}
|
||||||
|
* is triggered before and after each test.
|
||||||
|
*/
|
||||||
|
public static FakeSettingsProviderRule rule() {
|
||||||
|
return new FakeSettingsProviderRule();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This needs to be called before and after using the FakeSettingsProvider class.
|
* This needs to be called before and after using the FakeSettingsProvider class.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.internal.util.test;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
|
|
||||||
|
import org.junit.rules.TestRule;
|
||||||
|
import org.junit.runner.Description;
|
||||||
|
import org.junit.runners.model.Statement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JUnit Rule helps keeping test {@link FakeSettingsProvider} clean.
|
||||||
|
*
|
||||||
|
* <p>It clears {@link FakeSettingsProvider} before and after each test. Example use:
|
||||||
|
* <pre class="code"><code class="java">
|
||||||
|
* public class ExampleTest {
|
||||||
|
*
|
||||||
|
* @Rule public FakeSettingsProviderRule rule = FakeSettingsProvider.rule();
|
||||||
|
*
|
||||||
|
* @Test
|
||||||
|
* public void shouldDoSomething() {
|
||||||
|
* ContextResolver cr = rule.mockContentResolver(mContext);
|
||||||
|
* Settings.Global.putInt(cr, "my_setting_name", 1);
|
||||||
|
* // Test code relying on my_setting_name value using cr
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @see FakeSettingsProvider
|
||||||
|
*/
|
||||||
|
public final class FakeSettingsProviderRule implements TestRule {
|
||||||
|
|
||||||
|
/** Prevent initialization outside {@link FakeSettingsProvider}. */
|
||||||
|
FakeSettingsProviderRule() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link MockContentResolver} that uses the {@link FakeSettingsProvider} as the
|
||||||
|
* {@link Settings#AUTHORITY} provider.
|
||||||
|
*/
|
||||||
|
public MockContentResolver mockContentResolver(Context context) {
|
||||||
|
MockContentResolver contentResolver = new MockContentResolver(context);
|
||||||
|
contentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||||
|
return contentResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Statement apply(Statement base, Description description) {
|
||||||
|
return new Statement() {
|
||||||
|
public void evaluate() throws Throwable {
|
||||||
|
FakeSettingsProvider.clearSettingsProvider();
|
||||||
|
try {
|
||||||
|
base.evaluate();
|
||||||
|
} finally {
|
||||||
|
FakeSettingsProvider.clearSettingsProvider();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user