Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 866b26df authored by cjybyjk's avatar cjybyjk Committed by Bruno Martins
Browse files

SystemUI: Add UDFPS framework dimming support



Author: cjybyjk <cjybyjk@zjnu.edu.cn>
Date: Wed, 13 Apr 2022 09:29:41 +0000

   udfps: Implement framework dimming support

Author: bengris32 <bengris32@protonmail.ch>
Date: Sun, 17 Sep 2023 11:31:02 +0530

   udfps: Add delay for framework dimming support

   Co-authored-by: default avatarPranav Vashi <neobuddy89@gmail.com>

Author: Thomas DE SA <desathomas@gmail.com>
Date: Sun, 22 Oct 2023 17:46:42 +0200

   udfps: Apply dim layer in configureDisplay() callback

   Ensure that the timing of the dimming layer application is as close
   as possible to the timing of the illumination. Too early and you get
   the screen going dark for a few frames, too late and the screen gets
   bright for a few frames.

Change-Id: Icf84cc61e2448840944e50d3b5c48c9f24a7f9f5
parent a4ab736a
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -18,6 +18,42 @@
    <!-- Color of the UDFPS pressed view -->
    <color name="config_udfpsColor">#ffffffff</color>

    <!-- Whether to enable framework dimming for UDFPS -->
    <bool name="config_udfpsFrameworkDimming">false</bool>

    <!-- Array of brightness-alpha LUT for framework dimming -->
    <string-array name="config_udfpsDimmingBrightnessAlphaArray" translatable="false">
          <!-- Example:
          <item>0,255</item>
          <item>1,234</item>
          <item>3,227</item>
          <item>8,208</item>
          <item>16,192</item>
          <item>27,176</item>
          <item>41,160</item>
          <item>61,144</item>
          <item>80,128</item>
          <item>104,112</item>
          <item>130,96</item>
          <item>158,80</item>
          <item>188,64</item>
          <item>221,48</item>
          <item>250,36</item>
          <item>255,33</item>
          -->
    </string-array>

    <!-- Brightness range min for UDFPS dimming -->
    <integer name="config_udfpsDimmingBrightnessMin">0</integer>

    <!-- Brightness range max for UDFPS dimming -->
    <integer name="config_udfpsDimmingBrightnessMax">0</integer>

    <!-- The amount of delay to add when disabling the dimming.
         This is used to prevent flickers due to the dimming being disabled
         before the screen has had chance to switch out of HBM mode -->
    <integer name="config_udfpsDimmingDisableDelay">0</integer>

    <!-- Doze: does the double tap sensor need a proximity check? -->
    <bool name="doze_double_tap_proximity_check">false</bool>

