Loading core/java/android/service/dreams/DreamService.java +2 −3 Original line number Diff line number Diff line Loading @@ -787,7 +787,6 @@ public class DreamService extends Service implements Window.Callback { */ public void setInteractive(boolean interactive) { mInteractive = interactive; updateAccessibilityMessage(); } /** Loading Loading @@ -1641,9 +1640,9 @@ public class DreamService extends Service implements Window.Callback { if (mWindow == null) return; if (mDreamAccessibility == null) { final View rootView = mWindow.getDecorView(); mDreamAccessibility = new DreamAccessibility(this, rootView); mDreamAccessibility = new DreamAccessibility(this, rootView, this::wakeUp); } mDreamAccessibility.updateAccessibilityConfiguration(isInteractive()); mDreamAccessibility.updateAccessibilityConfiguration(); } private boolean getWindowFlagValue(int flag, boolean defaultValue) { Loading core/java/android/service/dreams/utils/DreamAccessibility.java +21 −23 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.service.dreams.utils; import android.annotation.NonNull; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; Loading @@ -32,22 +33,22 @@ public class DreamAccessibility { private final Context mContext; private final View mView; private final View.AccessibilityDelegate mAccessibilityDelegate; private final Runnable mDismissCallback; public DreamAccessibility(@NonNull Context context, @NonNull View view) { public DreamAccessibility(@NonNull Context context, @NonNull View view, @NonNull Runnable dismissCallback) { mContext = context; mView = view; mAccessibilityDelegate = createNewAccessibilityDelegate(mContext); mDismissCallback = dismissCallback; } /** * @param interactive * Removes and add accessibility configuration depending if the dream is interactive or not * Adds default accessibility configuration if none exist on the dream */ public void updateAccessibilityConfiguration(Boolean interactive) { if (!interactive) { public void updateAccessibilityConfiguration() { if (mView.getAccessibilityDelegate() == null) { addAccessibilityConfiguration(); } else { removeCustomAccessibilityAction(); } } Loading @@ -58,31 +59,28 @@ public class DreamAccessibility { mView.setAccessibilityDelegate(mAccessibilityDelegate); } /** * Removes Configured the accessibility actions for the given root view. */ private void removeCustomAccessibilityAction() { if (mView.getAccessibilityDelegate() == mAccessibilityDelegate) { mView.setAccessibilityDelegate(null); } } private View.AccessibilityDelegate createNewAccessibilityDelegate(Context context) { return new View.AccessibilityDelegate() { @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); for (AccessibilityNodeInfo.AccessibilityAction action : info.getActionList()) { if (action.getId() == AccessibilityNodeInfo.ACTION_CLICK) { info.removeAction(action); break; } } info.addAction(new AccessibilityNodeInfo.AccessibilityAction( AccessibilityNodeInfo.ACTION_CLICK, AccessibilityNodeInfo.ACTION_DISMISS, context.getResources().getString(R.string.dream_accessibility_action_click) )); } @Override public boolean performAccessibilityAction(View host, int action, Bundle args) { switch(action){ case AccessibilityNodeInfo.ACTION_DISMISS: if (mDismissCallback != null) { mDismissCallback.run(); } break; } return true; } }; } } packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalPopupSection.kt +0 −3 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp Loading Loading @@ -102,8 +101,6 @@ constructor( val interactionSource = remember { MutableInteractionSource() } val focusRequester = remember { FocusRequester() } val context = LocalContext.current LaunchedEffect(Unit) { // Adding a delay to ensure the animation completes before requesting focus delay(250) Loading services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java +29 −54 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.server.dreams; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; import android.content.res.Resources; Loading @@ -44,9 +46,6 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Collections; @SmallTest @RunWith(AndroidJUnit4.class) public class DreamAccessibilityTest { Loading @@ -73,7 +72,8 @@ public class DreamAccessibilityTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); mDreamAccessibility = new DreamAccessibility(mContext, mView); Runnable mDismissCallback = () -> {}; mDreamAccessibility = new DreamAccessibility(mContext, mView, mDismissCallback); when(mContext.getResources()).thenReturn(mResources); when(mResources.getString(R.string.dream_accessibility_action_click)) Loading @@ -84,80 +84,55 @@ public class DreamAccessibilityTest { */ @Test public void testConfigureAccessibilityActions() { when(mAccessibilityNodeInfo.getActionList()).thenReturn(new ArrayList<>()); when(mView.getAccessibilityDelegate()).thenReturn(null); mDreamAccessibility.updateAccessibilityConfiguration(false); mDreamAccessibility.updateAccessibilityConfiguration(); verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture()); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor.getValue(); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor .getValue(); capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo); verify(mAccessibilityNodeInfo).addAction(argThat(action -> action.getId() == AccessibilityNodeInfo.ACTION_CLICK action.getId() == AccessibilityNodeInfo.ACTION_DISMISS && TextUtils.equals(action.getLabel(), CUSTOM_ACTION))); } /** * Test to verify the configuration of accessibility actions within a view delegate, * specifically checking the removal of an existing click action and addition * of a new custom action. * Test to verify no accessibility configuration is added if one exist. */ @Test public void testConfigureAccessibilityActions_RemovesExistingClickAction() { AccessibilityNodeInfo.AccessibilityAction existingAction = new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, EXISTING_ACTION); when(mAccessibilityNodeInfo.getActionList()) .thenReturn(Collections.singletonList(existingAction)); mDreamAccessibility.updateAccessibilityConfiguration(false); verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture()); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor.getValue(); capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo); public void testNotAddingDuplicateAccessibilityConfiguration() { View.AccessibilityDelegate existingDelegate = mock(View.AccessibilityDelegate.class); when(mView.getAccessibilityDelegate()).thenReturn(existingDelegate); verify(mAccessibilityNodeInfo).removeAction(existingAction); verify(mAccessibilityNodeInfo).addAction(argThat(action -> action.getId() == AccessibilityNodeInfo.ACTION_CLICK && TextUtils.equals(action.getLabel(), CUSTOM_ACTION))); mDreamAccessibility.updateAccessibilityConfiguration(); verify(mView, never()).setAccessibilityDelegate(any()); } /** * Test to verify the removal of a custom accessibility action within a view delegate. * Test to verify dismiss callback is called */ @Test public void testRemoveCustomAccessibilityAction() { public void testPerformAccessibilityAction() { Runnable mockDismissCallback = mock(Runnable.class); DreamAccessibility dreamAccessibility = new DreamAccessibility(mContext, mView, mockDismissCallback); AccessibilityNodeInfo.AccessibilityAction existingAction = new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, EXISTING_ACTION); when(mAccessibilityNodeInfo.getActionList()) .thenReturn(Collections.singletonList(existingAction)); dreamAccessibility.updateAccessibilityConfiguration(); mDreamAccessibility.updateAccessibilityConfiguration(false); verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture()); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor.getValue(); when(mView.getAccessibilityDelegate()).thenReturn(capturedDelegate); clearInvocations(mView); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor .getValue(); mDreamAccessibility.updateAccessibilityConfiguration(true); verify(mView).setAccessibilityDelegate(null); } boolean result = capturedDelegate.performAccessibilityAction(mView, AccessibilityNodeInfo.ACTION_DISMISS, null); /** * Test to verify the removal of custom accessibility action is not called if delegate is not * set by the dreamService. */ @Test public void testRemoveCustomAccessibility_DoesNotRemoveDelegateNotSetByDreamAccessibility() { mDreamAccessibility.updateAccessibilityConfiguration(true); verify(mView, never()).setAccessibilityDelegate(any()); assertTrue(result); verify(mockDismissCallback).run(); } } Loading
core/java/android/service/dreams/DreamService.java +2 −3 Original line number Diff line number Diff line Loading @@ -787,7 +787,6 @@ public class DreamService extends Service implements Window.Callback { */ public void setInteractive(boolean interactive) { mInteractive = interactive; updateAccessibilityMessage(); } /** Loading Loading @@ -1641,9 +1640,9 @@ public class DreamService extends Service implements Window.Callback { if (mWindow == null) return; if (mDreamAccessibility == null) { final View rootView = mWindow.getDecorView(); mDreamAccessibility = new DreamAccessibility(this, rootView); mDreamAccessibility = new DreamAccessibility(this, rootView, this::wakeUp); } mDreamAccessibility.updateAccessibilityConfiguration(isInteractive()); mDreamAccessibility.updateAccessibilityConfiguration(); } private boolean getWindowFlagValue(int flag, boolean defaultValue) { Loading
core/java/android/service/dreams/utils/DreamAccessibility.java +21 −23 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.service.dreams.utils; import android.annotation.NonNull; import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; Loading @@ -32,22 +33,22 @@ public class DreamAccessibility { private final Context mContext; private final View mView; private final View.AccessibilityDelegate mAccessibilityDelegate; private final Runnable mDismissCallback; public DreamAccessibility(@NonNull Context context, @NonNull View view) { public DreamAccessibility(@NonNull Context context, @NonNull View view, @NonNull Runnable dismissCallback) { mContext = context; mView = view; mAccessibilityDelegate = createNewAccessibilityDelegate(mContext); mDismissCallback = dismissCallback; } /** * @param interactive * Removes and add accessibility configuration depending if the dream is interactive or not * Adds default accessibility configuration if none exist on the dream */ public void updateAccessibilityConfiguration(Boolean interactive) { if (!interactive) { public void updateAccessibilityConfiguration() { if (mView.getAccessibilityDelegate() == null) { addAccessibilityConfiguration(); } else { removeCustomAccessibilityAction(); } } Loading @@ -58,31 +59,28 @@ public class DreamAccessibility { mView.setAccessibilityDelegate(mAccessibilityDelegate); } /** * Removes Configured the accessibility actions for the given root view. */ private void removeCustomAccessibilityAction() { if (mView.getAccessibilityDelegate() == mAccessibilityDelegate) { mView.setAccessibilityDelegate(null); } } private View.AccessibilityDelegate createNewAccessibilityDelegate(Context context) { return new View.AccessibilityDelegate() { @Override public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(host, info); for (AccessibilityNodeInfo.AccessibilityAction action : info.getActionList()) { if (action.getId() == AccessibilityNodeInfo.ACTION_CLICK) { info.removeAction(action); break; } } info.addAction(new AccessibilityNodeInfo.AccessibilityAction( AccessibilityNodeInfo.ACTION_CLICK, AccessibilityNodeInfo.ACTION_DISMISS, context.getResources().getString(R.string.dream_accessibility_action_click) )); } @Override public boolean performAccessibilityAction(View host, int action, Bundle args) { switch(action){ case AccessibilityNodeInfo.ACTION_DISMISS: if (mDismissCallback != null) { mDismissCallback.run(); } break; } return true; } }; } }
packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/section/CommunalPopupSection.kt +0 −3 Original line number Diff line number Diff line Loading @@ -50,7 +50,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp Loading Loading @@ -102,8 +101,6 @@ constructor( val interactionSource = remember { MutableInteractionSource() } val focusRequester = remember { FocusRequester() } val context = LocalContext.current LaunchedEffect(Unit) { // Adding a delay to ensure the animation completes before requesting focus delay(250) Loading
services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java +29 −54 Original line number Diff line number Diff line Loading @@ -19,10 +19,12 @@ package com.android.server.dreams; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; import android.content.res.Resources; Loading @@ -44,9 +46,6 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.Collections; @SmallTest @RunWith(AndroidJUnit4.class) public class DreamAccessibilityTest { Loading @@ -73,7 +72,8 @@ public class DreamAccessibilityTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); mDreamAccessibility = new DreamAccessibility(mContext, mView); Runnable mDismissCallback = () -> {}; mDreamAccessibility = new DreamAccessibility(mContext, mView, mDismissCallback); when(mContext.getResources()).thenReturn(mResources); when(mResources.getString(R.string.dream_accessibility_action_click)) Loading @@ -84,80 +84,55 @@ public class DreamAccessibilityTest { */ @Test public void testConfigureAccessibilityActions() { when(mAccessibilityNodeInfo.getActionList()).thenReturn(new ArrayList<>()); when(mView.getAccessibilityDelegate()).thenReturn(null); mDreamAccessibility.updateAccessibilityConfiguration(false); mDreamAccessibility.updateAccessibilityConfiguration(); verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture()); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor.getValue(); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor .getValue(); capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo); verify(mAccessibilityNodeInfo).addAction(argThat(action -> action.getId() == AccessibilityNodeInfo.ACTION_CLICK action.getId() == AccessibilityNodeInfo.ACTION_DISMISS && TextUtils.equals(action.getLabel(), CUSTOM_ACTION))); } /** * Test to verify the configuration of accessibility actions within a view delegate, * specifically checking the removal of an existing click action and addition * of a new custom action. * Test to verify no accessibility configuration is added if one exist. */ @Test public void testConfigureAccessibilityActions_RemovesExistingClickAction() { AccessibilityNodeInfo.AccessibilityAction existingAction = new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, EXISTING_ACTION); when(mAccessibilityNodeInfo.getActionList()) .thenReturn(Collections.singletonList(existingAction)); mDreamAccessibility.updateAccessibilityConfiguration(false); verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture()); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor.getValue(); capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo); public void testNotAddingDuplicateAccessibilityConfiguration() { View.AccessibilityDelegate existingDelegate = mock(View.AccessibilityDelegate.class); when(mView.getAccessibilityDelegate()).thenReturn(existingDelegate); verify(mAccessibilityNodeInfo).removeAction(existingAction); verify(mAccessibilityNodeInfo).addAction(argThat(action -> action.getId() == AccessibilityNodeInfo.ACTION_CLICK && TextUtils.equals(action.getLabel(), CUSTOM_ACTION))); mDreamAccessibility.updateAccessibilityConfiguration(); verify(mView, never()).setAccessibilityDelegate(any()); } /** * Test to verify the removal of a custom accessibility action within a view delegate. * Test to verify dismiss callback is called */ @Test public void testRemoveCustomAccessibilityAction() { public void testPerformAccessibilityAction() { Runnable mockDismissCallback = mock(Runnable.class); DreamAccessibility dreamAccessibility = new DreamAccessibility(mContext, mView, mockDismissCallback); AccessibilityNodeInfo.AccessibilityAction existingAction = new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, EXISTING_ACTION); when(mAccessibilityNodeInfo.getActionList()) .thenReturn(Collections.singletonList(existingAction)); dreamAccessibility.updateAccessibilityConfiguration(); mDreamAccessibility.updateAccessibilityConfiguration(false); verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture()); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor.getValue(); when(mView.getAccessibilityDelegate()).thenReturn(capturedDelegate); clearInvocations(mView); View.AccessibilityDelegate capturedDelegate = mAccessibilityDelegateArgumentCaptor .getValue(); mDreamAccessibility.updateAccessibilityConfiguration(true); verify(mView).setAccessibilityDelegate(null); } boolean result = capturedDelegate.performAccessibilityAction(mView, AccessibilityNodeInfo.ACTION_DISMISS, null); /** * Test to verify the removal of custom accessibility action is not called if delegate is not * set by the dreamService. */ @Test public void testRemoveCustomAccessibility_DoesNotRemoveDelegateNotSetByDreamAccessibility() { mDreamAccessibility.updateAccessibilityConfiguration(true); verify(mView, never()).setAccessibilityDelegate(any()); assertTrue(result); verify(mockDismissCallback).run(); } }