diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java index 01811e9cdcedc..f607cc8f7e156 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTile.java @@ -118,6 +118,7 @@ public interface QSTile { public CharSequence label; public CharSequence secondaryLabel; public CharSequence contentDescription; + public CharSequence stateDescription; public CharSequence dualLabelContentDescription; public boolean disabledByPolicy; public boolean dualTarget = false; @@ -135,6 +136,7 @@ public interface QSTile { || !Objects.equals(other.label, label) || !Objects.equals(other.secondaryLabel, secondaryLabel) || !Objects.equals(other.contentDescription, contentDescription) + || !Objects.equals(other.stateDescription, stateDescription) || !Objects.equals(other.dualLabelContentDescription, dualLabelContentDescription) || !Objects.equals(other.expandedAccessibilityClassName, @@ -151,6 +153,7 @@ public interface QSTile { other.label = label; other.secondaryLabel = secondaryLabel; other.contentDescription = contentDescription; + other.stateDescription = stateDescription; other.dualLabelContentDescription = dualLabelContentDescription; other.expandedAccessibilityClassName = expandedAccessibilityClassName; other.disabledByPolicy = disabledByPolicy; @@ -177,6 +180,7 @@ public interface QSTile { sb.append(",label=").append(label); sb.append(",secondaryLabel=").append(secondaryLabel); sb.append(",contentDescription=").append(contentDescription); + sb.append(",stateDescription=").append(stateDescription); sb.append(",dualLabelContentDescription=").append(dualLabelContentDescription); sb.append(",expandedAccessibilityClassName=").append(expandedAccessibilityClassName); sb.append(",disabledByPolicy=").append(disabledByPolicy); diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index ebaf55fd7e9ce..8f9e934c97e53 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2032,6 +2032,9 @@ Off + + Unavailable + Navigation bar @@ -2586,6 +2589,4 @@ Controls Choose controls for quick access - - diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java index ae6162219afa8..c118630fe91a1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/external/CustomTile.java @@ -191,6 +191,7 @@ public class CustomTile extends QSTileImpl implements TileChangeListener mTile.setLabel(tile.getLabel()); mTile.setSubtitle(tile.getSubtitle()); mTile.setContentDescription(tile.getContentDescription()); + mTile.setStateDescription(tile.getStateDescription()); mTile.setState(tile.getState()); } @@ -345,6 +346,12 @@ public class CustomTile extends QSTileImpl implements TileChangeListener state.contentDescription = state.label; } + if (mTile.getStateDescription() != null) { + state.stateDescription = mTile.getStateDescription(); + } else { + state.stateDescription = null; + } + if (state instanceof BooleanState) { state.expandedAccessibilityClassName = Switch.class.getName(); ((BooleanState) state).value = (state.state == Tile.STATE_ACTIVE); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java index 2fe64d26f3acd..8feee10c7e834 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java @@ -63,7 +63,6 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { private String mAccessibilityClass; private boolean mTileState; private boolean mCollapsedView; - private boolean mClicked; private boolean mShowRippleEffect = true; private final ImageView mBg; @@ -230,13 +229,35 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { setLongClickable(state.handlesLongClick); mIcon.setIcon(state, allowAnimations); setContentDescription(state.contentDescription); + final StringBuilder stateDescription = new StringBuilder(); + switch (state.state) { + case Tile.STATE_UNAVAILABLE: + stateDescription.append(mContext.getString(R.string.tile_unavailable)); + break; + case Tile.STATE_INACTIVE: + if (state instanceof QSTile.BooleanState) { + stateDescription.append(mContext.getString(R.string.switch_bar_off)); + } + break; + case Tile.STATE_ACTIVE: + if (state instanceof QSTile.BooleanState) { + stateDescription.append(mContext.getString(R.string.switch_bar_on)); + } + break; + default: + break; + } + if (!TextUtils.isEmpty(state.stateDescription)) { + stateDescription.append(", "); + stateDescription.append(state.stateDescription); + } + setStateDescription(stateDescription.toString()); mAccessibilityClass = state.state == Tile.STATE_UNAVAILABLE ? null : state.expandedAccessibilityClassName; if (state instanceof QSTile.BooleanState) { boolean newState = ((BooleanState) state).value; if (mTileState != newState) { - mClicked = false; mTileState = newState; } } @@ -287,24 +308,11 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { return mIconFrame; } - @Override - public boolean performClick() { - mClicked = true; - return super.performClick(); - } - @Override public void onInitializeAccessibilityEvent(AccessibilityEvent event) { super.onInitializeAccessibilityEvent(event); if (!TextUtils.isEmpty(mAccessibilityClass)) { event.setClassName(mAccessibilityClass); - if (Switch.class.getName().equals(mAccessibilityClass)) { - boolean b = mClicked ? !mTileState : mTileState; - String label = getResources() - .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off); - event.setContentDescription(label); - event.setChecked(b); - } } } @@ -316,11 +324,13 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { if (!TextUtils.isEmpty(mAccessibilityClass)) { info.setClassName(mAccessibilityClass); if (Switch.class.getName().equals(mAccessibilityClass)) { - boolean b = mClicked ? !mTileState : mTileState; - String label = getResources() - .getString(b ? R.string.switch_bar_on : R.string.switch_bar_off); + String label = getResources().getString( + mTileState ? R.string.switch_bar_on : R.string.switch_bar_off); + // Set the text here for tests in + // android.platform.test.scenario.sysui.quicksettings. Can be removed when + // UiObject2 has a new getStateDescription() API and tests are updated. info.setText(label); - info.setChecked(b); + info.setChecked(mTileState); info.setCheckable(true); if (isLongClickable()) { info.addAction( diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 9282a2e3b3121..361b6c1b12600 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -134,25 +134,27 @@ public class BluetoothTile extends QSTileImpl { state.label = mContext.getString(R.string.quick_settings_bluetooth_label); state.secondaryLabel = TextUtils.emptyIfNull( getSecondaryLabel(enabled, connecting, connected, state.isTransient)); + state.contentDescription = state.label; + state.stateDescription = ""; if (enabled) { if (connected) { state.icon = new BluetoothConnectedTileIcon(); if (!TextUtils.isEmpty(mController.getConnectedDeviceName())) { state.label = mController.getConnectedDeviceName(); } - state.contentDescription = + state.stateDescription = mContext.getString(R.string.accessibility_bluetooth_name, state.label) + ", " + state.secondaryLabel; } else if (state.isTransient) { state.icon = ResourceIcon.get( com.android.internal.R.drawable.ic_bluetooth_transient_animation); - state.contentDescription = state.secondaryLabel; + state.stateDescription = state.secondaryLabel; } else { state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_bluetooth); state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_bluetooth) + "," - + mContext.getString(R.string.accessibility_not_connected); + R.string.accessibility_quick_settings_bluetooth); + state.stateDescription = mContext.getString(R.string.accessibility_not_connected); } state.state = Tile.STATE_ACTIVE; } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 32b051e356040..58de0575fa753 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -183,6 +183,7 @@ public class CastTile extends QSTileImpl { protected void handleUpdateState(BooleanState state, Object arg) { state.label = mContext.getString(R.string.quick_settings_cast_title); state.contentDescription = state.label; + state.stateDescription = ""; state.value = false; final List devices = mController.getCastDevices(); boolean connecting = false; @@ -192,8 +193,9 @@ public class CastTile extends QSTileImpl { if (device.state == CastDevice.STATE_CONNECTED) { state.value = true; state.secondaryLabel = getDeviceName(device); - state.contentDescription = state.contentDescription + "," - + mContext.getString(R.string.accessibility_cast_name, state.label); + state.stateDescription = state.stateDescription + "," + + mContext.getString( + R.string.accessibility_cast_name, state.label); connecting = false; break; } else if (device.state == CastDevice.STATE_CONNECTING) { @@ -217,9 +219,8 @@ public class CastTile extends QSTileImpl { state.state = Tile.STATE_UNAVAILABLE; String noWifi = mContext.getString(R.string.quick_settings_cast_no_wifi); state.secondaryLabel = noWifi; - state.contentDescription = state.contentDescription + ", " + mContext.getString( - R.string.accessibility_quick_settings_not_available, noWifi); } + state.stateDescription = state.stateDescription + ", " + state.secondaryLabel; mDetailAdapter.updateItems(devices); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index 22470c7f5af59..d5f86c9514072 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -194,17 +194,13 @@ public class CellularTile extends QSTileImpl { state.secondaryLabel = r.getString(R.string.cell_data_off); } - - // TODO(b/77881974): Instead of switching out the description via a string check for - // we need to have two strings provided by the MobileIconGroup. - final CharSequence contentDescriptionSuffix; + state.contentDescription = state.label; if (state.state == Tile.STATE_INACTIVE) { - contentDescriptionSuffix = r.getString(R.string.cell_data_off_content_description); + // This information is appended later by converting the Tile.STATE_INACTIVE state. + state.stateDescription = ""; } else { - contentDescriptionSuffix = state.secondaryLabel; + state.stateDescription = state.secondaryLabel; } - - state.contentDescription = state.label + ", " + contentDescriptionSuffix; } private CharSequence appendMobileDataType(CharSequence current, CharSequence dataType) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 52d1a5b3b9910..9215da4cda9a3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -240,6 +240,8 @@ public class DndTile extends QSTileImpl { zen != Global.ZEN_MODE_OFF, mController.getConfig(), false)); state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_dnd); checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME); + // Keeping the secondaryLabel in contentDescription instead of stateDescription is easier + // to understand. switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: state.contentDescription = diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index dafdd89ee62c5..792c364779621 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -102,14 +102,13 @@ public class FlashlightTile extends QSTileImpl implements } state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label); state.secondaryLabel = ""; + state.stateDescription = ""; if (!mFlashlightController.isAvailable()) { state.icon = mIcon; state.slash.isSlashed = true; state.secondaryLabel = mContext.getString( R.string.quick_settings_flashlight_camera_in_use); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_flashlight_unavailable) - + ", " + state.secondaryLabel; + state.stateDescription = state.secondaryLabel; state.state = Tile.STATE_UNAVAILABLE; return; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index 42f80109e0453..91b3ae480af96 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -148,6 +148,7 @@ public class HotspotTile extends QSTileImpl { state.secondaryLabel = getSecondaryLabel( isTileActive, isTransient, isDataSaverEnabled, numConnectedDevices); + state.stateDescription = state.secondaryLabel; } @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index fbdca3ba1c7b4..e617867eb10ea 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -105,15 +105,8 @@ public class LocationTile extends QSTileImpl { } state.icon = mIcon; state.slash.isSlashed = !state.value; - if (locationEnabled) { - state.label = mContext.getString(R.string.quick_settings_location_label); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_location_on); - } else { - state.label = mContext.getString(R.string.quick_settings_location_label); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_location_off); - } + state.label = mContext.getString(R.string.quick_settings_location_label); + state.contentDescription = state.label; state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.expandedAccessibilityClassName = Switch.class.getName(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index b7ce101cacab9..6e8dcf36baccc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -195,6 +195,7 @@ public class WifiTile extends QSTileImpl { state.activityIn = cb.enabled && cb.activityIn; state.activityOut = cb.enabled && cb.activityOut; final StringBuffer minimalContentDescription = new StringBuffer(); + final StringBuffer minimalStateDescription = new StringBuffer(); final Resources r = mContext.getResources(); if (isTransient) { state.icon = ResourceIcon.get( @@ -219,13 +220,14 @@ public class WifiTile extends QSTileImpl { mContext.getString(R.string.quick_settings_wifi_label)).append(","); if (state.value) { if (wifiConnected) { - minimalContentDescription.append(cb.wifiSignalContentDescription).append(","); + minimalStateDescription.append(cb.wifiSignalContentDescription); minimalContentDescription.append(removeDoubleQuotes(cb.ssid)); if (!TextUtils.isEmpty(state.secondaryLabel)) { minimalContentDescription.append(",").append(state.secondaryLabel); } } } + state.stateDescription = minimalStateDescription.toString(); state.contentDescription = minimalContentDescription.toString(); state.dualLabelContentDescription = r.getString( R.string.accessibility_quick_settings_open_settings, getTileLabel()); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index 7853dc388bcbb..e54ee51fb9d45 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -103,14 +103,11 @@ public class WorkModeTile extends QSTileImpl implements state.icon = mIcon; if (state.value) { state.slash.isSlashed = false; - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_work_mode_on); } else { state.slash.isSlashed = true; - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_work_mode_off); } state.label = mContext.getString(R.string.quick_settings_work_mode_label); + state.contentDescription = state.label; state.expandedAccessibilityClassName = Switch.class.getName(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; }