summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2023-08-14 15:41:37 -0700
committerXin Li <delphij@google.com>2023-08-14 15:41:37 -0700
commit515d4f6193ddb381303b3ce62cb108142a45c5f8 (patch)
treee76ffe4c398686600f5370565d5b0c785e3d9b02
parentdf2d0533ce500cb19a073de20117805f08856730 (diff)
parent829ee323b42695f6fb86ce1c0caa66bbbcd85a9c (diff)
downloadsystemlibs-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.xml22
-rw-r--r--car-qc-lib/res/color/qc_switch_thumb_selector.xml22
-rw-r--r--car-qc-lib/res/drawable/qc_toggle_background.xml4
-rw-r--r--car-qc-lib/res/drawable/qc_toggle_unavailable_background.xml4
-rw-r--r--car-qc-lib/res/layout/qc_row_view.xml2
-rw-r--r--car-qc-lib/res/values/colors.xml10
-rw-r--r--car-qc-lib/res/values/dimens.xml3
-rw-r--r--car-qc-lib/res/values/overlayable.xml87
-rw-r--r--car-qc-lib/src/com/android/car/qc/QCActionItem.java42
-rw-r--r--car-qc-lib/src/com/android/car/qc/provider/BaseQCProvider.java6
-rw-r--r--car-qc-lib/src/com/android/car/qc/view/QCRowView.java12
-rw-r--r--car-qc-lib/tests/unit/src/com/android/car/qc/QCActionItemTest.java21
-rw-r--r--car-qc-lib/tests/unit/src/com/android/car/qc/view/QCRowViewTest.java43
-rw-r--r--tools/rro/resource_utils.py6
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):