summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2024-03-06 09:30:04 -0800
committerXin Li <delphij@google.com>2024-03-06 09:30:04 -0800
commita4f26152ce629dfe0ff38fa85bcd2e00c1b1ecfd (patch)
treeda1c04ace825e3d5fab6f1933fe45d9d2e26e1ac
parent2c5f63adb20d9126bac628d5772ef4e63733859c (diff)
parentbdc50c111a744034880410725329a1a689ce39a0 (diff)
downloadsystemlibs-a4f26152ce629dfe0ff38fa85bcd2e00c1b1ecfd.tar.gz
Merge Android 14 QPR2 to AOSP main
Bug: 319669529 Merged-In: Idc7cb081e82d41792efd149330f89c2369edcf6b Change-Id: I472bd86a4e4704f4f3d541e995c17431df0c0d9c
-rw-r--r--car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramInfoExt.java19
-rw-r--r--car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramSelectorExt.java187
-rw-r--r--car-qc-lib/Android.bp1
-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/values/styles.xml11
-rw-r--r--car-qc-lib/src/com/android/car/qc/QCActionItem.java26
-rw-r--r--car-qc-lib/src/com/android/car/qc/view/QCRowView.java10
-rw-r--r--tools/rro/resource_utils.py4
9 files changed, 229 insertions, 73 deletions
diff --git a/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramInfoExt.java b/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramInfoExt.java
index d377dbd..c96521a 100644
--- a/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramInfoExt.java
+++ b/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramInfoExt.java
@@ -30,6 +30,7 @@ import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Comparator;
import java.util.Objects;
/**
@@ -171,8 +172,14 @@ public class ProgramInfoExt {
MediaMetadata.Builder bld = new MediaMetadata.Builder();
- ProgramSelector selector =
- ProgramSelectorExt.createAmFmSelector(info.getLogicallyTunedTo().getValue());
+ ProgramSelector selector;
+ ProgramSelector.Identifier logicallyTunedTo = info.getLogicallyTunedTo();
+ if (logicallyTunedTo != null && logicallyTunedTo.getType()
+ == ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY) {
+ selector = ProgramSelectorExt.createAmFmSelector(logicallyTunedTo.getValue());
+ } else {
+ selector = info.getSelector();
+ }
String displayTitle = ProgramSelectorExt.getDisplayName(selector, info.getChannel());
bld.putString(MediaMetadata.METADATA_KEY_DISPLAY_TITLE, displayTitle);
String subtitle = getProgramName(info, /* flags= */ 0, programNameOrder);
@@ -256,4 +263,12 @@ public class ProgramInfoExt {
}
return null;
}
+ public static class ProgramInfoComparator implements Comparator<RadioManager.ProgramInfo> {
+ @Override
+ public int compare(RadioManager.ProgramInfo info1, RadioManager.ProgramInfo info2) {
+ Comparator<ProgramSelector> selectorComparator =
+ new ProgramSelectorExt.ProgramSelectorComparator();
+ return selectorComparator.compare(info1.getSelector(), info2.getSelector());
+ }
+ }
}
diff --git a/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramSelectorExt.java b/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramSelectorExt.java
index 4b3583b..555176d 100644
--- a/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramSelectorExt.java
+++ b/car-broadcastradio-support/src/com/android/car/broadcastradio/support/platform/ProgramSelectorExt.java
@@ -29,6 +29,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.text.DecimalFormat;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -81,6 +82,11 @@ public class ProgramSelectorExt {
@Retention(RetentionPolicy.SOURCE)
public @interface NameFlag {}
+ /**
+ * Invalid value for a {@link ProgramSelector.Identifier}
+ */
+ public static int INVALID_IDENTIFIER_VALUE = 0;
+
private static final String URI_SCHEME_BROADCASTRADIO = "broadcastradio";
private static final String URI_AUTHORITY_PROGRAM = "program";
private static final String URI_VENDOR_PREFIX = "VENDOR_";
@@ -251,26 +257,81 @@ public class ProgramSelectorExt {
}
/**
+ * Get frequency from a {@link ProgramSelector}.
+ *
+ * @param selector Program selector
+ * @return frequency of the first {@link ProgramSelector#IDENTIFIER_TYPE_AMFM_FREQUENCY} id in
+ * program selector if it exists, otherwise the AM/FM frequency in
+ * {@link ProgramSelector#IDENTIFIER_TYPE_HD_STATION_ID_EXT} id if it is the primary id,
+ * {@link #INVALID_IDENTIFIER_VALUE} otherwise.
+ */
+ public static int getFrequency(@NonNull ProgramSelector selector) {
+ if (ProgramSelectorExt.hasId(selector, ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)) {
+ return (int) selector.getFirstId(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY);
+ } else if (selector.getPrimaryId().getType()
+ == ProgramSelector.IDENTIFIER_TYPE_HD_STATION_ID_EXT) {
+ return IdentifierExt.asHdPrimary(selector.getPrimaryId()).getFrequency();
+ } else if (selector.getPrimaryId().getType()
+ == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT
+ || selector.getPrimaryId().getType()
+ == ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT) {
+ try {
+ return (int) selector.getFirstId(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY);
+ } catch (IllegalArgumentException e) {
+ return INVALID_IDENTIFIER_VALUE;
+ }
+ }
+ return INVALID_IDENTIFIER_VALUE;
+ }
+
+ /**
+ * Get ensemble value from a DAB-type {@link ProgramSelector}.
+ *
+ * @param selector Program selector
+ * @return Value of the first {@link ProgramSelector#IDENTIFIER_TYPE_DAB_ENSEMBLE} identifier,
+ * 0 otherwise
+ */
+ public static int getDabEnsemble(@NonNull ProgramSelector selector) {
+ try {
+ return (int) selector.getFirstId(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE);
+ } catch (IllegalArgumentException e) {
+ return INVALID_IDENTIFIER_VALUE;
+ }
+ }
+
+ /**
* Returns a channel name that can be displayed to the user.
*
- * It's implemented only for radio technologies where the channel is meant
- * to be presented to the user.
+ * <p>It's implemented only for radio technologies where the channel is meant
+ * to be presented to the user, such as FM/AM and HD radio.
+ *
+ * <p>For HD radio, the display name is prefix with "-HD[NUMBER]" where the number is the
+ * sub channel.
*
* @param sel the program selector
- * @return Channel name or null, if radio technology doesn't present channel names to the user.
+ * @return Channel name or {@code null}, if radio technology doesn't present channel names to
+ * the user.
*/
public static @Nullable String getDisplayName(@NonNull ProgramSelector sel,
@NameFlag int flags) {
boolean noProgramTypeFallback = (flags & NAME_NO_PROGRAM_TYPE_FALLBACK) != 0;
if (isAmFmProgram(sel)) {
- if (!hasId(sel, ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)) {
+ long freq;
+ String hdSuffix = "";
+ if (sel.getPrimaryId().getType()
+ == ProgramSelector.IDENTIFIER_TYPE_HD_STATION_ID_EXT) {
+ IdentifierExt.HdPrimary hdIdExt = IdentifierExt.asHdPrimary(sel.getPrimaryId());
+ freq = hdIdExt.getFrequency();
+ hdSuffix = "-HD" + (hdIdExt.getSubchannel() + 1);
+ } else if (hasId(sel, ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)) {
+ freq = sel.getFirstId(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY);
+ } else {
if (noProgramTypeFallback) return null;
// if there is no frequency assigned, let's assume it's a malformed RDS selector
return "FM";
}
- long freq = sel.getFirstId(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY);
- return formatAmFmFrequency(freq, flags);
+ return formatAmFmFrequency(freq, flags) + hdSuffix;
}
if ((flags & NAME_MODULATION_ONLY) != 0) return null;
@@ -285,7 +346,8 @@ public class ProgramSelectorExt {
switch (sel.getPrimaryId().getType()) {
case ProgramSelector.IDENTIFIER_TYPE_SXM_SERVICE_ID:
return "SXM";
- case ProgramSelector.IDENTIFIER_TYPE_DAB_SIDECC:
+ case ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT:
+ case ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT:
return "DAB";
case ProgramSelector.IDENTIFIER_TYPE_DRMO_SERVICE_ID:
return "DRMO";
@@ -442,10 +504,10 @@ public class ProgramSelectorExt {
*/
public static class IdentifierExt {
/**
- * Decode {@link ProgramSelector#IDENTIFIER_TYPE_HD_STATION_ID_EXT} value.
+ * Decoder of {@link ProgramSelector#IDENTIFIER_TYPE_HD_STATION_ID_EXT} value.
*
- * @param id identifier to decode
- * @return value decoder
+ * When pushed to the framework, it will be non-static class referring
+ * to the original value.
*/
public static @Nullable HdPrimary asHdPrimary(@NonNull Identifier id) {
if (id.getType() == ProgramSelector.IDENTIFIER_TYPE_HD_STATION_ID_EXT) {
@@ -482,5 +544,110 @@ public class ProgramSelectorExt {
return (int) ((mValue >>> (32 + 4)) & 0x3FFFF);
}
}
+
+ /**
+ * Decoder of {@link ProgramSelector#IDENTIFIER_TYPE_DAB_DMB_SID_EXT} value.
+ *
+ * <p>When pushed to the framework, it will be non-static class referring
+ * to the original value.
+ * @param id Identifier to be decoded
+ * @return {@link DabPrimary} object if the identifier is DAB-type, {@code null} otherwise
+ */
+ public static @Nullable DabPrimary asDabPrimary(@NonNull Identifier id) {
+ if (id.getType() == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT) {
+ return new DabPrimary(id.getValue());
+ }
+ return null;
+ }
+
+ /**
+ * Decoder of {@link ProgramSelector#IDENTIFIER_TYPE_DAB_DMB_SID_EXT} value.
+ *
+ * <p>When pushed to the framework, it will be non-static class referring
+ * to the original value.
+ */
+ public static class DabPrimary {
+ private final long mValue;
+
+ private DabPrimary(long value) {
+ mValue = value;
+ }
+
+ /**
+ * Get Service Identifier (SId).
+ * @return SId value
+ */
+ public int getSId() {
+ return (int) (mValue & 0xFFFFFFFF);
+ }
+
+ /**
+ * Get Extended Country Code (ECC)
+ * @return Extended Country Code
+ */
+ public int getEcc() {
+ return (int) ((mValue >>> 32) & 0xFF);
+ }
+
+ /**
+ * Get SCIdS (Service Component Identifier within the Service) value
+ * @return SCIdS value
+ */
+ public int getSCIdS() {
+ return (int) ((mValue >>> (32 + 8)) & 0xF);
+ }
+ }
+ }
+
+ public static class ProgramSelectorComparator implements Comparator<ProgramSelector> {
+ @Override
+ public int compare(ProgramSelector selector1, ProgramSelector selector2) {
+ int type1 = selector1.getPrimaryId().getType();
+ int type2 = selector2.getPrimaryId().getType();
+ int frequency1 = getFrequency(selector1);
+ int frequency2 = getFrequency(selector2);
+ if (isAmFmProgram(selector1) && isAmFmProgram(selector2)) {
+ if (frequency1 != frequency2) {
+ return frequency1 > frequency2 ? 1 : -1;
+ }
+ int subchannel1 = selector1.getPrimaryId().getType()
+ == ProgramSelector.IDENTIFIER_TYPE_HD_STATION_ID_EXT
+ ? IdentifierExt.asHdPrimary(selector1.getPrimaryId()).getSubchannel() : 0;
+ int subchannel2 = selector2.getPrimaryId().getType()
+ == ProgramSelector.IDENTIFIER_TYPE_HD_STATION_ID_EXT
+ ? IdentifierExt.asHdPrimary(selector2.getPrimaryId()).getSubchannel() : 0;
+ if (subchannel1 != subchannel2) {
+ return subchannel1 > subchannel2 ? 1 : -1;
+ }
+ return selector1.getPrimaryId().getType() - selector2.getPrimaryId().getType();
+ } else if (type1 == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT
+ && type2 == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT) {
+ if (frequency1 != frequency2) {
+ return frequency1 > frequency2 ? 1 : -1;
+ }
+ IdentifierExt.DabPrimary dabPrimary1 = IdentifierExt.asDabPrimary(
+ selector1.getPrimaryId());
+ IdentifierExt.DabPrimary dabPrimary2 = IdentifierExt.asDabPrimary(
+ selector2.getPrimaryId());
+ int ecc1 = dabPrimary1.getEcc();
+ int ecc2 = dabPrimary2.getEcc();
+ if (ecc1 != ecc2) {
+ return ecc1 > ecc2 ? 1 : -1;
+ }
+ int sId1 = dabPrimary1.getSId();
+ int sId2 = dabPrimary2.getSId();
+ if (sId1 != sId2) {
+ return sId1 > sId2 ? 1 : -1;
+ }
+ int sCIds1 = dabPrimary1.getSCIdS();
+ int sCIds2 = dabPrimary2.getSCIdS();
+ if (sCIds1 != sCIds2) {
+ return sCIds1 > sCIds2 ? 1 : -1;
+ }
+ return getDabEnsemble(selector1) > getDabEnsemble(selector2) ? 1 : -1;
+ }
+ return type1 > type2 || (type1 == type2 && selector1.getPrimaryId().getValue()
+ > selector2.getPrimaryId().getValue()) ? 1 : -1;
+ }
}
}
diff --git a/car-qc-lib/Android.bp b/car-qc-lib/Android.bp
index 48b29d3..4d3a297 100644
--- a/car-qc-lib/Android.bp
+++ b/car-qc-lib/Android.bp
@@ -26,5 +26,6 @@ android_library {
static_libs: [
"androidx.annotation_annotation",
"car-ui-lib-no-overlayable",
+ "car-resource-common",
],
}
diff --git a/car-qc-lib/res/color/qc_seekbar_thumb_selector.xml b/car-qc-lib/res/color/qc_seekbar_thumb_selector.xml
deleted file mode 100644
index bf94a61..0000000
--- a/car-qc-lib/res/color/qc_seekbar_thumb_selector.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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
deleted file mode 100644
index e0bfc22..0000000
--- a/car-qc-lib/res/color/qc_switch_thumb_selector.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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/values/styles.xml b/car-qc-lib/res/values/styles.xml
index 587b522..51a7d35 100644
--- a/car-qc-lib/res/values/styles.xml
+++ b/car-qc-lib/res/values/styles.xml
@@ -16,16 +16,15 @@
<resources>
<style name="TextAppearance.QC" parent="android:TextAppearance.DeviceDefault">
- <item name="android:textColor">@color/car_ui_text_color_primary</item>
+ <item name="android:textColor">@color/car_on_surface</item>
</style>
- <style name="TextAppearance.QC.Title">
- <item name="android:textSize">@dimen/car_ui_body1_size</item>
+ <style name="TextAppearance.QC.Title" parent="android:TextAppearance.DeviceDefault.Large">
+ <item name="android:textColor">@color/car_on_surface</item>
</style>
- <style name="TextAppearance.QC.Subtitle">
- <item name="android:textColor">@color/car_ui_text_color_secondary</item>
- <item name="android:textSize">@dimen/car_ui_body3_size</item>
+ <style name="TextAppearance.QC.Subtitle" parent="android:TextAppearance.DeviceDefault.Small">
+ <item name="android:textColor">@color/car_on_surface_variant</item>
</style>
<style name="Widget.QC" parent="android:Widget.DeviceDefault"/>
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 b7b9cd1..f4e92d1 100644
--- a/car-qc-lib/src/com/android/car/qc/QCActionItem.java
+++ b/car-qc-lib/src/com/android/car/qc/QCActionItem.java
@@ -31,18 +31,20 @@ import androidx.annotation.StringRes;
public class QCActionItem extends QCItem {
private final boolean mIsChecked;
private final boolean mIsAvailable;
+ private final boolean mIsClickable;
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 String contentDescription, @Nullable PendingIntent action,
- @Nullable PendingIntent disabledClickAction) {
+ boolean isAvailable, boolean isClickable, boolean isClickableWhileDisabled,
+ @Nullable Icon icon, @Nullable String contentDescription,
+ @Nullable PendingIntent action, @Nullable PendingIntent disabledClickAction) {
super(type, isEnabled, isClickableWhileDisabled);
mIsChecked = isChecked;
mIsAvailable = isAvailable;
+ mIsClickable = isClickable;
mIcon = icon;
mContentDescription = contentDescription;
mAction = action;
@@ -53,6 +55,7 @@ public class QCActionItem extends QCItem {
super(in);
mIsChecked = in.readBoolean();
mIsAvailable = in.readBoolean();
+ mIsClickable = in.readBoolean();
boolean hasIcon = in.readBoolean();
if (hasIcon) {
mIcon = Icon.CREATOR.createFromParcel(in);
@@ -76,6 +79,7 @@ public class QCActionItem extends QCItem {
super.writeToParcel(dest, flags);
dest.writeBoolean(mIsChecked);
dest.writeBoolean(mIsAvailable);
+ dest.writeBoolean(mIsClickable);
boolean includeIcon = getType().equals(QC_TYPE_ACTION_TOGGLE) && mIcon != null;
dest.writeBoolean(includeIcon);
if (includeIcon) {
@@ -116,6 +120,10 @@ public class QCActionItem extends QCItem {
return mIsAvailable;
}
+ public boolean isClickable() {
+ return mIsClickable;
+ }
+
@Nullable
public Icon getIcon() {
return mIcon;
@@ -146,6 +154,7 @@ public class QCActionItem extends QCItem {
private boolean mIsChecked;
private boolean mIsEnabled = true;
private boolean mIsAvailable = true;
+ private boolean mIsClickable = true;
private boolean mIsClickableWhileDisabled = false;
private Icon mIcon;
private PendingIntent mAction;
@@ -184,6 +193,15 @@ public class QCActionItem extends QCItem {
}
/**
+ * Sets whether the action is clickable. This differs from available in that the style will
+ * remain as if it's enabled/available but click actions will not be processed.
+ */
+ public Builder setClickable(boolean clickable) {
+ mIsClickable = clickable;
+ return this;
+ }
+
+ /**
* Sets whether or not an action item should be clickable while disabled.
*/
public Builder setClickableWhileDisabled(boolean clickable) {
@@ -236,7 +254,7 @@ public class QCActionItem extends QCItem {
* Builds the final {@link QCActionItem}.
*/
public QCActionItem build() {
- return new QCActionItem(mType, mIsChecked, mIsEnabled, mIsAvailable,
+ return new QCActionItem(mType, mIsChecked, mIsEnabled, mIsAvailable, mIsClickable,
mIsClickableWhileDisabled, mIcon, mContentDescription, mAction,
mDisabledClickAction);
}
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 490615c..2045fd2 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
@@ -308,11 +308,10 @@ public class QCRowView extends FrameLayout {
CarUiUtils.makeAllViewsEnabled(switchView, action.isEnabled());
boolean shouldEnableView =
- (action.isEnabled() || action.isClickableWhileDisabled()) && action.isAvailable();
+ (action.isEnabled() || action.isClickableWhileDisabled()) && action.isAvailable()
+ && action.isClickable();
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) -> {
@@ -341,7 +340,8 @@ public class QCRowView extends FrameLayout {
}
DrawableStateToggleButton toggleButton = tmpToggleButton; // must be effectively final
boolean shouldEnableView =
- (action.isEnabled() || action.isClickableWhileDisabled()) && action.isAvailable();
+ (action.isEnabled() || action.isClickableWhileDisabled()) && action.isAvailable()
+ && action.isClickable();
toggleButton.setText(null);
toggleButton.setTextOn(null);
toggleButton.setTextOff(null);
@@ -416,8 +416,6 @@ 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/tools/rro/resource_utils.py b/tools/rro/resource_utils.py
index fe4c52c..003c69e 100644
--- a/tools/rro/resource_utils.py
+++ b/tools/rro/resource_utils.py
@@ -15,10 +15,12 @@
import os
import re
+import sys
try:
import lxml.etree as etree
except ImportError:
- print("Please install 'lxml' python package and retry.")
+ print("Please install 'lxml' python package and retry. \n"
+ + "E.g., you can use 'sudo apt-get install python3-lxml'.")
sys.exit(1)
class ResourceLocation: