Implement brightness-aware scrim

Bug: 163396794
Test: manual on device
Change-Id: I4a87c5876b3e173e5ae25fb35af5681db6538cf0
This commit is contained in:
Ilya Matyukhin
2020-08-12 17:35:33 -07:00
parent 5b9d1ce76e
commit 4b416fe4c9
2 changed files with 118 additions and 3 deletions

View File

@@ -17,19 +17,27 @@
package com.android.systemui.biometrics;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.MathUtils;
import android.util.Spline;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.widget.LinearLayout;
import com.android.internal.BrightnessSynchronizer;
import com.android.systemui.R;
import java.io.FileWriter;
@@ -41,16 +49,31 @@ import java.io.IOException;
*/
class UdfpsController {
private static final String TAG = "UdfpsController";
// Gamma approximation for the sRGB color space.
private static final float DISPLAY_GAMMA = 2.2f;
private final FingerprintManager mFingerprintManager;
private final WindowManager mWindowManager;
private final ContentResolver mContentResolver;
private final Handler mHandler;
private final UdfpsView mView;
private final WindowManager.LayoutParams mLayoutParams;
// Debugfs path to control the high-brightness mode.
private final String mHbmPath;
private final String mHbmEnableCommand;
private final String mHbmDisableCommand;
// Brightness in nits in the high-brightness mode.
private final float mHbmNits;
// A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to a
// brightness in nits.
private final Spline mBacklightToNitsSpline;
// A spline mapping from a value in nits to a backlight value of a hypothetical panel whose
// maximum backlight value corresponds to our panel's high-brightness mode.
// The output is normalized to the range [0, 1.0].
private Spline mNitsToHbmBacklightSpline;
// Default non-HBM backlight value normalized to the range [0, 1.0]. Used as a fallback when the
// actual brightness value cannot be retrieved.
private final float mDefaultBrightness;
private boolean mIsOverlayShowing;
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
@@ -96,6 +119,7 @@ class UdfpsController {
UdfpsController(Context context) {
mFingerprintManager = context.getSystemService(FingerprintManager.class);
mWindowManager = context.getSystemService(WindowManager.class);
mContentResolver = context.getContentResolver();
mHandler = new Handler(Looper.getMainLooper());
mLayoutParams = createLayoutParams(context);
@@ -109,6 +133,35 @@ class UdfpsController {
mHbmEnableCommand = context.getResources().getString(R.string.udfps_hbm_enable_command);
mHbmDisableCommand = context.getResources().getString(R.string.udfps_hbm_disable_command);
// This range only consists of the minimum and maximum values, which only cover
// non-high-brightness mode.
float[] nitsRange = toFloatArray(context.getResources().obtainTypedArray(
com.android.internal.R.array.config_screenBrightnessNits));
// The last value of this range corresponds to the high-brightness mode.
float[] nitsAutoBrightnessValues = toFloatArray(context.getResources().obtainTypedArray(
com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
mHbmNits = nitsAutoBrightnessValues[nitsAutoBrightnessValues.length - 1];
float[] hbmNitsRange = {nitsRange[0], mHbmNits};
// This range only consists of the minimum and maximum backlight values, which only apply
// in non-high-brightness mode.
float[] normalizedBacklightRange = normalizeBacklightRange(
context.getResources().getIntArray(
com.android.internal.R.array.config_screenBrightnessBacklight));
mBacklightToNitsSpline = Spline.createSpline(normalizedBacklightRange, nitsRange);
mNitsToHbmBacklightSpline = Spline.createSpline(hbmNitsRange, normalizedBacklightRange);
mDefaultBrightness = obtainDefaultBrightness(context);
// TODO(b/160025856): move to the "dump" method.
Log.v(TAG, String.format("ctor | mNitsRange: [%f, %f]", nitsRange[0], nitsRange[1]));
Log.v(TAG, String.format("ctor | mHbmNitsRange: [%f, %f]", hbmNitsRange[0],
hbmNitsRange[1]));
Log.v(TAG, String.format("ctor | mNormalizedBacklightRange: [%f, %f]",
normalizedBacklightRange[0], normalizedBacklightRange[1]));
mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());
mIsOverlayShowing = false;
}
@@ -138,7 +191,34 @@ class UdfpsController {
});
}
// Returns a value in the range of [0, 255].
private int computeScrimOpacity() {
// Backlight setting can be NaN, -1.0f, and [0.0f, 1.0f].
float backlightSetting = Settings.System.getFloatForUser(mContentResolver,
Settings.System.SCREEN_BRIGHTNESS_FLOAT, mDefaultBrightness,
UserHandle.USER_CURRENT);
// Constrain the backlight setting to [0.0f, 1.0f].
float backlightValue = MathUtils.constrain(backlightSetting,
PowerManager.BRIGHTNESS_MIN,
PowerManager.BRIGHTNESS_MAX);
// Interpolate the backlight value to nits.
float nits = mBacklightToNitsSpline.interpolate(backlightValue);
// Interpolate nits to a backlight value for a panel with enabled HBM.
float interpolatedHbmBacklightValue = mNitsToHbmBacklightSpline.interpolate(nits);
float gammaCorrectedHbmBacklightValue = (float) Math.pow(interpolatedHbmBacklightValue,
1.0f / DISPLAY_GAMMA);
float scrimOpacity = PowerManager.BRIGHTNESS_MAX - gammaCorrectedHbmBacklightValue;
// Interpolate the opacity value from [0.0f, 1.0f] to [0, 255].
return BrightnessSynchronizer.brightnessFloatToInt(scrimOpacity);
}
private void onFingerDown(int x, int y, float minor, float major) {
mView.setScrimAlpha(computeScrimOpacity());
try {
FileWriter fw = new FileWriter(mHbmPath);
fw.write(mHbmEnableCommand);
@@ -174,10 +254,41 @@ class UdfpsController {
// TODO(b/152419866): Use the UDFPS window type when it becomes available.
WindowManager.LayoutParams.TYPE_BOOT_PROGRESS,
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
| WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
PixelFormat.TRANSLUCENT);
lp.setTitle(TAG);
lp.windowAnimations = 0;
return lp;
}
private static float obtainDefaultBrightness(Context context) {
PowerManager powerManager = context.getSystemService(PowerManager.class);
if (powerManager == null) {
Log.e(TAG, "PowerManager is unavailable. Can't obtain default brightness.");
return 0f;
}
return MathUtils.constrain(powerManager.getBrightnessConstraint(
PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT), PowerManager.BRIGHTNESS_MIN,
PowerManager.BRIGHTNESS_MAX);
}
private static float[] toFloatArray(TypedArray array) {
final int n = array.length();
float[] vals = new float[n];
for (int i = 0; i < n; i++) {
vals[i] = array.getFloat(i, PowerManager.BRIGHTNESS_OFF_FLOAT);
}
array.recycle();
return vals;
}
private static float[] normalizeBacklightRange(int[] backlight) {
final int n = backlight.length;
float[] normalizedBacklight = new float[n];
for (int i = 0; i < n; i++) {
normalizedBacklight[i] = BrightnessSynchronizer.brightnessIntToFloat(backlight[i]);
}
return normalizedBacklight;
}
}

View File

@@ -79,7 +79,7 @@ public class UdfpsView extends View {
mScrimRect = new Rect();
mScrimPaint = new Paint(0 /* flags */);
mScrimPaint.setARGB(110 /* a */, 0 /* r */, 0 /* g */, 0 /* b */);
mScrimPaint.setColor(Color.BLACK);
mSensorRect = new RectF();
mSensorPaint = new Paint(0 /* flags */);
@@ -136,6 +136,10 @@ public class UdfpsView extends View {
&& y < (mSensorY + mSensorRadius * mSensorTouchAreaCoefficient);
}
void setScrimAlpha(int alpha) {
mScrimPaint.setAlpha(alpha);
}
boolean isFingerDown() {
return mIsFingerDown;
}