+82 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import android.os.Process;
import android.os.Trace;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.provider.Settings;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
@@ -220,6 +221,9 @@ public class UdfpsController implements DozeReceiver, Dumpable {
    private boolean mAttemptedToDismissKeyguard;
    private final Set<Callback> mCallbacks = new HashSet<>();

    private boolean mUseFrameworkDimming;
    private int[][] mBrightnessAlphaArray;

    @VisibleForTesting
    public static final VibrationAttributes UDFPS_VIBRATION_ATTRIBUTES =
            new VibrationAttributes.Builder()
@@ -924,6 +928,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {
        final UdfpsOverlayController mUdfpsOverlayController = new UdfpsOverlayController();
        mFingerprintManager.setUdfpsOverlayController(mUdfpsOverlayController);

        initUdfpsFrameworkDimming();

        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        context.registerReceiver(mBroadcastReceiver, filter,
@@ -1140,6 +1146,64 @@ public class UdfpsController implements DozeReceiver, Dumpable {
        return mSensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
    }

    private void initUdfpsFrameworkDimming() {
        mUseFrameworkDimming = mContext.getResources().getBoolean(
                com.android.systemui.R.bool.config_udfpsFrameworkDimming);

        if (mUseFrameworkDimming) {
            String[] array = mContext.getResources().getStringArray(
                    com.android.systemui.R.array.config_udfpsDimmingBrightnessAlphaArray);
            mBrightnessAlphaArray = new int[array.length][2];
            for (int i = 0; i < array.length; i++) {
                String[] s = array[i].split(",");
                mBrightnessAlphaArray[i][0] = Integer.parseInt(s[0]);
                mBrightnessAlphaArray[i][1] = Integer.parseInt(s[1]);
            }
        }
    }

    private static int interpolate(int x, int xa, int xb, int ya, int yb) {
        return ya - (ya - yb) * (x - xa) / (xb - xa);
    }

    private int getBrightness() {
        int brightness = Settings.System.getInt(mContext.getContentResolver(),
                Settings.System.SCREEN_BRIGHTNESS, 100);
        // Since the brightness is taken from the system settings, we need to interpolate it
        final int brightnessMin = mContext.getResources().getInteger(
                com.android.systemui.R.integer.config_udfpsDimmingBrightnessMin);
        final int brightnessMax = mContext.getResources().getInteger(
                com.android.systemui.R.integer.config_udfpsDimmingBrightnessMax);
        if (brightnessMax > 0) {
            brightness = interpolate(brightness, 0, 255, brightnessMin, brightnessMax);
        }
        return brightness;
    }

    private void updateViewDimAmount() {
        if (mOverlay == null || !mUseFrameworkDimming) {
            return;
        } else if (isFingerDown()) {
            int curBrightness = getBrightness();
            int i, dimAmount;
            for (i = 0; i < mBrightnessAlphaArray.length; i++) {
                if (mBrightnessAlphaArray[i][0] >= curBrightness) break;
            }
            if (i == 0) {
                dimAmount = mBrightnessAlphaArray[i][1];
            } else if (i == mBrightnessAlphaArray.length) {
                dimAmount = mBrightnessAlphaArray[i-1][1];
            } else {
                dimAmount = interpolate(curBrightness,
                        mBrightnessAlphaArray[i][0], mBrightnessAlphaArray[i-1][0],
                        mBrightnessAlphaArray[i][1], mBrightnessAlphaArray[i-1][1]);
            }
            mOverlay.setDimAmount(dimAmount / 255.0f);
        } else {
            mOverlay.setDimAmount(0.0f);
        }
    }

    public boolean isFingerDown() {
        return mOnFingerDown;
    }
@@ -1155,6 +1219,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
                    mSensorProps.sensorId);
            mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE);
        }
        updateViewDimAmount();
    }

    private void onFingerDown(
@@ -1304,6 +1369,23 @@ public class UdfpsController implements DozeReceiver, Dumpable {
            unconfigureDisplay(view);
        }
        cancelAodSendFingerUpAction();

        // Add a delay to ensure that the dim amount is updated after the display has had chance
        // to switch out of HBM mode. The delay, in ms is stored in config_udfpsDimmingDisableDelay.
        // If the delay is 0, the dim amount will be updated immediately.
        final int delay = mContext.getResources().getInteger(
                com.android.systemui.R.integer.config_udfpsDimmingDisableDelay);
        if (delay > 0) {
            mFgExecutor.executeDelayed(() -> {
                // A race condition exists where the overlay is destroyed before the dim amount
                // is updated. This check ensures that the overlay is still valid.
                if (mOverlay != null && mOverlay.matchesRequestId(requestId)) {
                    updateViewDimAmount();
                }
            }, delay);
        } else {
            updateViewDimAmount();
        }
    }

    /**
+9 −0
Original line number Diff line number Diff line
@@ -133,8 +133,10 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
        layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
        flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or
                WindowManager.LayoutParams.FLAG_DIM_BEHIND or
                WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
        privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
        dimAmount = 0.0f
        // Avoid announcing window title.
        accessibilityTitle = " "

@@ -143,6 +145,13 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        }
    }

    var dimAmount
        get() = coreLayoutParams.dimAmount
        set(value) {
            coreLayoutParams.dimAmount = value
            windowManager.updateViewLayout(overlayView, coreLayoutParams)
        }

    /** If the overlay is currently showing. */
    val isShowing: Boolean
        get() = overlayView != null