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

Commit 7923f0db authored by Shawn Lin's avatar Shawn Lin Committed by Android (Google) Code Review
Browse files

Merge "Support face auth animation for foldable devices" into main

parents e48319ab 9f0a677a
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.AuthController
import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
import com.android.systemui.common.shared.model.Position
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.doze.DozeMachine
@@ -71,6 +72,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
    private val testDispatcher = StandardTestDispatcher()
    private val testScope = TestScope(testDispatcher)
    private lateinit var systemClock: FakeSystemClock
    private lateinit var facePropertyRepository: FakeFacePropertyRepository

    private lateinit var underTest: KeyguardRepositoryImpl

@@ -78,6 +80,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        systemClock = FakeSystemClock()
        facePropertyRepository = FakeFacePropertyRepository()
        underTest =
            KeyguardRepositoryImpl(
                statusBarStateController,
@@ -89,6 +92,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
                mainDispatcher,
                testScope.backgroundScope,
                systemClock,
                facePropertyRepository,
            )
    }

@@ -482,10 +486,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
        testScope.runTest {
            val values = mutableListOf<Point?>()
            val job = underTest.faceSensorLocation.onEach(values::add).launchIn(this)

            val captor = argumentCaptor<AuthController.Callback>()
            runCurrent()
            verify(authController).addCallback(captor.capture())

            // An initial, null value should be initially emitted so that flows combined with this
            // one
@@ -500,8 +501,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
                    Point(250, 250),
                )
                .onEach {
                    whenever(authController.faceSensorLocation).thenReturn(it)
                    captor.value.onFaceSensorLocationChanged()
                    facePropertyRepository.setSensorLocation(it)
                    runCurrent()
                }
                .also { dispatchedSensorLocations ->
+11 −4
Original line number Diff line number Diff line
@@ -546,7 +546,7 @@
    <!-- Similar to config_frontBuiltInDisplayCutoutProtection but for inner display. -->
    <string translatable="false" name="config_innerBuiltInDisplayCutoutProtection"></string>

    <!-- ID for the camera of inner display that needs extra protection -->
    <!-- ID for the camera of inner display that needs extra protection. -->
    <string translatable="false" name="config_protectedInnerCameraId"></string>
    <!-- Physical ID for the camera of inner display that needs extra protection -->
    <string translatable="false" name="config_protectedInnerPhysicalCameraId"></string>
@@ -650,13 +650,20 @@
    <!-- Whether to use window background blur for the volume dialog. -->
    <bool name="config_volumeDialogUseBackgroundBlur">false</bool>

    <!-- The properties of the face auth camera in pixels -->
    <!-- The properties of the face auth front camera for outer display in pixels -->
    <integer-array name="config_face_auth_props">
        <!-- sensorLocationX -->
        <!-- sensorLocationY -->
        <!--sensorRadius -->
    </integer-array>

    <!-- The properties of the face auth front camera for inner display in pixels -->
    <integer-array name="config_inner_face_auth_props">
        <!-- sensorLocationX -->
        <!-- sensorLocationY -->
        <!--sensorRadius -->
    </integer-array>

    <!-- Overrides the behavior of the face unlock keyguard bypass setting:
         0 - Don't override the setting (default)
         1 - Override the setting to always bypass keyguard
+21 −19
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ import androidx.annotation.VisibleForTesting;

import com.android.internal.util.Preconditions;
import com.android.settingslib.Utils;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.data.repository.FacePropertyRepository;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.decor.CutoutDecorProviderFactory;
import com.android.systemui.decor.DebugRoundedCornerDelegate;
@@ -92,6 +92,7 @@ import com.android.systemui.statusbar.events.PrivacyDotViewController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.ThreadFactory;
import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.settings.SecureSettings;

import dalvik.annotation.optimization.NeverCompile;
@@ -131,8 +132,6 @@ public class ScreenDecorations implements
    };
    private final ScreenDecorationsLogger mLogger;

    private final AuthController mAuthController;

    private DisplayTracker mDisplayTracker;
    @VisibleForTesting
    protected boolean mIsRegistered;
