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

Commit d395057b authored by Grace Cheng's avatar Grace Cheng Committed by Android (Google) Code Review
Browse files

Merge "Disable timed dialog dismissal when a11y enabled" into 24D1-dev

parents 31cd136e 2b095632
Loading
Loading
Loading
Loading
+13 −1
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ import android.util.Log;
import android.view.View;
import android.view.View;
import android.view.Window;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;


import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
@@ -66,6 +67,7 @@ public class SideFpsEventHandler implements View.OnClickListener {
    private final int mDismissDialogTimeout;
    private final int mDismissDialogTimeout;
    @Nullable
    @Nullable
    private SideFpsToast mDialog;
    private SideFpsToast mDialog;
    private final AccessibilityManager mAccessibilityManager;
    private final Runnable mTurnOffDialog =
    private final Runnable mTurnOffDialog =
            () -> {
            () -> {
                dismissDialog("mTurnOffDialog");
                dismissDialog("mTurnOffDialog");
@@ -96,6 +98,7 @@ public class SideFpsEventHandler implements View.OnClickListener {
            DialogProvider provider) {
            DialogProvider provider) {
        mContext = context;
        mContext = context;
        mHandler = handler;
        mHandler = handler;
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
        mPowerManager = powerManager;
        mPowerManager = powerManager;
        mBiometricState = STATE_IDLE;
        mBiometricState = STATE_IDLE;
        mSideFpsEventHandlerReady = new AtomicBoolean(false);
        mSideFpsEventHandlerReady = new AtomicBoolean(false);
@@ -157,7 +160,9 @@ public class SideFpsEventHandler implements View.OnClickListener {
                                mHandler.removeCallbacks(mTurnOffDialog);
                                mHandler.removeCallbacks(mTurnOffDialog);
                            }
                            }
                            showDialog(eventTime, "Enroll Power Press");
                            showDialog(eventTime, "Enroll Power Press");
                            if (!mAccessibilityManager.isEnabled()) {
                                mHandler.postDelayed(mTurnOffDialog, mDismissDialogTimeout);
                                mHandler.postDelayed(mTurnOffDialog, mDismissDialogTimeout);
                            }
                        });
                        });
                return true;
                return true;
            case STATE_BP_AUTH:
            case STATE_BP_AUTH:
@@ -231,6 +236,10 @@ public class SideFpsEventHandler implements View.OnClickListener {
                                        public void onBiometricAction(
                                        public void onBiometricAction(
                                                @BiometricStateListener.Action int action) {
                                                @BiometricStateListener.Action int action) {
                                            Log.d(TAG, "onBiometricAction " + action);
                                            Log.d(TAG, "onBiometricAction " + action);
                                            if (mAccessibilityManager != null
                                                    && mAccessibilityManager.isEnabled()) {
                                                dismissDialog("mTurnOffDialog");
                                            }
                                        }
                                        }
                                    });
                                    });
                            mSideFpsEventHandlerReady.set(true);
                            mSideFpsEventHandlerReady.set(true);
@@ -256,6 +265,9 @@ public class SideFpsEventHandler implements View.OnClickListener {
        mLastPowerPressTime = time;
        mLastPowerPressTime = time;
        mDialog.show();
        mDialog.show();
        mDialog.setOnClickListener(this);
        mDialog.setOnClickListener(this);
        if (mAccessibilityManager.isEnabled()) {
            mDialog.addAccessibilityDelegate();
        }
    }
    }


    interface DialogProvider {
    interface DialogProvider {
+25 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.policy;
package com.android.server.policy;


import android.annotation.NonNull;
import android.app.Dialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Context;
import android.os.Bundle;
import android.os.Bundle;
@@ -23,6 +24,7 @@ import android.view.Gravity;
import android.view.View;
import android.view.View;
import android.view.Window;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.Button;


import com.android.internal.R;
import com.android.internal.R;
@@ -34,7 +36,6 @@ import com.android.internal.R;
 * This dialog is used by {@link SideFpsEventHandler}
 * This dialog is used by {@link SideFpsEventHandler}
 */
 */
public class SideFpsToast extends Dialog {
public class SideFpsToast extends Dialog {

    SideFpsToast(Context context) {
    SideFpsToast(Context context) {
        super(context);
        super(context);
    }
    }
@@ -66,4 +67,27 @@ public class SideFpsToast extends Dialog {
            turnOffScreen.setOnClickListener(listener);
            turnOffScreen.setOnClickListener(listener);
        }
        }
    }
    }

    /**
     * When accessibility mode is on, add AccessibilityDelegate to dismiss dialog when focus is
     * moved away from the dialog.
     */
    public void addAccessibilityDelegate() {
        final Button turnOffScreen = findViewById(R.id.turn_off_screen);
        if (turnOffScreen != null) {
            turnOffScreen.setAccessibilityDelegate(new View.AccessibilityDelegate() {
                @Override
                public void onInitializeAccessibilityEvent(@NonNull View host,
                        @NonNull AccessibilityEvent event) {
                    if (event.getEventType()
                            == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED
                            && isShowing()) {
                        dismiss();
                    }
                    super.onInitializeAccessibilityEvent(host, event);
                }
            });

        }
    }
}
}
+58 −9
Original line number Original line Diff line number Diff line
@@ -31,11 +31,13 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.os.Handler;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.test.TestLooper;
import android.os.test.TestLooper;
import android.testing.AndroidTestingRunner;
import android.testing.AndroidTestingRunner;
import android.testing.TestableContext;
import android.testing.TestableContext;
import android.testing.TestableResources;
import android.testing.TestableResources;
import android.view.Window;
import android.view.Window;
import android.view.accessibility.AccessibilityManager;


import androidx.test.InstrumentationRegistry;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;
@@ -48,7 +50,8 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;


