Loading core/java/com/android/internal/accessibility/util/AccessibilityUtils.java +15 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,21 @@ public final class AccessibilityUtils { @VisibleForTesting public static final String MENU_SERVICE_RELATIVE_CLASS_NAME = ".AccessibilityMenuService"; /** * The delay time in milliseconds for showing the magnification button. * @hide */ public static final long MAGNIFICATION_SHOW_BUTTON_DELAY_MS = 300; /** * The interval in milliseconds for throttling UI changes and reduce IPC to show/hide the * magnification mode switch button. It's set to be the same as * {@link #MAGNIFICATION_SHOW_BUTTON_DELAY_MS} so that users won't notice a delay. * @hide */ public static final long MAGNIFICATION_HANDLE_UI_CHANGE_INTERVAL_MS = MAGNIFICATION_SHOW_BUTTON_DELAY_MS; /** * {@link ComponentName} for the Accessibility Menu {@link AccessibilityService} as provided * inside the system build, used for automatic migration to this version of the service. Loading packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java +2 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import android.window.InputTransferToken; import androidx.annotation.NonNull; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.LauncherProxyService; Loading Loading @@ -72,7 +73,6 @@ import javax.inject.Inject; public class MagnificationImpl implements Magnification, CommandQueue.Callbacks { private static final String TAG = "Magnification"; @VisibleForTesting static final int DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS = 300; private static final int MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL = 1; private final ModeSwitchesController mModeSwitchesController; Loading Loading @@ -429,7 +429,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks mHandler.sendMessageDelayed( mHandler.obtainMessage( MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL, displayId, magnificationMode), DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS); AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS); } @MainThread Loading packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java +8 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.systemui.accessibility; import static com.android.systemui.accessibility.MagnificationImpl.DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; Loading @@ -44,6 +42,7 @@ import android.view.accessibility.IRemoteMagnificationAnimationCallback; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.systemui.LauncherProxyService; import com.android.systemui.SysuiTestCase; import com.android.systemui.model.SysUiState; Loading Loading @@ -200,10 +199,10 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // showMagnificationButton request to Magnification. processAllPendingMessages(); // The delayed message would be processed after DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS. // So call this processAllPendingMessages with a timeout to verify the showButton // will be called. int timeout = DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100; // The delayed message would be processed after // AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS. So call this // processAllPendingMessages with a timeout to verify the showButton will be called. long timeout = AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS + 100; processAllPendingMessages(timeout); verify(mModeSwitchesController).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); Loading @@ -222,7 +221,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // The isMagnificationSettingsShowing will be checked after timeout, so // process all message after a timeout here to verify the showButton will not be called. processAllPendingMessages(DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100); processAllPendingMessages(AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS + 100); verify(mModeSwitchesController, never()).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } Loading @@ -249,7 +248,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // Call this processAllPendingMessages with a timeout to ensure the delayed show button // message should be removed and thus the showButton will not be called after timeout. int timeout = DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100; long timeout = AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS + 100; processAllPendingMessages(/* timeForwardMs= */ timeout); verify(mModeSwitchesController, never()).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); Loading Loading @@ -281,7 +280,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { processAllPendingMessages(/* timeForwardMs=*/ 0); } private void processAllPendingMessages(int timeForwardMs) { private void processAllPendingMessages(long timeForwardMs) { if (timeForwardMs > 0) { mTestableLooper.moveTimeForward(timeForwardMs); } Loading services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +10 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ import android.view.ViewConfiguration; import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.function.pooled.PooledLambda; Loading Loading @@ -125,6 +126,7 @@ public class MagnificationController implements MagnificationConnectionManager.C // in multiple directions at once (for example, up + left), tracking last // panned time ensures that panning doesn't occur too frequently. private long mLastPannedTime = 0; private long mLastMouseMoveTriggeredUiChangeTime = 0; private boolean mRepeatKeysEnabled = true; private @ZoomDirection int mActiveZoomDirection = ZOOM_DIRECTION_IN; Loading Loading @@ -386,16 +388,24 @@ public class MagnificationController implements MagnificationConnectionManager.C @Override public void onTouchInteractionStart(int displayId, int mode) { // TODO(435498747): Add throttling for touch similarly to mouse events. handleUserInteractionChanged(displayId, mode); } @Override public void onTouchInteractionEnd(int displayId, int mode) { // TODO(435498747): Add throttling for touch similarly to mouse events. handleUserInteractionChanged(displayId, mode); } @Override public void onMouseMove(int displayId, int mode) { final long currentTime = mSystemClock.uptimeMillis(); if (currentTime - mLastMouseMoveTriggeredUiChangeTime < AccessibilityUtils.MAGNIFICATION_HANDLE_UI_CHANGE_INTERVAL_MS) { return; } mLastMouseMoveTriggeredUiChangeTime = currentTime; handleUserInteractionChanged(displayId, mode); } Loading services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +42 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.floatThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; Loading Loading @@ -81,6 +82,7 @@ import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; Loading Loading @@ -2192,6 +2194,46 @@ public class MagnificationControllerTest { eq(TEST_DISPLAY)); } @Test public void onMouseMove_withThrottle_shouldRateLimit() throws RemoteException { mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); setMagnificationEnabled(MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // The first call should go through and trigger a UI update. mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // Subsequent calls within the throttle period should be ignored. mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager, never()).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); } @Test public void onMouseMove_withThrottle_shouldNotRateLimitAfterDelay() throws RemoteException { mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); setMagnificationEnabled(MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // The first call should go through and trigger a UI update. mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // Advance time past the throttle period. The next call should now go through. mSystemClock.advanceTime(AccessibilityUtils.MAGNIFICATION_HANDLE_UI_CHANGE_INTERVAL_MS + 1); mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); } @Test public void enableWindowMode_showMagnificationButton() throws RemoteException { Loading Loading
core/java/com/android/internal/accessibility/util/AccessibilityUtils.java +15 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,21 @@ public final class AccessibilityUtils { @VisibleForTesting public static final String MENU_SERVICE_RELATIVE_CLASS_NAME = ".AccessibilityMenuService"; /** * The delay time in milliseconds for showing the magnification button. * @hide */ public static final long MAGNIFICATION_SHOW_BUTTON_DELAY_MS = 300; /** * The interval in milliseconds for throttling UI changes and reduce IPC to show/hide the * magnification mode switch button. It's set to be the same as * {@link #MAGNIFICATION_SHOW_BUTTON_DELAY_MS} so that users won't notice a delay. * @hide */ public static final long MAGNIFICATION_HANDLE_UI_CHANGE_INTERVAL_MS = MAGNIFICATION_SHOW_BUTTON_DELAY_MS; /** * {@link ComponentName} for the Accessibility Menu {@link AccessibilityService} as provided * inside the system build, used for automatic migration to this version of the service. Loading
packages/SystemUI/src/com/android/systemui/accessibility/MagnificationImpl.java +2 −2 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import android.window.InputTransferToken; import androidx.annotation.NonNull; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.LauncherProxyService; Loading Loading @@ -72,7 +73,6 @@ import javax.inject.Inject; public class MagnificationImpl implements Magnification, CommandQueue.Callbacks { private static final String TAG = "Magnification"; @VisibleForTesting static final int DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS = 300; private static final int MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL = 1; private final ModeSwitchesController mModeSwitchesController; Loading Loading @@ -429,7 +429,7 @@ public class MagnificationImpl implements Magnification, CommandQueue.Callbacks mHandler.sendMessageDelayed( mHandler.obtainMessage( MSG_SHOW_MAGNIFICATION_BUTTON_INTERNAL, displayId, magnificationMode), DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS); AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS); } @MainThread Loading
packages/SystemUI/tests/src/com/android/systemui/accessibility/IMagnificationConnectionTest.java +8 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.systemui.accessibility; import static com.android.systemui.accessibility.MagnificationImpl.DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; Loading @@ -44,6 +42,7 @@ import android.view.accessibility.IRemoteMagnificationAnimationCallback; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.systemui.LauncherProxyService; import com.android.systemui.SysuiTestCase; import com.android.systemui.model.SysUiState; Loading Loading @@ -200,10 +199,10 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // showMagnificationButton request to Magnification. processAllPendingMessages(); // The delayed message would be processed after DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS. // So call this processAllPendingMessages with a timeout to verify the showButton // will be called. int timeout = DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100; // The delayed message would be processed after // AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS. So call this // processAllPendingMessages with a timeout to verify the showButton will be called. long timeout = AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS + 100; processAllPendingMessages(timeout); verify(mModeSwitchesController).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); Loading @@ -222,7 +221,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // The isMagnificationSettingsShowing will be checked after timeout, so // process all message after a timeout here to verify the showButton will not be called. processAllPendingMessages(DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100); processAllPendingMessages(AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS + 100); verify(mModeSwitchesController, never()).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); } Loading @@ -249,7 +248,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { // Call this processAllPendingMessages with a timeout to ensure the delayed show button // message should be removed and thus the showButton will not be called after timeout. int timeout = DELAY_SHOW_MAGNIFICATION_TIMEOUT_MS + 100; long timeout = AccessibilityUtils.MAGNIFICATION_SHOW_BUTTON_DELAY_MS + 100; processAllPendingMessages(/* timeForwardMs= */ timeout); verify(mModeSwitchesController, never()).showButton(TEST_DISPLAY, Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); Loading Loading @@ -281,7 +280,7 @@ public class IMagnificationConnectionTest extends SysuiTestCase { processAllPendingMessages(/* timeForwardMs=*/ 0); } private void processAllPendingMessages(int timeForwardMs) { private void processAllPendingMessages(long timeForwardMs) { if (timeForwardMs > 0) { mTestableLooper.moveTimeForward(timeForwardMs); } Loading
services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +10 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ import android.view.ViewConfiguration; import android.view.accessibility.MagnificationAnimationCallback; import com.android.internal.accessibility.util.AccessibilityStatsLogUtils; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.function.pooled.PooledLambda; Loading Loading @@ -125,6 +126,7 @@ public class MagnificationController implements MagnificationConnectionManager.C // in multiple directions at once (for example, up + left), tracking last // panned time ensures that panning doesn't occur too frequently. private long mLastPannedTime = 0; private long mLastMouseMoveTriggeredUiChangeTime = 0; private boolean mRepeatKeysEnabled = true; private @ZoomDirection int mActiveZoomDirection = ZOOM_DIRECTION_IN; Loading Loading @@ -386,16 +388,24 @@ public class MagnificationController implements MagnificationConnectionManager.C @Override public void onTouchInteractionStart(int displayId, int mode) { // TODO(435498747): Add throttling for touch similarly to mouse events. handleUserInteractionChanged(displayId, mode); } @Override public void onTouchInteractionEnd(int displayId, int mode) { // TODO(435498747): Add throttling for touch similarly to mouse events. handleUserInteractionChanged(displayId, mode); } @Override public void onMouseMove(int displayId, int mode) { final long currentTime = mSystemClock.uptimeMillis(); if (currentTime - mLastMouseMoveTriggeredUiChangeTime < AccessibilityUtils.MAGNIFICATION_HANDLE_UI_CHANGE_INTERVAL_MS) { return; } mLastMouseMoveTriggeredUiChangeTime = currentTime; handleUserInteractionChanged(displayId, mode); } Loading
services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java +42 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.floatThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; Loading Loading @@ -81,6 +82,7 @@ import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.android.internal.accessibility.util.AccessibilityUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.test.FakeSettingsProvider; import com.android.server.LocalServices; Loading Loading @@ -2192,6 +2194,46 @@ public class MagnificationControllerTest { eq(TEST_DISPLAY)); } @Test public void onMouseMove_withThrottle_shouldRateLimit() throws RemoteException { mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); setMagnificationEnabled(MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // The first call should go through and trigger a UI update. mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // Subsequent calls within the throttle period should be ignored. mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager, never()).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); } @Test public void onMouseMove_withThrottle_shouldNotRateLimitAfterDelay() throws RemoteException { mMagnificationController.setMagnificationCapabilities( Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL); setMagnificationEnabled(MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // The first call should go through and trigger a UI update. mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); clearInvocations(mMagnificationConnectionManager); // Advance time past the throttle period. The next call should now go through. mSystemClock.advanceTime(AccessibilityUtils.MAGNIFICATION_HANDLE_UI_CHANGE_INTERVAL_MS + 1); mMagnificationController.onMouseMove(TEST_DISPLAY, MODE_FULLSCREEN); verify(mMagnificationConnectionManager).showMagnificationButton( TEST_DISPLAY, MODE_FULLSCREEN); } @Test public void enableWindowMode_showMagnificationButton() throws RemoteException { Loading