@@ -183,6 +182,9 @@ public class ScreenDecorations implements
    private DisplayCutout mDisplayCutout;
    private boolean mPendingManualConfigUpdate;

    private FacePropertyRepository mFacePropertyRepository;
    private JavaAdapter mJavaAdapter;

    @VisibleForTesting
    protected void showCameraProtection(@NonNull Path protectionPath, @NonNull Rect bounds) {
        if (mFaceScanningFactory.shouldShowFaceScanningAnim()) {
@@ -330,7 +332,8 @@ public class ScreenDecorations implements
            PrivacyDotDecorProviderFactory dotFactory,
            FaceScanningProviderFactory faceScanningFactory,
            ScreenDecorationsLogger logger,
            AuthController authController) {
            FacePropertyRepository facePropertyRepository,
            JavaAdapter javaAdapter) {
        mContext = context;
        mSecureSettings = secureSettings;
        mCommandRegistry = commandRegistry;
@@ -342,21 +345,9 @@ public class ScreenDecorations implements
        mFaceScanningFactory = faceScanningFactory;
        mFaceScanningViewId = com.android.systemui.res.R.id.face_scanning_anim;
        mLogger = logger;
        mAuthController = authController;
    }


    private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
        @Override
        public void onFaceSensorLocationChanged() {
            mLogger.onSensorLocationChanged();
            if (mExecutor != null) {
                mExecutor.execute(
                        () -> updateOverlayProviderViews(
                                new Integer[]{mFaceScanningViewId}));
        mFacePropertyRepository = facePropertyRepository;
        mJavaAdapter = javaAdapter;
    }
        }
    };

    private final ScreenDecorCommand.Callback mScreenDecorCommandCallback = (cmd, pw) -> {
        // If we are exiting debug mode, we can set it (false) and bail, otherwise we will
@@ -407,7 +398,8 @@ public class ScreenDecorations implements
        mExecutor = mThreadFactory.buildDelayableExecutorOnHandler(mHandler);
        mExecutor.execute(this::startOnScreenDecorationsThread);
        mDotViewController.setUiExecutor(mExecutor);
        mAuthController.addCallback(mAuthControllerCallback);
        mJavaAdapter.alwaysCollectFlow(mFacePropertyRepository.getSensorLocation(),
                this::onFaceSensorLocationChanged);
        mCommandRegistry.registerCommand(ScreenDecorCommand.SCREEN_DECOR_CMD_NAME,
                () -> new ScreenDecorCommand(mScreenDecorCommandCallback));
    }
