diff options
author | Xin Li <delphij@google.com> | 2023-08-14 15:41:37 -0700 |
---|---|---|
committer | Xin Li <delphij@google.com> | 2023-08-14 15:41:37 -0700 |
commit | 515d4f6193ddb381303b3ce62cb108142a45c5f8 (patch) | |
tree | e76ffe4c398686600f5370565d5b0c785e3d9b02 | |
parent | df2d0533ce500cb19a073de20117805f08856730 (diff) | |
parent | 829ee323b42695f6fb86ce1c0caa66bbbcd85a9c (diff) | |
download | systemlibs-tmp_amf_298295554.tar.gz |
Merge Android U (ab/10368041)tmp_amf_298295554
Bug: 291102124
Merged-In: I83d433bb2235e3181a1a0dad1d95647bad2226b3
Change-Id: If74942622d2a09641ebe85f657bd7be338d8926b
-rw-r--r-- | car-qc-lib/res/color/qc_seekbar_thumb_selector.xml | 22 | ||||
-rw-r--r-- | car-qc-lib/res/color/qc_switch_thumb_selector.xml | 22 | ||||
-rw-r--r-- | car-qc-lib/res/drawable/qc_toggle_background.xml | 4 | ||||
-rw-r--r-- | car-qc-lib/res/drawable/qc_toggle_unavailable_background.xml | 4 | ||||
-rw-r--r-- | car-qc-lib/res/layout/qc_row_view.xml | 2 | ||||
-rw-r--r-- | car-qc-lib/res/values/colors.xml | 10 | ||||
-rw-r--r-- | car-qc-lib/res/values/dimens.xml | 3 | ||||
-rw-r--r-- | car-qc-lib/res/values/overlayable.xml | 87 | ||||
-rw-r--r-- | car-qc-lib/src/com/android/car/qc/QCActionItem.java | 42 | ||||
-rw-r--r-- | car-qc-lib/src/com/android/car/qc/provider/BaseQCProvider.java | 6 | ||||
-rw-r--r-- | car-qc-lib/src/com/android/car/qc/view/QCRowView.java | 12 | ||||
-rw-r--r-- | car-qc-lib/tests/unit/src/com/android/car/qc/QCActionItemTest.java | 21 | ||||
-rw-r--r-- | car-qc-lib/tests/unit/src/com/android/car/qc/view/QCRowViewTest.java | 43 | ||||
-rw-r--r-- | tools/rro/resource_utils.py | 6 |
14 files changed, 262 insertions, 22 deletions
diff --git a/car-qc-lib/res/color/qc_seekbar_thumb_selector.xml b/car-qc-lib/res/color/qc_seekbar_thumb_selector.xml new file mode 100644 index 0000000..bf94a61 --- /dev/null +++ b/car-qc-lib/res/color/qc_seekbar_thumb_selector.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_enabled="false" + android:color="@color/qc_seekbar_thumb_disabled_on_dark"/> + <item android:color="@color/qc_seekbar_thumb"/> +</selector> diff --git a/car-qc-lib/res/color/qc_switch_thumb_selector.xml b/car-qc-lib/res/color/qc_switch_thumb_selector.xml new file mode 100644 index 0000000..e0bfc22 --- /dev/null +++ b/car-qc-lib/res/color/qc_switch_thumb_selector.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2023 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:state_enabled="false" + android:color="@color/qc_switch_thumb_color_disabled_on_dark"/> + <item android:color="@color/qc_switch_thumb_color"/> +</selector> diff --git a/car-qc-lib/res/drawable/qc_toggle_background.xml b/car-qc-lib/res/drawable/qc_toggle_background.xml index 3688175..4e30cf4 100644 --- a/car-qc-lib/res/drawable/qc_toggle_background.xml +++ b/car-qc-lib/res/drawable/qc_toggle_background.xml @@ -16,8 +16,8 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background" - android:width="@dimen/qc_toggle_size" - android:height="@dimen/qc_toggle_size" + android:width="@dimen/qc_toggle_background_size" + android:height="@dimen/qc_toggle_background_size" android:start="@dimen/qc_toggle_background_padding" android:top="@dimen/qc_toggle_background_padding" android:drawable="@drawable/qc_toggle_button_background"> diff --git a/car-qc-lib/res/drawable/qc_toggle_unavailable_background.xml b/car-qc-lib/res/drawable/qc_toggle_unavailable_background.xml index e9f2e12..185b801 100644 --- a/car-qc-lib/res/drawable/qc_toggle_unavailable_background.xml +++ b/car-qc-lib/res/drawable/qc_toggle_unavailable_background.xml @@ -16,8 +16,8 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@android:id/background" - android:width="@dimen/qc_toggle_size" - android:height="@dimen/qc_toggle_size" + android:width="@dimen/qc_toggle_background_size" + android:height="@dimen/qc_toggle_background_size" android:start="@dimen/qc_toggle_background_padding" android:top="@dimen/qc_toggle_background_padding"> <shape android:shape="rectangle"> diff --git a/car-qc-lib/res/layout/qc_row_view.xml b/car-qc-lib/res/layout/qc_row_view.xml index 2d95888..a4af032 100644 --- a/car-qc-lib/res/layout/qc_row_view.xml +++ b/car-qc-lib/res/layout/qc_row_view.xml @@ -119,7 +119,7 @@ app:layout_constraintTop_toBottomOf="@+id/barrier2" app:layout_constraintBottom_toBottomOf="parent"> <com.android.car.qc.view.QCSeekBarView - android:id="@+id/seekbar" + android:id="@+id/qc_seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" style="@style/Widget.QC.SeekBar"/> diff --git a/car-qc-lib/res/values/colors.xml b/car-qc-lib/res/values/colors.xml index 62bcfdc..a2b85ff 100644 --- a/car-qc-lib/res/values/colors.xml +++ b/car-qc-lib/res/values/colors.xml @@ -20,4 +20,12 @@ <color name="qc_toggle_unavailable_background_color">@android:color/transparent</color> <color name="qc_toggle_unavailable_color">#37FFFFFF</color> <color name="qc_toggle_rotary_shadow_color">#C7000000</color> -</resources>
\ No newline at end of file + <!-- The SeekBar thumb color. --> + <color name="qc_seekbar_thumb">#FFFFFF</color> + <!-- The SeekBar thumb color when disabled. Use for the dark theme. --> + <color name="qc_seekbar_thumb_disabled_on_dark">#757575</color> + <!-- The Switch thumb color. --> + <color name="qc_switch_thumb_color">#FFFFFF</color> + <!-- The Switch thumb color when disabled. Use for the dark theme. --> + <color name="qc_switch_thumb_color_disabled_on_dark">#757575</color> +</resources> diff --git a/car-qc-lib/res/values/dimens.xml b/car-qc-lib/res/values/dimens.xml index b973774..912891f 100644 --- a/car-qc-lib/res/values/dimens.xml +++ b/car-qc-lib/res/values/dimens.xml @@ -24,7 +24,8 @@ <dimen name="qc_row_content_margin">16dp</dimen> <dimen name="qc_action_items_horizontal_margin">32dp</dimen> - <dimen name="qc_toggle_size">72dp</dimen> + <dimen name="qc_toggle_size">80dp</dimen> + <dimen name="qc_toggle_background_size">72dp</dimen> <dimen name="qc_toggle_margin">12dp</dimen> <dimen name="qc_row_horizontal_margin">16dp</dimen> <dimen name="qc_toggle_background_radius">16dp</dimen> diff --git a/car-qc-lib/res/values/overlayable.xml b/car-qc-lib/res/values/overlayable.xml new file mode 100644 index 0000000..d5b405a --- /dev/null +++ b/car-qc-lib/res/values/overlayable.xml @@ -0,0 +1,87 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- + ~ Copyright (C) 2022 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<!-- +THIS FILE WAS AUTO GENERATED, DO NOT EDIT MANUALLY. +REGENERATE USING packages/apps/Car/tests/tools/rro/generate-overlayable.py +--> +<resources> + <overlayable name="car-qc-lib"> + <policy type="system|product|signature"> + <item type="attr" name="state_toggle_unavailable"/> + <item type="color" name="qc_start_icon_color"/> + <item type="color" name="qc_toggle_background_color"/> + <item type="color" name="qc_toggle_icon_fill_color"/> + <item type="color" name="qc_toggle_off_background_color"/> + <item type="color" name="qc_toggle_rotary_shadow_color"/> + <item type="color" name="qc_toggle_unavailable_background_color"/> + <item type="color" name="qc_toggle_unavailable_color"/> + <item type="dimen" name="qc_action_items_horizontal_margin"/> + <item type="dimen" name="qc_row_content_margin"/> + <item type="dimen" name="qc_row_horizontal_margin"/> + <item type="dimen" name="qc_row_icon_margin_end"/> + <item type="dimen" name="qc_row_icon_size"/> + <item type="dimen" name="qc_row_margin_vertical"/> + <item type="dimen" name="qc_row_min_height"/> + <item type="dimen" name="qc_row_padding_end"/> + <item type="dimen" name="qc_row_padding_start"/> + <item type="dimen" name="qc_seekbar_padding_top"/> + <item type="dimen" name="qc_toggle_background_padding"/> + <item type="dimen" name="qc_toggle_background_radius"/> + <item type="dimen" name="qc_toggle_foreground_icon_inset"/> + <item type="dimen" name="qc_toggle_margin"/> + <item type="dimen" name="qc_toggle_rotary_highlight_radius"/> + <item type="dimen" name="qc_toggle_rotary_highlight_size"/> + <item type="dimen" name="qc_toggle_rotary_shadow_padding"/> + <item type="dimen" name="qc_toggle_rotary_shadow_radius"/> + <item type="dimen" name="qc_toggle_rotary_shadow_size"/> + <item type="dimen" name="qc_toggle_rotary_shadow_width"/> + <item type="dimen" name="qc_toggle_background_size"/> + <item type="dimen" name="qc_toggle_size"/> + <item type="dimen" name="qc_toggle_unavailable_outline_width"/> + <item type="drawable" name="qc_row_action_divider"/> + <item type="drawable" name="qc_seekbar_wrapper_background"/> + <item type="drawable" name="qc_toggle_background"/> + <item type="drawable" name="qc_toggle_button_background"/> + <item type="drawable" name="qc_toggle_rotary_background"/> + <item type="drawable" name="qc_toggle_rotary_highlight"/> + <item type="drawable" name="qc_toggle_rotary_shadow"/> + <item type="drawable" name="qc_toggle_unavailable_background"/> + <item type="id" name="barrier1"/> + <item type="id" name="barrier2"/> + <item type="id" name="qc_icon"/> + <item type="id" name="qc_row_content"/> + <item type="id" name="qc_row_end_items"/> + <item type="id" name="qc_row_start_items"/> + <item type="id" name="qc_seekbar"/> + <item type="id" name="qc_seekbar_wrapper"/> + <item type="id" name="qc_summary"/> + <item type="id" name="qc_tile_toggle_button"/> + <item type="id" name="qc_tile_wrapper"/> + <item type="id" name="qc_title"/> + <item type="id" name="qc_toggle_button"/> + <item type="layout" name="qc_action_switch"/> + <item type="layout" name="qc_action_toggle"/> + <item type="layout" name="qc_row_view"/> + <item type="layout" name="qc_tile_view"/> + <item type="style" name="TextAppearance.QC"/> + <item type="style" name="TextAppearance.QC.Subtitle"/> + <item type="style" name="TextAppearance.QC.Title"/> + <item type="style" name="Widget.QC"/> + <item type="style" name="Widget.QC.SeekBar"/> + </policy> + </overlayable> +</resources>
\ No newline at end of file diff --git a/car-qc-lib/src/com/android/car/qc/QCActionItem.java b/car-qc-lib/src/com/android/car/qc/QCActionItem.java index c476e09..b7b9cd1 100644 --- a/car-qc-lib/src/com/android/car/qc/QCActionItem.java +++ b/car-qc-lib/src/com/android/car/qc/QCActionItem.java @@ -17,11 +17,13 @@ package com.android.car.qc; import android.app.PendingIntent; +import android.content.Context; import android.graphics.drawable.Icon; import android.os.Parcel; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.StringRes; /** * Quick Control Action that are includes as either start or end actions in {@link QCRow} @@ -32,14 +34,17 @@ public class QCActionItem extends QCItem { private Icon mIcon; private PendingIntent mAction; private PendingIntent mDisabledClickAction; + private String mContentDescription; public QCActionItem(@NonNull @QCItemType String type, boolean isChecked, boolean isEnabled, boolean isAvailable, boolean isClickableWhileDisabled, @Nullable Icon icon, - @Nullable PendingIntent action, @Nullable PendingIntent disabledClickAction) { + @Nullable String contentDescription, @Nullable PendingIntent action, + @Nullable PendingIntent disabledClickAction) { super(type, isEnabled, isClickableWhileDisabled); mIsChecked = isChecked; mIsAvailable = isAvailable; mIcon = icon; + mContentDescription = contentDescription; mAction = action; mDisabledClickAction = disabledClickAction; } @@ -52,6 +57,10 @@ public class QCActionItem extends QCItem { if (hasIcon) { mIcon = Icon.CREATOR.createFromParcel(in); } + boolean hasContentDescription = in.readBoolean(); + if (hasContentDescription) { + mContentDescription = in.readString(); + } boolean hasAction = in.readBoolean(); if (hasAction) { mAction = PendingIntent.CREATOR.createFromParcel(in); @@ -72,6 +81,11 @@ public class QCActionItem extends QCItem { if (includeIcon) { mIcon.writeToParcel(dest, flags); } + boolean hasContentDescription = mContentDescription != null; + dest.writeBoolean(hasContentDescription); + if (hasContentDescription) { + dest.writeString(mContentDescription); + } boolean hasAction = mAction != null; dest.writeBoolean(hasAction); if (hasAction) { @@ -107,6 +121,11 @@ public class QCActionItem extends QCItem { return mIcon; } + @Nullable + public String getContentDescription() { + return mContentDescription; + } + public static Creator<QCActionItem> CREATOR = new Creator<QCActionItem>() { @Override public QCActionItem createFromParcel(Parcel source) { @@ -131,6 +150,7 @@ public class QCActionItem extends QCItem { private Icon mIcon; private PendingIntent mAction; private PendingIntent mDisabledClickAction; + private String mContentDescription; public Builder(@NonNull @QCItemType String type) { if (!isValidType(type)) { @@ -180,6 +200,23 @@ public class QCActionItem extends QCItem { } /** + * Sets the content description + */ + public Builder setContentDescription(@Nullable String contentDescription) { + mContentDescription = contentDescription; + return this; + } + + /** + * Sets the string resource to use for content description + */ + public Builder setContentDescription(@NonNull Context context, + @StringRes int contentDescriptionResId) { + mContentDescription = context.getString(contentDescriptionResId); + return this; + } + + /** * Sets the PendingIntent to be sent when the action item is clicked. */ public Builder setAction(@Nullable PendingIntent action) { @@ -200,7 +237,8 @@ public class QCActionItem extends QCItem { */ public QCActionItem build() { return new QCActionItem(mType, mIsChecked, mIsEnabled, mIsAvailable, - mIsClickableWhileDisabled, mIcon, mAction, mDisabledClickAction); + mIsClickableWhileDisabled, mIcon, mContentDescription, mAction, + mDisabledClickAction); } private boolean isValidType(String type) { diff --git a/car-qc-lib/src/com/android/car/qc/provider/BaseQCProvider.java b/car-qc-lib/src/com/android/car/qc/provider/BaseQCProvider.java index 61db361..8e9e550 100644 --- a/car-qc-lib/src/com/android/car/qc/provider/BaseQCProvider.java +++ b/car-qc-lib/src/com/android/car/qc/provider/BaseQCProvider.java @@ -172,7 +172,11 @@ public abstract class BaseQCProvider extends ContentProvider { try { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectAll() - .penaltyDeath() + + // TODO(268275789): Revert back to penaltyDeath and ensure it works in + // presubmit + .penaltyLog() + .build()); return onBind(uri); } finally { diff --git a/car-qc-lib/src/com/android/car/qc/view/QCRowView.java b/car-qc-lib/src/com/android/car/qc/view/QCRowView.java index 1e10e4b..2b6b7a5 100644 --- a/car-qc-lib/src/com/android/car/qc/view/QCRowView.java +++ b/car-qc-lib/src/com/android/car/qc/view/QCRowView.java @@ -193,7 +193,7 @@ public class QCRowView extends FrameLayout { mStartItemsContainer = findViewById(R.id.qc_row_start_items); mEndItemsContainer = findViewById(R.id.qc_row_end_items); mSeekBarContainer = findViewById(R.id.qc_seekbar_wrapper); - mSeekBar = findViewById(R.id.seekbar); + mSeekBar = findViewById(R.id.qc_seekbar); } void setActionListener(QCActionListener listener) { @@ -311,7 +311,10 @@ public class QCRowView extends FrameLayout { (action.isEnabled() || action.isClickableWhileDisabled()) && action.isAvailable(); switchView.setOnCheckedChangeListener(null); switchView.setEnabled(shouldEnableView); + switchView.setThumbTintList(getContext().getColorStateList( + R.color.qc_switch_thumb_selector)); switchView.setChecked(action.isChecked()); + switchView.setContentDescription(action.getContentDescription()); switchView.setOnTouchListener((v, event) -> { if (!action.isEnabled()) { if (event.getActionMasked() == MotionEvent.ACTION_UP) { @@ -345,6 +348,7 @@ public class QCRowView extends FrameLayout { toggleButton.setOnCheckedChangeListener(null); Drawable icon = QCViewUtils.getInstance(mContext).getToggleIcon( action.getIcon(), action.isAvailable()); + toggleButton.setContentDescription(action.getContentDescription()); toggleButton.setButtonDrawable(icon); toggleButton.setChecked(action.isChecked()); toggleButton.setEnabled(shouldEnableView); @@ -397,13 +401,15 @@ public class QCRowView extends FrameLayout { // remove current action view root.removeView(actionView); } - actionView = mLayoutInflater.inflate(resId, /* root= */ null); + actionView = mLayoutInflater.inflate(resId, root, /* attachToRoot= */ false); root.addView(actionView); return actionView; } private void initSlider(QCSlider slider) { mQCSlider = slider; + CarUiUtils.makeAllViewsEnabled(mSeekBar, slider.isEnabled()); + mSeekBar.setOnSeekBarChangeListener(null); mSeekBar.setMin(slider.getMin()); mSeekBar.setMax(slider.getMax()); @@ -411,6 +417,8 @@ public class QCRowView extends FrameLayout { mSeekBar.setEnabled(slider.isEnabled()); mSeekBar.setClickableWhileDisabled(slider.isClickableWhileDisabled()); mSeekBar.setDisabledClickListener(seekBar -> fireAction(slider, new Intent())); + mSeekBar.setThumbTintList(getContext().getColorStateList( + R.color.qc_seekbar_thumb_selector)); if (!slider.isEnabled() && mInDirectManipulationMode) { setInDirectManipulationMode(mSeekBarContainer, mSeekBar, false); } diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/QCActionItemTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/QCActionItemTest.java index ff70540..c945301 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/QCActionItemTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/QCActionItemTest.java @@ -33,32 +33,34 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class QCActionItemTest extends QCItemTestCase<QCActionItem> { + private static final String TEST_CONTENT_DESCRIPTION = "test_content_description"; @Test public void onCreate_invalidType_throwsException() { assertThrows(IllegalArgumentException.class, () -> createAction("INVALID_TYPE", /* action= */ null, - /* disabledAction= */ null, /* icon= */ null)); + /* disabledAction= */ null, /* icon= */ null, /* contentDescription=*/ + null)); } @Test public void onCreateSwitch_hasCorrectType() { QCActionItem action = createAction(QC_TYPE_ACTION_SWITCH, /* action= */ null, - /* disabledAction= */ null, /* icon= */null); + /* disabledAction= */ null, /* icon= */null, /* contentDescription=*/ null); assertThat(action.getType()).isEqualTo(QC_TYPE_ACTION_SWITCH); } @Test public void onCreateToggle_hasCorrectType() { QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, /* action= */ null, - /* disabledAction= */ null, /* icon= */ null); + /* disabledAction= */ null, /* icon= */ null, /* contentDescription=*/ null); assertThat(action.getType()).isEqualTo(QC_TYPE_ACTION_TOGGLE); } @Test public void onBundle_nullActions_noCrash() { QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, /* action= */ null, - /* disabledAction= */ null, mDefaultIcon); + /* disabledAction= */ null, mDefaultIcon, /* contentDescription=*/ null); writeAndLoadFromBundle(action); // Test passes if this doesn't crash } @@ -66,7 +68,7 @@ public class QCActionItemTest extends QCItemTestCase<QCActionItem> { @Test public void onBundle_nullIcon_noCrash() { QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, mDefaultAction, - mDefaultDisabledAction, /* icon= */ null); + mDefaultDisabledAction, /* icon= */ null, /* contentDescription=*/ null); writeAndLoadFromBundle(action); // Test passes if this doesn't crash } @@ -74,7 +76,7 @@ public class QCActionItemTest extends QCItemTestCase<QCActionItem> { @Test public void onBundle_switch_accurateData() { QCActionItem action = createAction(QC_TYPE_ACTION_SWITCH, mDefaultAction, - mDefaultDisabledAction, /* icon= */ null); + mDefaultDisabledAction, /* icon= */ null, TEST_CONTENT_DESCRIPTION); QCActionItem newAction = writeAndLoadFromBundle(action); assertThat(newAction.getType()).isEqualTo(QC_TYPE_ACTION_SWITCH); assertThat(newAction.isChecked()).isTrue(); @@ -82,12 +84,13 @@ public class QCActionItemTest extends QCItemTestCase<QCActionItem> { assertThat(newAction.isClickableWhileDisabled()).isFalse(); assertThat(newAction.getPrimaryAction()).isNotNull(); assertThat(newAction.getIcon()).isNull(); + assertThat(newAction.getContentDescription()).isEqualTo(TEST_CONTENT_DESCRIPTION); } @Test public void onBundle_toggle_accurateDate() { QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, mDefaultAction, - mDefaultDisabledAction, mDefaultIcon); + mDefaultDisabledAction, mDefaultIcon, TEST_CONTENT_DESCRIPTION); QCActionItem newAction = writeAndLoadFromBundle(action); assertThat(newAction.getType()).isEqualTo(QC_TYPE_ACTION_TOGGLE); assertThat(newAction.isChecked()).isTrue(); @@ -95,16 +98,18 @@ public class QCActionItemTest extends QCItemTestCase<QCActionItem> { assertThat(newAction.isClickableWhileDisabled()).isFalse(); assertThat(newAction.getPrimaryAction()).isNotNull(); assertThat(newAction.getIcon()).isNotNull(); + assertThat(newAction.getContentDescription()).isEqualTo(TEST_CONTENT_DESCRIPTION); } private QCActionItem createAction(String type, PendingIntent action, - PendingIntent disabledAction, Icon icon) { + PendingIntent disabledAction, Icon icon, String contentDescription) { return new QCActionItem.Builder(type) .setChecked(true) .setEnabled(true) .setAction(action) .setDisabledClickAction(disabledAction) .setIcon(icon) + .setContentDescription(contentDescription) .build(); } } diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCRowViewTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCRowViewTest.java index 647317a..9c1aa79 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCRowViewTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCRowViewTest.java @@ -30,12 +30,14 @@ import static org.mockito.Mockito.verify; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.content.res.ColorStateList; import android.graphics.drawable.Icon; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.SeekBar; +import android.widget.Switch; import android.widget.TextView; import androidx.test.annotation.UiThreadTest; @@ -203,11 +205,50 @@ public class QCRowViewTest { .addSlider(new QCSlider.Builder().setInputAction(action).build()) .build(); mView.setRow(row); - SeekBar seekBar = mView.findViewById(R.id.seekbar); + SeekBar seekBar = mView.findViewById(R.id.qc_seekbar); seekBar.setProgress(50); MotionEvent motionEvent = ExtendedMockito.mock(MotionEvent.class); ExtendedMockito.when(motionEvent.getAction()).thenReturn(MotionEvent.ACTION_UP); seekBar.onTouchEvent(motionEvent); verify(action).send(any(Context.class), anyInt(), any(Intent.class)); } + + @Test + @UiThreadTest + public void setRow_switchViewThumbTintList() { + PendingIntent action = mock(PendingIntent.class); + QCRow row = new QCRow.Builder() + .addEndItem( + new QCActionItem.Builder(QC_TYPE_ACTION_SWITCH).setAction(action).build()) + .build(); + mView.setRow(row); + LinearLayout endContainer = mView.findViewById(R.id.qc_row_end_items); + assertThat(endContainer.getChildCount()).isEqualTo(1); + Switch switchView = (Switch) endContainer.getChildAt(0); + assertThat(switchView.getThumbTintList()).isNotNull(); + + ColorStateList switchColorStateList = switchView.getThumbTintList(); + int[] enabledState = {android.R.attr.state_enabled}; + int[] disabledState = {-android.R.attr.state_enabled}; + assertThat(switchColorStateList.getColorForState(enabledState, 0)).isNotEqualTo( + switchColorStateList.getColorForState(disabledState, 0)); + } + + @Test + @UiThreadTest + public void setRow_sliderViewThumbTintList() { + PendingIntent action = mock(PendingIntent.class); + QCRow row = new QCRow.Builder() + .addSlider(new QCSlider.Builder().setInputAction(action).build()) + .build(); + mView.setRow(row); + SeekBar seekBar = mView.findViewById(R.id.qc_seekbar); + assertThat(seekBar.getThumbTintList()).isNotNull(); + + ColorStateList seekBarColorStateList = seekBar.getThumbTintList(); + int[] enabledState = {android.R.attr.state_enabled}; + int[] disabledState = {-android.R.attr.state_enabled}; + assertThat(seekBarColorStateList.getColorForState(enabledState, 0)).isNotEqualTo( + seekBarColorStateList.getColorForState(disabledState, 0)); + } } diff --git a/tools/rro/resource_utils.py b/tools/rro/resource_utils.py index 5f35e1a..fe4c52c 100644 --- a/tools/rro/resource_utils.py +++ b/tools/rro/resource_utils.py @@ -15,7 +15,11 @@ import os import re -import lxml.etree as etree +try: + import lxml.etree as etree +except ImportError: + print("Please install 'lxml' python package and retry.") + sys.exit(1) class ResourceLocation: def __init__(self, file, line=None): |