diff options
| author | 2022-09-06 16:42:27 +0000 | |
|---|---|---|
| committer | 2022-09-06 16:42:27 +0000 | |
| commit | ff04c8b4d477b85fd6d32ea4e7dd95d3fb206693 (patch) | |
| tree | bfa9ca1cf18f2229f7ee5c12cfa474b35c797f29 | |
| parent | 0d5367cd2c27afd9a55d0c9afc4bb599306b0d82 (diff) | |
| parent | 54dd46a8142d5d00375d0f17c035d6b3c66c0c19 (diff) | |
Merge "Make disabled by policy tiles look UNAVAILABLE" into tm-qpr-dev am: 54dd46a814
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/19802196
Change-Id: I41fd0ba7950495059e63cb199078bb9e63b8ab57
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
6 files changed, 178 insertions, 53 deletions
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index b33cea7fe22e..df6486abb083 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1644,8 +1644,9 @@ <!-- The tile in quick settings is unavailable. [CHAR LIMIT=32] --> <string name="tile_unavailable">Unavailable</string> - <!-- The tile in quick settings is disabled by a device administration policy [CHAR LIMIT=32] --> - <string name="tile_disabled">Disabled</string> + <!-- Accessibility text for the click action on a tile that is disabled by policy. This will + be used following "Double-tap to..." [CHAR LIMIT=NONE] --> + <string name="accessibility_tile_disabled_by_policy_action_description">learn more</string> <!-- SysUI Tuner: Button that leads to the navigation bar customization screen [CHAR LIMIT=60] --> <string name="nav_bar">Navigation bar</string> diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java index be6982ab2470..58426656e4bf 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java @@ -165,7 +165,7 @@ public class QSIconViewImpl extends QSIconView { iv.clearColorFilter(); } if (state.state != mState) { - int color = getColor(state.state); + int color = getColor(state); mState = state.state; if (mTint != 0 && allowAnimations && shouldAnimate(iv)) { animateGrayScale(mTint, color, iv, () -> updateIcon(iv, state, allowAnimations)); @@ -183,7 +183,7 @@ public class QSIconViewImpl extends QSIconView { } } - protected int getColor(int state) { + protected int getColor(QSTile.State state) { return getIconColorForState(getContext(), state); } @@ -239,19 +239,18 @@ public class QSIconViewImpl extends QSIconView { /** * Color to tint the tile icon based on state */ - public static int getIconColorForState(Context context, int state) { - switch (state) { - case Tile.STATE_UNAVAILABLE: - return Utils.applyAlpha(QSTileViewImpl.UNAVAILABLE_ALPHA, - Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)); - case Tile.STATE_INACTIVE: - return Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary); - case Tile.STATE_ACTIVE: - return Utils.getColorAttrDefaultColor(context, - com.android.internal.R.attr.textColorOnAccent); - default: - Log.e("QSIconView", "Invalid state " + state); - return 0; + private static int getIconColorForState(Context context, QSTile.State state) { + if (state.disabledByPolicy || state.state == Tile.STATE_UNAVAILABLE) { + return Utils.applyAlpha(QSTileViewImpl.UNAVAILABLE_ALPHA, + Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)); + } else if (state.state == Tile.STATE_INACTIVE) { + return Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary); + } else if (state.state == Tile.STATE_ACTIVE) { + return Utils.getColorAttrDefaultColor(context, + com.android.internal.R.attr.textColorOnAccent); + } else { + Log.e("QSIconView", "Invalid state " + state); + return 0; } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 2731d64ee4e7..163ee2af600c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -35,6 +35,7 @@ import android.view.View import android.view.ViewGroup import android.view.accessibility.AccessibilityEvent import android.view.accessibility.AccessibilityNodeInfo +import android.widget.Button import android.widget.ImageView import android.widget.LinearLayout import android.widget.Switch @@ -144,6 +145,7 @@ open class QSTileViewImpl @JvmOverloads constructor( superSetVisibility = { super.setVisibility(it) }, superSetTransitionVisibility = { super.setTransitionVisibility(it) }, ) + private var lastDisabledByPolicy = false private val locInScreen = IntArray(2) @@ -376,8 +378,22 @@ open class QSTileViewImpl @JvmOverloads constructor( super.onInitializeAccessibilityNodeInfo(info) // Clear selected state so it is not announce by talkback. info.isSelected = false + if (lastDisabledByPolicy) { + info.addAction( + AccessibilityNodeInfo.AccessibilityAction( + AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id, + resources.getString( + R.string.accessibility_tile_disabled_by_policy_action_description + ) + ) + ) + } if (!TextUtils.isEmpty(accessibilityClass)) { - info.className = accessibilityClass + info.className = if (lastDisabledByPolicy) { + Button::class.java.name + } else { + accessibilityClass + } if (Switch::class.java.name == accessibilityClass) { val label = resources.getString( if (tileState) R.string.switch_bar_on else R.string.switch_bar_off) @@ -430,6 +446,10 @@ open class QSTileViewImpl @JvmOverloads constructor( state.secondaryLabel = stateText } } + if (state.disabledByPolicy && state.state != Tile.STATE_UNAVAILABLE) { + stateDescription.append(", ") + stateDescription.append(getUnavailableText(state.spec)) + } if (!TextUtils.isEmpty(state.stateDescription)) { stateDescription.append(", ") stateDescription.append(state.stateDescription) @@ -470,38 +490,38 @@ open class QSTileViewImpl @JvmOverloads constructor( } // Colors - if (state.state != lastState) { + if (state.state != lastState || state.disabledByPolicy || lastDisabledByPolicy) { singleAnimator.cancel() if (allowAnimations) { singleAnimator.setValues( colorValuesHolder( BACKGROUND_NAME, paintColor, - getBackgroundColorForState(state.state) + getBackgroundColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( LABEL_NAME, label.currentTextColor, - getLabelColorForState(state.state) + getLabelColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( SECONDARY_LABEL_NAME, secondaryLabel.currentTextColor, - getSecondaryLabelColorForState(state.state) + getSecondaryLabelColorForState(state.state, state.disabledByPolicy) ), colorValuesHolder( CHEVRON_NAME, chevronView.imageTintList?.defaultColor ?: 0, - getChevronColorForState(state.state) + getChevronColorForState(state.state, state.disabledByPolicy) ) ) singleAnimator.start() } else { setAllColors( - getBackgroundColorForState(state.state), - getLabelColorForState(state.state), - getSecondaryLabelColorForState(state.state), - getChevronColorForState(state.state) + getBackgroundColorForState(state.state, state.disabledByPolicy), + getLabelColorForState(state.state, state.disabledByPolicy), + getSecondaryLabelColorForState(state.state, state.disabledByPolicy), + getChevronColorForState(state.state, state.disabledByPolicy) ) } } @@ -512,6 +532,7 @@ open class QSTileViewImpl @JvmOverloads constructor( label.isEnabled = !state.disabledByPolicy lastState = state.state + lastDisabledByPolicy = state.disabledByPolicy } private fun setAllColors( @@ -559,13 +580,14 @@ open class QSTileViewImpl @JvmOverloads constructor( } } - private fun getStateText(state: QSTile.State): String { - if (state.disabledByPolicy) { - return context.getString(R.string.tile_disabled) - } + private fun getUnavailableText(spec: String?): String { + val arrayResId = SubtitleArrayMapping.getSubtitleId(spec) + return resources.getStringArray(arrayResId)[Tile.STATE_UNAVAILABLE] + } + private fun getStateText(state: QSTile.State): String { return if (state.state == Tile.STATE_UNAVAILABLE || state is BooleanState) { - var arrayResId = SubtitleArrayMapping.getSubtitleId(state.spec) + val arrayResId = SubtitleArrayMapping.getSubtitleId(state.spec) val array = resources.getStringArray(arrayResId) array[state.state] } else { @@ -587,11 +609,11 @@ open class QSTileViewImpl @JvmOverloads constructor( return locInScreen.get(1) >= -height } - private fun getBackgroundColorForState(state: Int): Int { - return when (state) { - Tile.STATE_ACTIVE -> colorActive - Tile.STATE_INACTIVE -> colorInactive - Tile.STATE_UNAVAILABLE -> colorUnavailable + private fun getBackgroundColorForState(state: Int, disabledByPolicy: Boolean = false): Int { + return when { + state == Tile.STATE_UNAVAILABLE || disabledByPolicy -> colorUnavailable + state == Tile.STATE_ACTIVE -> colorActive + state == Tile.STATE_INACTIVE -> colorInactive else -> { Log.e(TAG, "Invalid state $state") 0 @@ -599,11 +621,11 @@ open class QSTileViewImpl @JvmOverloads constructor( } } - private fun getLabelColorForState(state: Int): Int { - return when (state) { - Tile.STATE_ACTIVE -> colorLabelActive - Tile.STATE_INACTIVE -> colorLabelInactive - Tile.STATE_UNAVAILABLE -> colorLabelUnavailable + private fun getLabelColorForState(state: Int, disabledByPolicy: Boolean = false): Int { + return when { + state == Tile.STATE_UNAVAILABLE || disabledByPolicy -> colorLabelUnavailable + state == Tile.STATE_ACTIVE -> colorLabelActive + state == Tile.STATE_INACTIVE -> colorLabelInactive else -> { Log.e(TAG, "Invalid state $state") 0 @@ -611,11 +633,11 @@ open class QSTileViewImpl @JvmOverloads constructor( } } - private fun getSecondaryLabelColorForState(state: Int): Int { - return when (state) { - Tile.STATE_ACTIVE -> colorSecondaryLabelActive - Tile.STATE_INACTIVE -> colorSecondaryLabelInactive - Tile.STATE_UNAVAILABLE -> colorSecondaryLabelUnavailable + private fun getSecondaryLabelColorForState(state: Int, disabledByPolicy: Boolean = false): Int { + return when { + state == Tile.STATE_UNAVAILABLE || disabledByPolicy -> colorSecondaryLabelUnavailable + state == Tile.STATE_ACTIVE -> colorSecondaryLabelActive + state == Tile.STATE_INACTIVE -> colorSecondaryLabelInactive else -> { Log.e(TAG, "Invalid state $state") 0 @@ -623,7 +645,16 @@ open class QSTileViewImpl @JvmOverloads constructor( } } - private fun getChevronColorForState(state: Int): Int = getSecondaryLabelColorForState(state) + private fun getChevronColorForState(state: Int, disabledByPolicy: Boolean = false): Int = + getSecondaryLabelColorForState(state, disabledByPolicy) + + @VisibleForTesting + internal fun getCurrentColors(): List<Int> = listOf( + paintColor, + label.currentTextColor, + secondaryLabel.currentTextColor, + chevronView.imageTintList?.defaultColor ?: 0 + ) } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java index e910f725a4a6..619e50b47f13 100644 --- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java +++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.PixelFormat; @@ -58,7 +59,6 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.logging.QSLogger; -import com.android.systemui.qs.tileimpl.QSIconViewImpl; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.MessageRouter; @@ -304,7 +304,7 @@ public class GarbageMonitor implements Dumpable { MemoryIconDrawable(Context context) { baseIcon = context.getDrawable(R.drawable.ic_memory).mutate(); dp = context.getResources().getDisplayMetrics().density; - paint.setColor(QSIconViewImpl.getIconColorForState(context, STATE_ACTIVE)); + paint.setColor(Color.WHITE); } public void setRss(long rss) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java index 23e51687f9e1..2c76be64aa7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java @@ -97,7 +97,7 @@ public class QSIconViewImplTest extends SysuiTestCase { ImageView iv = mock(ImageView.class); State s = new State(); s.state = Tile.STATE_ACTIVE; - int desiredColor = mIconView.getColor(s.state); + int desiredColor = mIconView.getColor(s); when(iv.isShown()).thenReturn(true); mIconView.setIcon(iv, s, true); @@ -109,7 +109,7 @@ public class QSIconViewImplTest extends SysuiTestCase { ImageView iv = mock(ImageView.class); State s = new State(); s.state = Tile.STATE_ACTIVE; - int desiredColor = mIconView.getColor(s.state); + int desiredColor = mIconView.getColor(s); Icon i = mock(Icon.class); s.icon = i; when(i.toString()).thenReturn("MOCK ICON"); @@ -124,6 +124,18 @@ public class QSIconViewImplTest extends SysuiTestCase { assertFalse(mIconView.toString().contains("lastIcon")); } + @Test + public void testIconColorDisabledByPolicy_sameAsUnavailable() { + State s1 = new State(); + s1.state = Tile.STATE_INACTIVE; + s1.disabledByPolicy = true; + + State s2 = new State(); + s2.state = Tile.STATE_UNAVAILABLE; + + assertEquals(mIconView.getColor(s1), mIconView.getColor(s2)); + } + private static Drawable.ConstantState fakeConstantState(Drawable otherDrawable) { return new Drawable.ConstantState() { @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt index 9fdc2fd60870..d3ec1dd8bfb2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt @@ -280,6 +280,88 @@ class QSTileViewImplTest : SysuiTestCase() { assertThat(info.collectionItemInfo).isNull() } + @Test + fun testDisabledByPolicyInactive_usesUnavailableColors() { + val stateDisabledByPolicy = QSTile.State() + stateDisabledByPolicy.state = Tile.STATE_INACTIVE + stateDisabledByPolicy.disabledByPolicy = true + + val stateUnavailable = QSTile.State() + stateUnavailable.state = Tile.STATE_UNAVAILABLE + + tileView.changeState(stateDisabledByPolicy) + val colorsDisabledByPolicy = tileView.getCurrentColors() + + tileView.changeState(stateUnavailable) + val colorsUnavailable = tileView.getCurrentColors() + + assertThat(colorsDisabledByPolicy).containsExactlyElementsIn(colorsUnavailable) + } + + @Test + fun testDisabledByPolicyActive_usesUnavailableColors() { + val stateDisabledByPolicy = QSTile.State() + stateDisabledByPolicy.state = Tile.STATE_ACTIVE + stateDisabledByPolicy.disabledByPolicy = true + + val stateUnavailable = QSTile.State() + stateUnavailable.state = Tile.STATE_UNAVAILABLE + + tileView.changeState(stateDisabledByPolicy) + val colorsDisabledByPolicy = tileView.getCurrentColors() + + tileView.changeState(stateUnavailable) + val colorsUnavailable = tileView.getCurrentColors() + + assertThat(colorsDisabledByPolicy).containsExactlyElementsIn(colorsUnavailable) + } + + @Test + fun testDisabledByPolicy_secondaryLabelText() { + val testA11yLabel = "TEST_LABEL" + context.orCreateTestableResources + .addOverride( + R.string.accessibility_tile_disabled_by_policy_action_description, + testA11yLabel + ) + + val stateDisabledByPolicy = QSTile.State() + stateDisabledByPolicy.state = Tile.STATE_INACTIVE + stateDisabledByPolicy.disabledByPolicy = true + + tileView.changeState(stateDisabledByPolicy) + + val info = AccessibilityNodeInfo(tileView) + tileView.onInitializeAccessibilityNodeInfo(info) + assertThat( + info.actionList.find { + it.id == AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.id + }?.label + ).isEqualTo(testA11yLabel) + } + + @Test + fun testDisabledByPolicy_unavailableInStateDescription() { + val state = QSTile.BooleanState() + val spec = "internet" + state.spec = spec + state.disabledByPolicy = true + state.state = Tile.STATE_INACTIVE + + val unavailableString = "${spec}_unavailable" + val offString = "${spec}_off" + val onString = "${spec}_on" + + context.orCreateTestableResources.addOverride(R.array.tile_states_internet, arrayOf( + unavailableString, + offString, + onString + )) + + tileView.changeState(state) + assertThat(tileView.stateDescription?.contains(unavailableString)).isTrue() + } + class FakeTileView( context: Context, icon: QSIconView, @@ -289,4 +371,4 @@ class QSTileViewImplTest : SysuiTestCase() { handleStateChanged(state) } } -}
\ No newline at end of file +} |