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

Commit c0d931d3 authored by Beverly's avatar Beverly
Browse files

Add tap target for when udfps is unavailable

tapping on the target will bring up the bouncer since UDFPS is
unavailable

Test: manual
Bug: 172050991
Change-Id: I8fafa2da174aec905ae0d9c4c19aff8907a4c67e
parent 2388cd52
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="oval">
    <solid android:color="#33FFFFFF" />
</shape>
 No newline at end of file
+24 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ 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.
  -->
<com.android.keyguard.DisabledUdfpsView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
    android:id="@+id/disabled_udfps_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/circle_white"
/>
+15 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ 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.
  -->
<com.android.systemui.biometrics.UdfpsView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+155 −0
Original line number Diff line number Diff line
/*
 * 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.keyguard;

import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;

import android.hardware.biometrics.BiometricSourceType;
import android.view.View;

import androidx.annotation.NonNull;

import com.android.systemui.Dumpable;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.ViewController;

import java.io.FileDescriptor;
import java.io.PrintWriter;

/**
 * Controls when to show the DisabledUdfpsView to unlock the device on the lockscreen.
 * If the device is not authenticated, the bouncer will show.
 *
 * This tap target will only show when:
 * - User has UDFPS enrolled
 * - UDFPS is currently unavailable see {@link KeyguardUpdateMonitor#shouldListenForUdfps}
 */
@SysUISingleton
public class DisabledUdfpsController extends ViewController<DisabledUdfpsView> implements Dumpable {
    @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    @NonNull private final KeyguardViewController mKeyguardViewController;
    @NonNull private final StatusBarStateController mStatusBarStateController;

    private boolean mIsDozing;
    private boolean mIsBouncerShowing;
    private boolean mIsKeyguardShowing;
    private boolean mRunningFPS;
    private boolean mAuthenticated;

    private boolean mShowButton;

    public DisabledUdfpsController(
            @NonNull DisabledUdfpsView view,
            @NonNull StatusBarStateController statusBarStateController,
            @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
            @NonNull AuthController authController,
            @NonNull KeyguardViewController keyguardViewController
    ) {
        super(view);
        mView.setOnClickListener(mOnClickListener);
        mView.setSensorProperties(authController.getUdfpsProps().get(0));

        mStatusBarStateController = statusBarStateController;
        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
        mKeyguardViewController = keyguardViewController;
    }

    @Override
    protected void onViewAttached() {
        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
        mIsBouncerShowing = mKeyguardViewController.isBouncerShowing();

        mStatusBarStateController.addCallback(mStatusBarStateListener);
        mIsKeyguardShowing = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
        mIsDozing = mStatusBarStateController.isDozing();
        mAuthenticated = false;
    }

    @Override
    protected void onViewDetached() {
        mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
        mStatusBarStateController.removeCallback(mStatusBarStateListener);
    }

    private void updateButtonVisibility() {
        mShowButton = !mAuthenticated && !mIsDozing && mIsKeyguardShowing
                && !mIsBouncerShowing && !mRunningFPS;
        if (mShowButton) {
            mView.setVisibility(View.VISIBLE);
        } else {
            mView.setVisibility(View.INVISIBLE);
        }
    }

    @Override
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("DisabledUdfpsController state:");
        pw.println("  mShowBouncerButton: " + mShowButton);
        pw.println("  mIsDozing: " + mIsDozing);
        pw.println("  mIsKeyguardShowing: " + mIsKeyguardShowing);
        pw.println("  mIsBouncerShowing: " + mIsBouncerShowing);
        pw.println("  mRunningFPS: " + mRunningFPS);
        pw.println("  mAuthenticated: " + mAuthenticated);
    }

    private final View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mKeyguardViewController.showBouncer(/* scrim */ true);
        }
    };

    private StatusBarStateController.StateListener mStatusBarStateListener =
            new StatusBarStateController.StateListener() {
                @Override
                public void onStateChanged(int newState) {
                    mIsKeyguardShowing = newState == StatusBarState.KEYGUARD;
                    updateButtonVisibility();
                }

                @Override
                public void onDozingChanged(boolean isDozing) {
                    mIsDozing = isDozing;
                    updateButtonVisibility();
                }
            };

    private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
            new KeyguardUpdateMonitorCallback() {
                @Override
                public void onKeyguardBouncerChanged(boolean bouncer) {
                    mIsBouncerShowing = bouncer;
                    updateButtonVisibility();
                }

                @Override
                public void onBiometricRunningStateChanged(boolean running,
                        BiometricSourceType biometricSourceType) {
                    mRunningFPS = running && biometricSourceType == FINGERPRINT;
                    updateButtonVisibility();
                }

                @Override
                public void onUserUnlocked() {
                    mAuthenticated = true;
                    updateButtonVisibility();
                }
            };
}
+89 −0
Original line number Diff line number Diff line
/*
 * 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.keyguard;

import android.annotation.NonNull;
import android.content.Context;
import android.graphics.RectF;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.util.AttributeSet;
import android.view.Surface;
import android.widget.Button;
import android.widget.FrameLayout;

/**
 * A full screen view with an oval target where the UDFPS sensor is.
 * Controlled by {@link DisabledUdfpsController}.
 */
public class DisabledUdfpsView extends Button {
    @NonNull private final RectF mSensorRect;
    @NonNull private final Context mContext;

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

    public DisabledUdfpsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mSensorRect = new RectF();
    }

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

    // 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.
        }

        setX(mSensorRect.left);
        setY(mSensorRect.top);
        setLayoutParams(new FrameLayout.LayoutParams(
                (int) (mSensorRect.right - mSensorRect.left),
                (int) (mSensorRect.bottom - mSensorRect.top)));
    }

    @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;
        updateSensorRect(h, w);
    }
}
Loading