Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
feat(focus-mvp-android-device): silence focus events after a recent o…
Browse files Browse the repository at this point in the history
…rientation change (#93)

* feat(focus-mvp-android-device): silence focus events after a recent orientation change

* use dateProvider
  • Loading branch information
waabid authored Apr 6, 2021
1 parent 3fa7f59 commit f5679ec
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ protected void onServiceConnected() {
LayoutParamGenerator layoutParamGenerator = new LayoutParamGenerator(this::getRealDisplayMetrics);
focusVisualizationCanvas = new FocusVisualizationCanvas(this);
focusVisualizer = new FocusVisualizer(new FocusVisualizerStyles(), focusVisualizationCanvas);
focusVisualizerController = new FocusVisualizerController(focusVisualizer, focusVisualizationStateManager, new UIThreadRunner(), windowManager, layoutParamGenerator, focusVisualizationCanvas);
focusVisualizerController = new FocusVisualizerController(focusVisualizer, focusVisualizationStateManager, new UIThreadRunner(), windowManager, layoutParamGenerator, focusVisualizationCanvas, new DateProvider());
accessibilityEventDispatcher = new AccessibilityEventDispatcher();
deviceOrientationHandler = new DeviceOrientationHandler(getResources().getConfiguration().orientation);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

package com.microsoft.accessibilityinsightsforandroidservice;

import java.util.Date;

public class DateProvider {
public Date get() {
return new Date();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.Date;

public class FocusVisualizerController {
private FocusVisualizer focusVisualizer;
Expand All @@ -15,27 +16,33 @@ public class FocusVisualizerController {
private LayoutParamGenerator layoutParamGenerator;
private FocusVisualizationCanvas focusVisualizationCanvas;
private AccessibilityNodeInfo lastEventSource;
private DateProvider dateProvider;
private Date lastOrientationChange;
private long maximumOrientationChangeDelay = 1000;

public FocusVisualizerController(
FocusVisualizer focusVisualizer,
FocusVisualizationStateManager focusVisualizationStateManager,
UIThreadRunner uiThreadRunner,
WindowManager windowManager,
LayoutParamGenerator layoutParamGenerator,
FocusVisualizationCanvas focusVisualizationCanvas) {
FocusVisualizationCanvas focusVisualizationCanvas,
DateProvider dateProvider) {
this.focusVisualizer = focusVisualizer;
this.focusVisualizationStateManager = focusVisualizationStateManager;
this.uiThreadRunner = uiThreadRunner;
this.windowManager = windowManager;
this.layoutParamGenerator = layoutParamGenerator;
this.focusVisualizationCanvas = focusVisualizationCanvas;
this.dateProvider = dateProvider;
this.focusVisualizationStateManager.subscribe(this::onFocusVisualizationStateChange);
this.lastOrientationChange = dateProvider.get();
}

public void onFocusEvent(AccessibilityEvent event) {
lastEventSource = event.getSource();

if (focusVisualizationStateManager.getState() == false) {
if (focusVisualizationStateManager.getState() == false
|| ignoreFocusEventDueToRecentOrientationChange()) {
return;
}

Expand All @@ -62,7 +69,7 @@ public void onOrientationChanged(Integer orientation) {
if (focusVisualizationStateManager.getState() == false) {
return;
}

lastOrientationChange = dateProvider.get();
windowManager.updateViewLayout(focusVisualizationCanvas, layoutParamGenerator.get());
focusVisualizer.resetVisualizations();
}
Expand All @@ -86,4 +93,12 @@ private void removeFocusVisualizationToScreen() {
focusVisualizer.resetVisualizations();
windowManager.removeView(focusVisualizationCanvas);
}

private boolean ignoreFocusEventDueToRecentOrientationChange() {
Date currentTime = dateProvider.get();
long cur = currentTime.getTime();
long last = lastOrientationChange.getTime();
long timeSinceLastOrientationChange = cur - last;
return timeSinceLastOrientationChange < maximumOrientationChangeDelay;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package com.microsoft.accessibilityinsightsforandroidservice;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -12,8 +13,7 @@
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.Date;
import java.util.function.Consumer;
import org.junit.Assert;
import org.junit.Before;
Expand All @@ -25,8 +25,6 @@
@RunWith(PowerMockRunner.class)
public class FocusVisualizerControllerTest {

private static final ScheduledExecutorService mainThread =
Executors.newSingleThreadScheduledExecutor();
@Mock FocusVisualizer focusVisualizerMock;
@Mock FocusVisualizationStateManager focusVisualizationStateManagerMock;
@Mock AccessibilityEvent accessibilityEventMock;
Expand All @@ -36,6 +34,9 @@ public class FocusVisualizerControllerTest {
@Mock FocusVisualizationCanvas focusVisualizationCanvas;
@Mock WindowManager.LayoutParams layoutParams;
@Mock AccessibilityNodeInfo accessibilityNodeInfo;
@Mock DateProvider dateProvider;
@Mock Date oldDateMock;
@Mock Date newDateMock;

Consumer<Boolean> listener;
FocusVisualizerController testSubject;
Expand All @@ -44,14 +45,16 @@ public class FocusVisualizerControllerTest {
public void prepare() {
when(layoutParamGenerator.get()).thenReturn(layoutParams);
listener = null;
when(dateProvider.get()).thenReturn(oldDateMock);
testSubject =
new FocusVisualizerController(
focusVisualizerMock,
focusVisualizationStateManagerMock,
uiThreadRunner,
windowManager,
layoutParamGenerator,
focusVisualizationCanvas);
focusVisualizationCanvas,
dateProvider);
}

@Test
Expand All @@ -67,9 +70,25 @@ public void onFocusEventDoesNotCallVisualizerIfStateIsFalse() {
}

@Test
public void onFocusEventCallsVisualizerIfStateIsTrue() {
public void onFocusEventDoesNotCallVisualizerIfOrientationChangedRecently() {
reset(dateProvider);
when(dateProvider.get()).thenReturn(newDateMock);
when(focusVisualizationStateManagerMock.getState()).thenReturn(true);
when(oldDateMock.getTime()).thenReturn((long) 500);
when(newDateMock.getTime()).thenReturn((long) 501);
testSubject.onFocusEvent(accessibilityEventMock);
verify(focusVisualizerMock, times(0)).addNewFocusedElement(accessibilityNodeInfo);
}

@Test
public void onFocusEventCallsVisualizerIfStateIsTrueAndOrientationHasNotChangedRecently()
throws Exception {
reset(dateProvider);
when(dateProvider.get()).thenReturn(newDateMock);
when(focusVisualizationStateManagerMock.getState()).thenReturn(true);
when(accessibilityEventMock.getSource()).thenReturn(accessibilityNodeInfo);
when(oldDateMock.getTime()).thenReturn((long) 500);
when(newDateMock.getTime()).thenReturn((long) 10000);
testSubject.onFocusEvent(accessibilityEventMock);
verify(focusVisualizerMock, times(1)).addNewFocusedElement(accessibilityNodeInfo);
}
Expand Down Expand Up @@ -145,7 +164,8 @@ public void onFocusVisualizationStateChangeToEnabledAddsVisualization() {
uiThreadRunner,
windowManager,
layoutParamGenerator,
focusVisualizationCanvas);
focusVisualizationCanvas,
dateProvider);

verify(windowManager).addView(focusVisualizationCanvas, layoutParams);
}
Expand Down Expand Up @@ -178,7 +198,8 @@ public void onFocusVisualizationStateChangeToEnabledAddsVisualizationWithLastEve
uiThreadRunner,
windowManager,
layoutParamGenerator,
focusVisualizationCanvas);
focusVisualizationCanvas,
dateProvider);

testSubject.onFocusEvent(accessibilityEventMock);
listener.accept(true);
Expand Down Expand Up @@ -214,7 +235,8 @@ public void onFocusVisualizationStateChangToDisabledRemovesVisualizations() {
uiThreadRunner,
windowManager,
layoutParamGenerator,
focusVisualizationCanvas);
focusVisualizationCanvas,
dateProvider);

verify(focusVisualizerMock).resetVisualizations();
}
Expand Down

0 comments on commit f5679ec

Please sign in to comment.