import java.util.List;
import java.util.List;


@@ -71,10 +74,16 @@ public class SideFpsEventHandlerTest {


    private static final Integer AUTO_DISMISS_DIALOG = 500;
    private static final Integer AUTO_DISMISS_DIALOG = 500;


    @Rule
    public MockitoRule rule = MockitoJUnit.rule();

    @Rule
    @Rule
    public TestableContext mContext =
    public TestableContext mContext =
            new TestableContext(InstrumentationRegistry.getContext(), null);
            new TestableContext(InstrumentationRegistry.getContext(), null);


    private final AccessibilityManager mAccessibilityManager =
            mContext.getSystemService(AccessibilityManager.class);

    @Mock
    @Mock
    private PackageManager mPackageManager;
    private PackageManager mPackageManager;
    @Mock
    @Mock
@@ -89,9 +98,8 @@ public class SideFpsEventHandlerTest {
    private BiometricStateListener mBiometricStateListener;
    private BiometricStateListener mBiometricStateListener;


    @Before
    @Before
    public void setup() {
    public void setup() throws RemoteException {
        MockitoAnnotations.initMocks(this);
        disableAccessibility();

        mContext.addMockSystemService(PackageManager.class, mPackageManager);
        mContext.addMockSystemService(PackageManager.class, mPackageManager);
        mContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
        mContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
        TestableResources resources = mContext.getOrCreateTestableResources();
        TestableResources resources = mContext.getOrCreateTestableResources();
@@ -192,9 +200,8 @@ public class SideFpsEventHandlerTest {
    }
    }


    @Test
    @Test
    public void dialogDismissesAfterTime() throws Exception {
    public void dialogDismissesAfterTime_accessibilityDisabled() throws Exception {
        setupWithSensor(true /* hasSfps */, true /* initialized */);
        setupWithSensor(true /* hasSfps */, true /* initialized */);

        setBiometricState(BiometricStateListener.STATE_ENROLLING);
        setBiometricState(BiometricStateListener.STATE_ENROLLING);
        when(mDialog.isShowing()).thenReturn(true);
        when(mDialog.isShowing()).thenReturn(true);
        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
@@ -207,9 +214,23 @@ public class SideFpsEventHandlerTest {
    }
    }


    @Test
    @Test
    public void dialogDoesNotDismissOnSensorTouch() throws Exception {
    public void dialogDoesNotDismissAfterTime_accessibilityEnabled() throws Exception {
        enableAccessibility();
        setupWithSensor(true /* hasSfps */, true /* initialized */);
        setupWithSensor(true /* hasSfps */, true /* initialized */);
        setBiometricState(BiometricStateListener.STATE_ENROLLING);
        when(mDialog.isShowing()).thenReturn(true);
        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();

        mLooper.dispatchAll();
        verify(mDialog).show();
        mLooper.moveTimeForward(AUTO_DISMISS_DIALOG);
        mLooper.dispatchAll();
        verify(mDialog, never()).dismiss();
    }


    @Test
    public void dialogDoesNotDismissOnSensorTouch_accessibilityDisabled() throws Exception {
        setupWithSensor(true /* hasSfps */, true /* initialized */);
        setBiometricState(BiometricStateListener.STATE_ENROLLING);
        setBiometricState(BiometricStateListener.STATE_ENROLLING);
        when(mDialog.isShowing()).thenReturn(true);
        when(mDialog.isShowing()).thenReturn(true);
        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();
@@ -218,12 +239,26 @@ public class SideFpsEventHandlerTest {
        verify(mDialog).show();
        verify(mDialog).show();


        mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
        mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
        mLooper.moveTimeForward(AUTO_DISMISS_DIALOG - 1);
        mLooper.dispatchAll();
        mLooper.dispatchAll();

        verify(mDialog, never()).dismiss();
        verify(mDialog, never()).dismiss();
    }
    }


    @Test
    public void dialogDismissesOnSensorTouch_accessibilityEnabled() throws Exception {
        enableAccessibility();
        setupWithSensor(true /* hasSfps */, true /* initialized */);
        setBiometricState(BiometricStateListener.STATE_ENROLLING);
        when(mDialog.isShowing()).thenReturn(true);
        assertThat(mEventHandler.shouldConsumeSinglePress(80000L)).isTrue();

        mLooper.dispatchAll();
        verify(mDialog).show();

        mBiometricStateListener.onBiometricAction(BiometricStateListener.ACTION_SENSOR_TOUCH);
        mLooper.dispatchAll();
        verify(mDialog).dismiss();
    }

    private void setBiometricState(@BiometricStateListener.State int newState) {
    private void setBiometricState(@BiometricStateListener.State int newState) {
        if (mBiometricStateListener != null) {
        if (mBiometricStateListener != null) {
            mBiometricStateListener.onStateChanged(newState);
            mBiometricStateListener.onStateChanged(newState);
@@ -231,6 +266,20 @@ public class SideFpsEventHandlerTest {
        }
        }
    }
    }


    private void enableAccessibility() throws RemoteException {
        if (mAccessibilityManager != null) {
            mAccessibilityManager.getClient().setState(1);
            mLooper.dispatchAll();
        }
    }

    private void disableAccessibility() throws RemoteException {
        if (mAccessibilityManager != null) {
            mAccessibilityManager.getClient().setState(0);
            mLooper.dispatchAll();
        }
    }

    private void setupWithSensor(boolean hasSfps, boolean initialized) throws Exception {
    private void setupWithSensor(boolean hasSfps, boolean initialized) throws Exception {
        when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_FINGERPRINT)))
        when(mPackageManager.hasSystemFeature(eq(PackageManager.FEATURE_FINGERPRINT)))
                .thenReturn(true);
                .thenReturn(true);