@@ -1320,6 +1312,16 @@ public class ScreenDecorations implements
        view.setLayoutParams(params);
    }

    @VisibleForTesting
    void onFaceSensorLocationChanged(Point location) {
        mLogger.onSensorLocationChanged();
        if (mExecutor != null) {
            mExecutor.execute(
                    () -> updateOverlayProviderViews(
                            new Integer[]{mFaceScanningViewId}));
        }
    }

    public static class DisplayCutoutView extends DisplayCutoutBaseView {
        final List<Rect> mBounds = new ArrayList();
        final Rect mBoundingRect = new Rect();
+0 −48
Original line number Diff line number Diff line
@@ -148,10 +148,6 @@ public class AuthController implements

    private final Display mDisplay;
    private float mScaleFactor = 1f;
    // sensor locations without any resolution scaling nor rotation adjustments:
    @Nullable private final Point mFaceSensorLocationDefault;
    // cached sensor locations:
    @Nullable private Point mFaceSensorLocation;
    @Nullable private Point mFingerprintSensorLocation;
    @Nullable private Rect mUdfpsBounds;
    private final Set<Callback> mCallbacks = new HashSet<>();
@@ -622,7 +618,6 @@ public class AuthController implements
        mScaleFactor = mUdfpsUtils.getScaleFactor(mCachedDisplayInfo);
        updateUdfpsLocation();
        updateFingerprintLocation();
        updateFaceLocation();
    }
    /**
     * @return where the fingerprint sensor exists in pixels in its natural orientation.
@@ -681,31 +676,6 @@ public class AuthController implements
        return mFpProps;
    }

    /**
     * @return where the face sensor exists in pixels in the current device orientation. Returns
     * null if no face sensor exists.
     */
    @Nullable public Point getFaceSensorLocation() {
        return mFaceSensorLocation;
    }

    private void updateFaceLocation() {
        if (mFaceProps == null || mFaceSensorLocationDefault == null) {
            mFaceSensorLocation = null;
        } else {
            mFaceSensorLocation = rotateToCurrentOrientation(
                    new Point(
                            (int) (mFaceSensorLocationDefault.x * mScaleFactor),
                            (int) (mFaceSensorLocationDefault.y * mScaleFactor)),
                    mCachedDisplayInfo
            );
        }

        for (final Callback cb : mCallbacks) {
            cb.onFaceSensorLocationChanged();
        }
    }

    /**
     * @param inOutPoint point on the display in pixels. Going in, represents the point
     *                   in the device's natural orientation. Going out, represents
@@ -821,17 +791,7 @@ public class AuthController implements
        mWakefulnessLifecycle = wakefulnessLifecycle;
        mPanelInteractionDetector = panelInteractionDetector;


        mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
        int[] faceAuthLocation = context.getResources().getIntArray(
                com.android.systemui.res.R.array.config_face_auth_props);
        if (faceAuthLocation == null || faceAuthLocation.length < 2) {
            mFaceSensorLocationDefault = null;
        } else {
            mFaceSensorLocationDefault = new Point(
                    faceAuthLocation[0],
                    faceAuthLocation[1]);
        }

        mDisplay = mContext.getDisplay();
        updateSensorLocations();
@@ -1359,8 +1319,6 @@ public class AuthController implements
        final AuthDialog dialog = mCurrentDialog;
        pw.println("  mCachedDisplayInfo=" + mCachedDisplayInfo);
        pw.println("  mScaleFactor=" + mScaleFactor);
        pw.println("  faceAuthSensorLocationDefault=" + mFaceSensorLocationDefault);
        pw.println("  faceAuthSensorLocation=" + getFaceSensorLocation());
        pw.println("  fingerprintSensorLocationInNaturalOrientation="
                + getFingerprintSensorLocationInNaturalOrientation());
        pw.println("  fingerprintSensorLocation=" + getFingerprintSensorLocation());
@@ -1434,11 +1392,5 @@ public class AuthController implements
         * {@link #onFingerprintLocationChanged}.
         */
        default void onUdfpsLocationChanged(UdfpsOverlayParams udfpsOverlayParams) {}

        /**
         * Called when the location of the face unlock sensor (typically the front facing camera)
         * changes. The location in pixels can change due to resolution changes.
         */
        default void onFaceSensorLocationChanged() {}
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.keyguard.logging.KeyguardLogger
import com.android.settingslib.Utils
import com.android.systemui.CoreStartable
import com.android.systemui.Flags.lightRevealMigration
import com.android.systemui.biometrics.data.repository.FacePropertyRepository
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
@@ -80,6 +81,7 @@ class AuthRippleController @Inject constructor(
    private val logger: KeyguardLogger,
    private val biometricUnlockController: BiometricUnlockController,
    private val lightRevealScrim: LightRevealScrim,
    private val facePropertyRepository: FacePropertyRepository,
    rippleView: AuthRippleView?
) :
    ViewController<AuthRippleView>(rippleView),
@@ -263,7 +265,7 @@ class AuthRippleController @Inject constructor(

    fun updateSensorLocation() {
        fingerprintSensorLocation = authController.fingerprintSensorLocation
        faceSensorLocation = authController.faceSensorLocation
        faceSensorLocation = facePropertyRepository.sensorLocation.value
    }

    private fun updateRippleColor() {
Loading