diff --git a/res/values/ids.xml b/res/values/ids.xml
index efd1791d5ed..211a7071872 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -25,6 +25,8 @@
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 468f3fa79ec..ec2620e0393 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4592,6 +4592,8 @@
]]>
+
+ enter settings
Autoclick (dwell timing)
diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java
index 1bced76a6b7..6dd1a30ec71 100644
--- a/src/com/android/settings/panel/PanelSlicesAdapter.java
+++ b/src/com/android/settings/panel/PanelSlicesAdapter.java
@@ -18,6 +18,7 @@ package com.android.settings.panel;
import static android.app.slice.Slice.HINT_ERROR;
import static android.app.slice.SliceItem.FORMAT_SLICE;
+import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import android.app.settings.SettingsEnums;
import android.content.Context;
@@ -25,6 +26,7 @@ import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
@@ -59,12 +61,15 @@ public class PanelSlicesAdapter
private final List> mSliceLiveData;
private final int mMetricsCategory;
private final PanelFragment mPanelFragment;
+ private final String mSliceClickActionLabel;
public PanelSlicesAdapter(
PanelFragment fragment, Map> sliceLiveData, int metricsCategory) {
mPanelFragment = fragment;
mSliceLiveData = new ArrayList<>(sliceLiveData.values());
mMetricsCategory = metricsCategory;
+ mSliceClickActionLabel = mPanelFragment.getContext().getString(
+ R.string.accessibility_action_label_panel_slice);
}
@NonNull
@@ -78,7 +83,6 @@ public class PanelSlicesAdapter
} else {
view = inflater.inflate(R.layout.panel_slice_row, viewGroup, false);
}
-
return new SliceRowViewHolder(view);
}
@@ -115,6 +119,9 @@ public class PanelSlicesAdapter
public class SliceRowViewHolder extends RecyclerView.ViewHolder
implements DividerItemDecoration.DividedViewHolder {
+ private static final int ROW_VIEW_ID = androidx.slice.view.R.id.row_view;
+ private static final int ROW_VIEW_TAG = R.id.tag_row_view;
+
@VisibleForTesting
final SliceView sliceView;
@VisibleForTesting
@@ -135,6 +142,7 @@ public class PanelSlicesAdapter
public void onBind(Slice slice) {
// Hides slice which reports with error hint or not contain any slice sub-item.
if (slice == null || !isValidSlice(slice)) {
+ updateActionLabel();
sliceView.setVisibility(View.GONE);
return;
} else {
@@ -158,6 +166,60 @@ public class PanelSlicesAdapter
eventInfo.actionType /* value */);
})
);
+ updateActionLabel();
+ }
+
+ /**
+ * Either set the action label if the row view is inflated into Slice, or set a listener to
+ * do so later when the row is available.
+ */
+ @VisibleForTesting void updateActionLabel() {
+ if (sliceView == null) {
+ return;
+ }
+
+ final LinearLayout llRow = sliceView.findViewById(ROW_VIEW_ID);
+ if (llRow != null) {
+ // Just set the label for the row. if is already laid out, there is no need for
+ // listening to future changes.
+ setActionLabel(llRow);
+ } else { // set the accessibility delegate when row_view is laid out
+ Object alreadyAddedListener = sliceView.getTag(ROW_VIEW_TAG);
+ if (alreadyAddedListener != null) {
+ return;
+ }
+ sliceView.setTag(ROW_VIEW_TAG, new Object());
+
+ sliceView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft, int oldTop, int oldRight, int oldBottom) {
+ LinearLayout row = sliceView.findViewById(ROW_VIEW_ID);
+ if (row != null) {
+ setActionLabel(row);
+ sliceView.removeOnLayoutChangeListener(this);
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Update the action label for TalkBack to be more specific
+ * @param view the RowView within the Slice
+ */
+ private void setActionLabel(View view) {
+ view.setAccessibilityDelegate(new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host,
+ AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ AccessibilityNodeInfo.AccessibilityAction customClick =
+ new AccessibilityNodeInfo.AccessibilityAction(
+ ACTION_CLICK, mSliceClickActionLabel);
+ info.addAction(customClick);
+ }
+ });
}
private boolean isValidSlice(Slice slice) {
diff --git a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
index cc5b2f83276..516d088634a 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelSlicesAdapterTest.java
@@ -19,6 +19,7 @@ package com.android.settings.panel;
import static com.android.settings.panel.PanelContent.VIEW_TYPE_SLIDER;
import static com.android.settings.panel.PanelSlicesAdapter.MAX_NUM_OF_SLICES;
import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_INDICATOR_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.VOLUME_NOTIFICATION_URI;
import static com.google.common.truth.Truth.assertThat;
@@ -139,6 +140,19 @@ public class PanelSlicesAdapterTest {
assertThat(viewHolder.mSliceSliderLayout).isNull();
}
+ @Test
+ public void onCreateViewHolder_viewTypeSlider_verifyActionLabelSet() {
+ addTestLiveData(VOLUME_NOTIFICATION_URI);
+
+ final PanelSlicesAdapter adapter =
+ new PanelSlicesAdapter(mPanelFragment, mData, 0);
+ final ViewGroup view = new FrameLayout(mContext);
+ SliceRowViewHolder viewHolder = spy(adapter.onCreateViewHolder(view, 0 /* view type*/));
+ adapter.onBindViewHolder(viewHolder, 0);
+
+ verify(viewHolder).updateActionLabel();
+ }
+
@Test
public void onCreateViewHolder_viewTypeSlider_verifyLayout() {
final PanelSlicesAdapter adapter =