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

Commit 224138c8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes Id6ec26ec,Ie0484267

* changes:
  Handle rotation in the UDFPS overlay
  Minor UdfpsView cleanup
parents ad50ae60 e0937537
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -565,6 +565,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
                    promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
                }

                if (mUdfpsController != null) {
                    mUdfpsController.onConfigurationChanged();
                }

                showDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
            }
        }
+40 −28
Original line number Diff line number Diff line
@@ -75,15 +75,15 @@ class UdfpsController implements DozeReceiver {
    private static final float DISPLAY_GAMMA = 2.2f;
    private static final long AOD_INTERRUPT_TIMEOUT_MILLIS = 1000;

    private final Context mContext;
    private final FingerprintManager mFingerprintManager;
    // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
    // sensors, this, in addition to a lot of the code here, will be updated.
    @VisibleForTesting
    final FingerprintSensorPropertiesInternal mSensorProps;
    private final WindowManager mWindowManager;
    private final SystemSettings mSystemSettings;
    private final DelayableExecutor mFgExecutor;
    private final WindowManager.LayoutParams mLayoutParams;
    // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
    // sensors, this, in addition to a lot of the code here, will be updated.
    @VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
    private final WindowManager.LayoutParams mCoreLayoutParams;
    private final UdfpsView mView;
    // Debugfs path to control the high-brightness mode.
    private final String mHbmPath;
@@ -171,18 +171,29 @@ class UdfpsController implements DozeReceiver {
            SystemSettings systemSettings,
            @NonNull StatusBarStateController statusBarStateController,
            @Main DelayableExecutor fgExecutor) {
        mContext = context;
        // The fingerprint manager is queried for UDFPS before this class is constructed, so the
        // fingerprint manager should never be null.
        mFingerprintManager = checkNotNull(fingerprintManager);
        mWindowManager = windowManager;
        mSystemSettings = systemSettings;
        mFgExecutor = fgExecutor;
        mLayoutParams = createLayoutParams(context);

        mSensorProps = findFirstUdfps();
        // At least one UDFPS sensor exists
        checkArgument(mSensorProps != null);

        mCoreLayoutParams = new WindowManager.LayoutParams(
                // 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_LAYOUT_INSET_DECOR
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                PixelFormat.TRANSLUCENT);
        mCoreLayoutParams.setTitle(TAG);
        mCoreLayoutParams.setFitInsetsTypes(0);

        mView = (UdfpsView) inflater.inflate(R.layout.udfps_view, null, false);
        mView.setSensorProperties(mSensorProps);

@@ -266,12 +277,34 @@ class UdfpsController implements DozeReceiver {
        }
    }

    private WindowManager.LayoutParams computeLayoutParams() {
        Point p = new Point();
        // Gets the size based on the current rotation of the display.
        mContext.getDisplay().getRealSize(p);
        mCoreLayoutParams.width = p.x;
        mCoreLayoutParams.x = p.x;
        mCoreLayoutParams.height = p.y;
        mCoreLayoutParams.y = p.y;
        return mCoreLayoutParams;
    }

    void onConfigurationChanged() {
        // When the configuration changes it's almost always necessary to destroy and re-create
        // the overlay's window to pass it the new LayoutParams.
        // Hiding the overlay will destroy its window. It's safe to hide the overlay regardless
        // of whether it is already hidden.
        hideUdfpsOverlay();
        // If the overlay needs to be shown, this will re-create and show the overlay with the
        // updated LayoutParams. Otherwise, the overlay will remain hidden.
        updateOverlay();
    }

    private void showUdfpsOverlay() {
        mFgExecutor.execute(() -> {
            if (!mIsOverlayShowing) {
                try {
                    Log.v(TAG, "showUdfpsOverlay | adding window");
                    mWindowManager.addView(mView, mLayoutParams);
                    mWindowManager.addView(mView, computeLayoutParams());
                    mIsOverlayShowing = true;
                    mView.setOnTouchListener(mOnTouchListener);
                } catch (RuntimeException e) {
@@ -394,27 +427,6 @@ class UdfpsController implements DozeReceiver {
        }
    }

    private static WindowManager.LayoutParams createLayoutParams(Context context) {
        Point displaySize = new Point();
        context.getDisplay().getRealSize(displaySize);
        // TODO(b/160025856): move to the "dump" method.
        Log.v(TAG, "createLayoutParams | display size: " + displaySize.x + "x"
                + displaySize.y);
        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                displaySize.x,
                displaySize.y,
                // 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_LAYOUT_INSET_DECOR
                        | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
                PixelFormat.TRANSLUCENT);
        lp.setTitle(TAG);
        lp.setFitInsetsTypes(0);
        return lp;
    }

    private static float obtainDefaultBrightness(PowerManager powerManager) {
        if (powerManager == null) {
            Log.e(TAG, "PowerManager is unavailable. Can't obtain default brightness.");
+74 −30
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.biometrics;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
@@ -31,6 +32,7 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
import android.view.Surface;
import android.view.View;
import android.view.ViewTreeObserver;

@@ -51,20 +53,26 @@ public class UdfpsView extends View implements DozeReceiver,

    private static final int DEBUG_TEXT_SIZE_PX = 32;

    private final Rect mScrimRect;
    private final Paint mScrimPaint;
    private final Paint mDebugTextPaint;
    @NonNull private final Rect mScrimRect;
    @NonNull private final Paint mScrimPaint;
    @NonNull private final Paint mDebugTextPaint;

    private final RectF mSensorRect;
    private final Paint mSensorPaint;
    @NonNull private final RectF mSensorRect;
    @NonNull private final Paint mSensorPaint;
    private final float mSensorTouchAreaCoefficient;
    private final int mMaxBurnInOffsetX;
    private final int mMaxBurnInOffsetY;

    private final Rect mTouchableRegion;
    private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener;
    // Stores rounded up values from mSensorRect. Necessary for APIs that only take Rect (not RecF).
    @NonNull private final Rect mTouchableRegion;
    // mInsetsListener is used to set the touchable region for our window. Our window covers the
    // whole screen, and by default its touchable region is the whole screen. We use
    // mInsetsListener to restrict the touchable region and allow the touches outside of the sensor
    // to propagate to the rest of the UI.
    @NonNull private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener;

    @NonNull private FingerprintSensorPropertiesInternal mProps;
    // Used to obtain the sensor location.
    @NonNull private FingerprintSensorPropertiesInternal mSensorProps;

    // AOD anti-burn-in offsets
    private float mInterpolatedDarkAmount;
@@ -72,8 +80,8 @@ public class UdfpsView extends View implements DozeReceiver,
    private float mBurnInOffsetY;

    private boolean mIsScrimShowing;
    private boolean mHbmSupported;
    private String mDebugMessage;
    private boolean mIsHbmSupported;
    @Nullable private String mDebugMessage;

    public UdfpsView(Context context, AttributeSet attrs) {
        super(context, attrs);
@@ -107,7 +115,6 @@ public class UdfpsView extends View implements DozeReceiver,
        mSensorPaint.setStyle(Paint.Style.STROKE);
        mSensorPaint.setStrokeWidth(SENSOR_OUTLINE_WIDTH);
        mSensorPaint.setShadowLayer(SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK);
        mSensorPaint.setAntiAlias(true);

        mDebugTextPaint = new Paint();
        mDebugTextPaint.setAntiAlias(true);
@@ -115,6 +122,8 @@ public class UdfpsView extends View implements DozeReceiver,
        mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX);

        mTouchableRegion = new Rect();
        // When the device is rotated, it's important that mTouchableRegion is updated before
        // this listener is called. This listener is usually called shortly after onLayout.
        mInsetsListener = internalInsetsInfo -> {
            internalInsetsInfo.setTouchableInsets(
                    ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
@@ -125,7 +134,7 @@ public class UdfpsView extends View implements DozeReceiver,
    }

    void setSensorProperties(@NonNull FingerprintSensorPropertiesInternal properties) {
        mProps = properties;
        mSensorProps = properties;
    }

    @Override
@@ -151,22 +160,50 @@ public class UdfpsView extends View implements DozeReceiver,
        postInvalidate();
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.v(TAG, "onAttachedToWindow");
    // The "h" and "w" are the display's height and width relative to its current rotation.
    private void updateSensorRect(int h, int w) {
        // mSensorProps coordinates assume portrait mode.
        mSensorRect.set(mSensorProps.sensorLocationX - mSensorProps.sensorRadius,
                mSensorProps.sensorLocationY - mSensorProps.sensorRadius,
                mSensorProps.sensorLocationX + mSensorProps.sensorRadius,
                mSensorProps.sensorLocationY + mSensorProps.sensorRadius);

        // Transform mSensorRect if the device is in landscape mode.
        switch (mContext.getDisplay().getRotation()) {
            case Surface.ROTATION_90:
                mSensorRect.set(mSensorRect.top, h - mSensorRect.right, mSensorRect.bottom,
                        h - mSensorRect.left);
                break;
            case Surface.ROTATION_270:
                mSensorRect.set(w - mSensorRect.bottom, mSensorRect.left, w - mSensorRect.top,
                        mSensorRect.right);
                break;
            default:
                // Do nothing to stay in portrait mode.
        }
    }

        final int h = getLayoutParams().height;
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        // Always re-compute the layout regardless of whether "changed" is true. It is usually false
        // when the device goes from landscape to seascape and vice versa, but mSensorRect and
        // its dependencies need to be recalculated to stay at the same physical location on the
        // screen.
        final int w = getLayoutParams().width;
        final int h = getLayoutParams().height;
        mScrimRect.set(0 /* left */, 0 /* top */, w, h);
        mSensorRect.set(mProps.sensorLocationX - mProps.sensorRadius,
                mProps.sensorLocationY - mProps.sensorRadius,
                mProps.sensorLocationX + mProps.sensorRadius,
                mProps.sensorLocationY + mProps.sensorRadius);

        // Sets mTouchableRegion with rounded up values from mSensorRect.
        updateSensorRect(h, w);
        // Update mTouchableRegion with the rounded up values from mSensorRect. After "onLayout"
        // is finished, mTouchableRegion will be used by mInsetsListener to compute the touch
        // insets.
        mSensorRect.roundOut(mTouchableRegion);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        Log.v(TAG, "onAttachedToWindow");
        getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
    }

@@ -181,7 +218,7 @@ public class UdfpsView extends View implements DozeReceiver,
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mIsScrimShowing && mHbmSupported) {
        if (mIsScrimShowing && mIsHbmSupported) {
            // Only draw the scrim if HBM is supported.
            canvas.drawRect(mScrimRect, mScrimPaint);
        }
@@ -200,8 +237,8 @@ public class UdfpsView extends View implements DozeReceiver,
        return new RectF(mSensorRect);
    }

    void setHbmSupported(boolean hbmSupported) {
        mHbmSupported = hbmSupported;
    void setHbmSupported(boolean value) {
        mIsHbmSupported = value;
    }

    void setDebugMessage(String message) {
@@ -210,10 +247,17 @@ public class UdfpsView extends View implements DozeReceiver,
    }

    boolean isValidTouch(float x, float y, float pressure) {
        return x > (mProps.sensorLocationX - mProps.sensorRadius * mSensorTouchAreaCoefficient)
                && x < (mProps.sensorLocationX + mProps.sensorRadius * mSensorTouchAreaCoefficient)
                && y > (mProps.sensorLocationY - mProps.sensorRadius * mSensorTouchAreaCoefficient)
                && y < (mProps.sensorLocationY + mProps.sensorRadius * mSensorTouchAreaCoefficient);
        // The X and Y coordinates of the sensor's center.
        final float cx = mSensorRect.centerX();
        final float cy = mSensorRect.centerY();
        // Radii along the X and Y axes.
        final float rx = (mSensorRect.right - mSensorRect.left) / 2.0f;
        final float ry = (mSensorRect.bottom - mSensorRect.top) / 2.0f;

        return x > (cx - rx * mSensorTouchAreaCoefficient)
                && x < (cx + rx * mSensorTouchAreaCoefficient)
                && y > (cy - ry * mSensorTouchAreaCoefficient)
                && y < (cy + ry * mSensorTouchAreaCoefficient);
    }

    void setScrimAlpha(int alpha) {