diff options
author | Alex Stetson <alexstetson@google.com> | 2022-01-21 00:37:55 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-01-21 00:37:55 +0000 |
commit | c2018a67d9a447f4419dff322261193947336d37 (patch) | |
tree | c4684117508499f239082fd43a124601cd1d573c | |
parent | 22728dd9300cf942333e3b7d2f99a38f8622b9bf (diff) | |
parent | a1bd7f7593f3f346a81ce2721dfe8d862a49106a (diff) | |
download | systemlibs-c2018a67d9a447f4419dff322261193947336d37.tar.gz |
Add clickable while disabled functionality am: a1bd7f7593
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Car/libs/+/16286579
Change-Id: I94cb59068439563a4ce89604d43904741829eac1
19 files changed, 404 insertions, 88 deletions
diff --git a/car-qc-lib/res/layout/qc_action_switch.xml b/car-qc-lib/res/layout/qc_action_switch.xml index d51b61d..9ab57ba 100644 --- a/car-qc-lib/res/layout/qc_action_switch.xml +++ b/car-qc-lib/res/layout/qc_action_switch.xml @@ -14,9 +14,8 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<Switch +<com.android.car.ui.uxr.DrawableStateSwitch xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/switch_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" /> - diff --git a/car-qc-lib/res/layout/qc_row_view.xml b/car-qc-lib/res/layout/qc_row_view.xml index 5975426..3005175 100644 --- a/car-qc-lib/res/layout/qc_row_view.xml +++ b/car-qc-lib/res/layout/qc_row_view.xml @@ -120,7 +120,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@+id/barrier2" app:layout_constraintBottom_toBottomOf="parent"> - <SeekBar + <com.android.car.ui.uxr.DrawableStateSeekBar android:id="@+id/seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" 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 4c66bea..c476e09 100644 --- a/car-qc-lib/src/com/android/car/qc/QCActionItem.java +++ b/car-qc-lib/src/com/android/car/qc/QCActionItem.java @@ -28,25 +28,25 @@ import androidx.annotation.Nullable; */ public class QCActionItem extends QCItem { private final boolean mIsChecked; - private final boolean mIsEnabled; private final boolean mIsAvailable; private Icon mIcon; private PendingIntent mAction; + private PendingIntent mDisabledClickAction; public QCActionItem(@NonNull @QCItemType String type, boolean isChecked, boolean isEnabled, - boolean isAvailable, @Nullable Icon icon, @Nullable PendingIntent action) { - super(type); - mIsEnabled = isEnabled; + boolean isAvailable, boolean isClickableWhileDisabled, @Nullable Icon icon, + @Nullable PendingIntent action, @Nullable PendingIntent disabledClickAction) { + super(type, isEnabled, isClickableWhileDisabled); mIsChecked = isChecked; mIsAvailable = isAvailable; mIcon = icon; mAction = action; + mDisabledClickAction = disabledClickAction; } public QCActionItem(@NonNull Parcel in) { super(in); mIsChecked = in.readBoolean(); - mIsEnabled = in.readBoolean(); mIsAvailable = in.readBoolean(); boolean hasIcon = in.readBoolean(); if (hasIcon) { @@ -56,13 +56,16 @@ public class QCActionItem extends QCItem { if (hasAction) { mAction = PendingIntent.CREATOR.createFromParcel(in); } + boolean hasDisabledClickAction = in.readBoolean(); + if (hasDisabledClickAction) { + mDisabledClickAction = PendingIntent.CREATOR.createFromParcel(in); + } } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeBoolean(mIsChecked); - dest.writeBoolean(mIsEnabled); dest.writeBoolean(mIsAvailable); boolean includeIcon = getType().equals(QC_TYPE_ACTION_TOGGLE) && mIcon != null; dest.writeBoolean(includeIcon); @@ -74,6 +77,11 @@ public class QCActionItem extends QCItem { if (hasAction) { mAction.writeToParcel(dest, flags); } + boolean hasDisabledClickAction = mDisabledClickAction != null; + dest.writeBoolean(hasDisabledClickAction); + if (hasDisabledClickAction) { + mDisabledClickAction.writeToParcel(dest, flags); + } } @Override @@ -81,12 +89,13 @@ public class QCActionItem extends QCItem { return mAction; } - public boolean isChecked() { - return mIsChecked; + @Override + public PendingIntent getDisabledClickAction() { + return mDisabledClickAction; } - public boolean isEnabled() { - return mIsEnabled; + public boolean isChecked() { + return mIsChecked; } public boolean isAvailable() { @@ -118,8 +127,10 @@ public class QCActionItem extends QCItem { private boolean mIsChecked; private boolean mIsEnabled = true; private boolean mIsAvailable = true; + private boolean mIsClickableWhileDisabled = false; private Icon mIcon; private PendingIntent mAction; + private PendingIntent mDisabledClickAction; public Builder(@NonNull @QCItemType String type) { if (!isValidType(type)) { @@ -153,6 +164,14 @@ public class QCActionItem extends QCItem { } /** + * Sets whether or not an action item should be clickable while disabled. + */ + public Builder setClickableWhileDisabled(boolean clickable) { + mIsClickableWhileDisabled = clickable; + return this; + } + + /** * Sets the icon for {@link QC_TYPE_ACTION_TOGGLE} actions */ public Builder setIcon(@Nullable Icon icon) { @@ -169,10 +188,19 @@ public class QCActionItem extends QCItem { } /** + * Sets the PendingIntent to be sent when the action item is clicked while disabled. + */ + public Builder setDisabledClickAction(@Nullable PendingIntent action) { + mDisabledClickAction = action; + return this; + } + + /** * Builds the final {@link QCActionItem}. */ public QCActionItem build() { - return new QCActionItem(mType, mIsChecked, mIsEnabled, mIsAvailable, mIcon, mAction); + return new QCActionItem(mType, mIsChecked, mIsEnabled, mIsAvailable, + mIsClickableWhileDisabled, mIcon, mAction, mDisabledClickAction); } private boolean isValidType(String type) { diff --git a/car-qc-lib/src/com/android/car/qc/QCItem.java b/car-qc-lib/src/com/android/car/qc/QCItem.java index 77fe30f..c6826ae 100644 --- a/car-qc-lib/src/com/android/car/qc/QCItem.java +++ b/car-qc-lib/src/com/android/car/qc/QCItem.java @@ -57,14 +57,26 @@ public abstract class QCItem implements Parcelable { } private final String mType; + private final boolean mIsEnabled; + private final boolean mIsClickableWhileDisabled; private ActionHandler mActionHandler; + private ActionHandler mDisabledClickActionHandler; public QCItem(@NonNull @QCItemType String type) { + this(type, /* isEnabled= */true, /* isClickableWhileDisabled= */ false); + } + + public QCItem(@NonNull @QCItemType String type, boolean isEnabled, + boolean isClickableWhileDisabled) { mType = type; + mIsEnabled = isEnabled; + mIsClickableWhileDisabled = isClickableWhileDisabled; } public QCItem(@NonNull Parcel in) { mType = in.readString(); + mIsEnabled = in.readBoolean(); + mIsClickableWhileDisabled = in.readBoolean(); } @NonNull @@ -73,6 +85,14 @@ public abstract class QCItem implements Parcelable { return mType; } + public boolean isEnabled() { + return mIsEnabled; + } + + public boolean isClickableWhileDisabled() { + return mIsClickableWhileDisabled; + } + @Override public int describeContents() { return 0; @@ -81,17 +101,28 @@ public abstract class QCItem implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(mType); + dest.writeBoolean(mIsEnabled); + dest.writeBoolean(mIsClickableWhileDisabled); } public void setActionHandler(@Nullable ActionHandler handler) { mActionHandler = handler; } + public void setDisabledClickActionHandler(@Nullable ActionHandler handler) { + mDisabledClickActionHandler = handler; + } + @Nullable public ActionHandler getActionHandler() { return mActionHandler; } + @Nullable + public ActionHandler getDisabledClickActionHandler() { + return mDisabledClickActionHandler; + } + /** * Returns the PendingIntent that is sent when the item is clicked. */ @@ -99,6 +130,12 @@ public abstract class QCItem implements Parcelable { public abstract PendingIntent getPrimaryAction(); /** + * Returns the PendingIntent that is sent when the item is clicked while disabled. + */ + @Nullable + public abstract PendingIntent getDisabledClickAction(); + + /** * Action handler that can listen for an action to occur and notify listeners. */ public interface ActionHandler { diff --git a/car-qc-lib/src/com/android/car/qc/QCList.java b/car-qc-lib/src/com/android/car/qc/QCList.java index 250b5d8..0a19a93 100644 --- a/car-qc-lib/src/com/android/car/qc/QCList.java +++ b/car-qc-lib/src/com/android/car/qc/QCList.java @@ -60,6 +60,11 @@ public class QCList extends QCItem { return null; } + @Override + public PendingIntent getDisabledClickAction() { + return null; + } + @NonNull public List<QCRow> getRows() { return mRows; diff --git a/car-qc-lib/src/com/android/car/qc/QCRow.java b/car-qc-lib/src/com/android/car/qc/QCRow.java index deb4429..8d93295 100644 --- a/car-qc-lib/src/com/android/car/qc/QCRow.java +++ b/car-qc-lib/src/com/android/car/qc/QCRow.java @@ -44,15 +44,18 @@ public class QCRow extends QCItem { private final List<QCActionItem> mStartItems; private final List<QCActionItem> mEndItems; private final PendingIntent mPrimaryAction; + private PendingIntent mDisabledClickAction; - public QCRow(@Nullable String title, @Nullable String subtitle, - @Nullable PendingIntent primaryAction, @Nullable Icon startIcon, boolean isIconTintable, - @Nullable QCSlider slider, @NonNull List<QCActionItem> startItems, - @NonNull List<QCActionItem> endItems) { - super(QC_TYPE_ROW); + public QCRow(@Nullable String title, @Nullable String subtitle, boolean isEnabled, + boolean isClickableWhileDisabled, @Nullable PendingIntent primaryAction, + @Nullable PendingIntent disabledClickAction, @Nullable Icon startIcon, + boolean isIconTintable, @Nullable QCSlider slider, + @NonNull List<QCActionItem> startItems, @NonNull List<QCActionItem> endItems) { + super(QC_TYPE_ROW, isEnabled, isClickableWhileDisabled); mTitle = title; mSubtitle = subtitle; mPrimaryAction = primaryAction; + mDisabledClickAction = disabledClickAction; mStartIcon = startIcon; mIsStartIconTintable = isIconTintable; mSlider = slider; @@ -95,6 +98,12 @@ public class QCRow extends QCItem { } else { mPrimaryAction = null; } + boolean hasDisabledClickAction = in.readBoolean(); + if (hasDisabledClickAction) { + mDisabledClickAction = PendingIntent.CREATOR.createFromParcel(in); + } else { + mDisabledClickAction = null; + } } @Override @@ -121,11 +130,16 @@ public class QCRow extends QCItem { for (QCActionItem endItem : mEndItems) { endItem.writeToParcel(dest, flags); } - dest.writeBoolean(mPrimaryAction != null); boolean hasPrimaryAction = mPrimaryAction != null; + dest.writeBoolean(hasPrimaryAction); if (hasPrimaryAction) { mPrimaryAction.writeToParcel(dest, flags); } + boolean hasDisabledClickAction = mDisabledClickAction != null; + dest.writeBoolean(hasDisabledClickAction); + if (hasDisabledClickAction) { + mDisabledClickAction.writeToParcel(dest, flags); + } } @Override @@ -133,6 +147,11 @@ public class QCRow extends QCItem { return mPrimaryAction; } + @Override + public PendingIntent getDisabledClickAction() { + return mDisabledClickAction; + } + @Nullable public String getTitle() { return mTitle; @@ -189,8 +208,11 @@ public class QCRow extends QCItem { private boolean mIsStartIconTintable = true; private String mTitle; private String mSubtitle; + private boolean mIsEnabled = true; + private boolean mIsClickableWhileDisabled = false; private QCSlider mSlider; private PendingIntent mPrimaryAction; + private PendingIntent mDisabledClickAction; /** * Sets the row title. @@ -209,6 +231,23 @@ public class QCRow extends QCItem { } /** + * Sets whether or not the row is enabled. Note that this only affects the main row area, + * not the action items contained within the row. + */ + public Builder setEnabled(boolean enabled) { + mIsEnabled = enabled; + return this; + } + + /** + * Sets whether or not the row should be clickable while disabled. + */ + public Builder setClickableWhileDisabled(boolean clickable) { + mIsClickableWhileDisabled = clickable; + return this; + } + + /** * Sets the row icon. */ public Builder setIcon(@Nullable Icon icon) { @@ -241,6 +280,14 @@ public class QCRow extends QCItem { } /** + * Sets the PendingIntent to be sent when the action item is clicked while disabled. + */ + public Builder setDisabledClickAction(@Nullable PendingIntent action) { + mDisabledClickAction = action; + return this; + } + + /** * Adds a {@link QCActionItem} to the start items area. */ public Builder addStartItem(@NonNull QCActionItem item) { @@ -260,7 +307,8 @@ public class QCRow extends QCItem { * Builds the final {@link QCRow}. */ public QCRow build() { - return new QCRow(mTitle, mSubtitle, mPrimaryAction, mStartIcon, mIsStartIconTintable, + return new QCRow(mTitle, mSubtitle, mIsEnabled, mIsClickableWhileDisabled, + mPrimaryAction, mDisabledClickAction, mStartIcon, mIsStartIconTintable, mSlider, mStartItems, mEndItems); } } diff --git a/car-qc-lib/src/com/android/car/qc/QCSlider.java b/car-qc-lib/src/com/android/car/qc/QCSlider.java index 16be5e7..612274b 100644 --- a/car-qc-lib/src/com/android/car/qc/QCSlider.java +++ b/car-qc-lib/src/com/android/car/qc/QCSlider.java @@ -30,13 +30,16 @@ public class QCSlider extends QCItem { private int mMax = 100; private int mValue = 0; private PendingIntent mInputAction; + private PendingIntent mDisabledClickAction; - public QCSlider(int min, int max, int value, @Nullable PendingIntent inputAction) { - super(QC_TYPE_SLIDER); + public QCSlider(int min, int max, int value, boolean enabled, boolean clickableWhileDisabled, + @Nullable PendingIntent inputAction, @Nullable PendingIntent disabledClickAction) { + super(QC_TYPE_SLIDER, enabled, clickableWhileDisabled); mMin = min; mMax = max; mValue = value; mInputAction = inputAction; + mDisabledClickAction = disabledClickAction; } public QCSlider(@NonNull Parcel in) { @@ -48,6 +51,10 @@ public class QCSlider extends QCItem { if (hasAction) { mInputAction = PendingIntent.CREATOR.createFromParcel(in); } + boolean hasDisabledClickAction = in.readBoolean(); + if (hasDisabledClickAction) { + mDisabledClickAction = PendingIntent.CREATOR.createFromParcel(in); + } } @Override @@ -61,6 +68,11 @@ public class QCSlider extends QCItem { if (hasAction) { mInputAction.writeToParcel(dest, flags); } + boolean hasDisabledClickAction = mDisabledClickAction != null; + dest.writeBoolean(hasDisabledClickAction); + if (hasDisabledClickAction) { + mDisabledClickAction.writeToParcel(dest, flags); + } } @Override @@ -68,6 +80,11 @@ public class QCSlider extends QCItem { return mInputAction; } + @Override + public PendingIntent getDisabledClickAction() { + return mDisabledClickAction; + } + public int getMin() { return mMin; } @@ -99,7 +116,10 @@ public class QCSlider extends QCItem { private int mMin = 0; private int mMax = 100; private int mValue = 0; + private boolean mIsEnabled = true; + private boolean mIsClickableWhileDisabled = false; private PendingIntent mInputAction; + private PendingIntent mDisabledClickAction; /** * Set the minimum allowed value for the slider input. @@ -126,6 +146,23 @@ public class QCSlider extends QCItem { } /** + * Sets whether or not the slider is enabled. + */ + public Builder setEnabled(boolean enabled) { + mIsEnabled = enabled; + return this; + } + + /** + * Sets whether or not a slider should be clickable while disabled. + */ + public Builder setClickableWhileDisabled(boolean clickable) { + mIsClickableWhileDisabled = clickable; + return this; + } + + + /** * Set the PendingIntent to be sent when the slider value is changed. */ public Builder setInputAction(@Nullable PendingIntent inputAction) { @@ -134,10 +171,19 @@ public class QCSlider extends QCItem { } /** + * Sets the PendingIntent to be sent when the action item is clicked while disabled. + */ + public Builder setDisabledClickAction(@Nullable PendingIntent action) { + mDisabledClickAction = action; + return this; + } + + /** * Builds the final {@link QCSlider}. */ public QCSlider build() { - return new QCSlider(mMin, mMax, mValue, mInputAction); + return new QCSlider(mMin, mMax, mValue, mIsEnabled, mIsClickableWhileDisabled, + mInputAction, mDisabledClickAction); } } } diff --git a/car-qc-lib/src/com/android/car/qc/QCTile.java b/car-qc-lib/src/com/android/car/qc/QCTile.java index 5f891e6..9ae22e9 100644 --- a/car-qc-lib/src/com/android/car/qc/QCTile.java +++ b/car-qc-lib/src/com/android/car/qc/QCTile.java @@ -34,27 +34,27 @@ import androidx.annotation.Nullable; */ public class QCTile extends QCItem { private final boolean mIsChecked; - private final boolean mIsEnabled; private final boolean mIsAvailable; private final String mSubtitle; private Icon mIcon; private PendingIntent mAction; + private PendingIntent mDisabledClickAction; public QCTile(boolean isChecked, boolean isEnabled, boolean isAvailable, - @Nullable String subtitle, @Nullable Icon icon, @Nullable PendingIntent action) { - super(QC_TYPE_TILE); - mIsEnabled = isEnabled; + boolean isClickableWhileDisabled, @Nullable String subtitle, @Nullable Icon icon, + @Nullable PendingIntent action, @Nullable PendingIntent disabledClickAction) { + super(QC_TYPE_TILE, isEnabled, isClickableWhileDisabled); mIsChecked = isChecked; mIsAvailable = isAvailable; mSubtitle = subtitle; mIcon = icon; mAction = action; + mDisabledClickAction = disabledClickAction; } public QCTile(@NonNull Parcel in) { super(in); mIsChecked = in.readBoolean(); - mIsEnabled = in.readBoolean(); mIsAvailable = in.readBoolean(); mSubtitle = in.readString(); boolean hasIcon = in.readBoolean(); @@ -65,13 +65,16 @@ public class QCTile extends QCItem { if (hasAction) { mAction = PendingIntent.CREATOR.createFromParcel(in); } + boolean hasDisabledClickAction = in.readBoolean(); + if (hasDisabledClickAction) { + mDisabledClickAction = PendingIntent.CREATOR.createFromParcel(in); + } } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeBoolean(mIsChecked); - dest.writeBoolean(mIsEnabled); dest.writeBoolean(mIsAvailable); dest.writeString(mSubtitle); boolean hasIcon = mIcon != null; @@ -84,6 +87,11 @@ public class QCTile extends QCItem { if (hasAction) { mAction.writeToParcel(dest, flags); } + boolean hasDisabledClickAction = mDisabledClickAction != null; + dest.writeBoolean(hasDisabledClickAction); + if (hasDisabledClickAction) { + mDisabledClickAction.writeToParcel(dest, flags); + } } @Override @@ -91,12 +99,13 @@ public class QCTile extends QCItem { return mAction; } - public boolean isChecked() { - return mIsChecked; + @Override + public PendingIntent getDisabledClickAction() { + return mDisabledClickAction; } - public boolean isEnabled() { - return mIsEnabled; + public boolean isChecked() { + return mIsChecked; } public boolean isAvailable() { @@ -132,9 +141,11 @@ public class QCTile extends QCItem { private boolean mIsChecked; private boolean mIsEnabled = true; private boolean mIsAvailable = true; + private boolean mIsClickableWhileDisabled = false; private String mSubtitle; private Icon mIcon; private PendingIntent mAction; + private PendingIntent mDisabledClickAction; /** * Sets whether or not the tile should be checked. @@ -161,6 +172,14 @@ public class QCTile extends QCItem { } /** + * Sets whether or not a tile should be clickable while disabled. + */ + public Builder setClickableWhileDisabled(boolean clickable) { + mIsClickableWhileDisabled = clickable; + return this; + } + + /** * Sets the tile's subtitle. */ public Builder setSubtitle(@Nullable String subtitle) { @@ -185,10 +204,19 @@ public class QCTile extends QCItem { } /** + * Sets the PendingIntent to be sent when the action item is clicked while disabled. + */ + public Builder setDisabledClickAction(@Nullable PendingIntent action) { + mDisabledClickAction = action; + return this; + } + + /** * Builds the final {@link QCTile}. */ public QCTile build() { - return new QCTile(mIsChecked, mIsEnabled, mIsAvailable, mSubtitle, mIcon, mAction); + return new QCTile(mIsChecked, mIsEnabled, mIsAvailable, mIsClickableWhileDisabled, + mSubtitle, mIcon, 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 14d4b19..e4c3aa3 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 @@ -53,6 +53,7 @@ import com.android.car.qc.QCItem; import com.android.car.qc.QCRow; import com.android.car.qc.QCSlider; import com.android.car.qc.R; +import com.android.car.ui.utils.CarUiUtils; import com.android.car.ui.utils.DirectManipulationHelper; import com.android.car.ui.uxr.DrawableStateToggleButton; @@ -73,6 +74,8 @@ public class QCRowView extends FrameLayout { private LinearLayout mStartItemsContainer; private LinearLayout mEndItemsContainer; private LinearLayout mSeekBarContainer; + @Nullable + private QCSlider mQCSlider; private SeekBar mSeekBar; private QCActionListener mActionListener; private boolean mInDirectManipulationMode; @@ -81,7 +84,7 @@ public class QCRowView extends FrameLayout { private final View.OnKeyListener mSeekBarKeyListener = new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { - if (mSeekBar == null) { + if (mSeekBar == null || !mSeekBar.isEnabled()) { return false; } // Consume nudge events in direct manipulation mode. @@ -96,7 +99,13 @@ public class QCRowView extends FrameLayout { // Handle events to enter or exit direct manipulation mode. if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { if (event.getAction() == KeyEvent.ACTION_DOWN) { - setInDirectManipulationMode(v, mSeekBar, !mInDirectManipulationMode); + if (mQCSlider != null) { + if (mQCSlider.isEnabled()) { + setInDirectManipulationMode(v, mSeekBar, !mInDirectManipulationMode); + } else { + fireAction(mQCSlider, new Intent()); + } + } } return true; } @@ -196,7 +205,15 @@ public class QCRowView extends FrameLayout { return; } setVisibility(VISIBLE); - if (row.getPrimaryAction() != null || row.getActionHandler() != null) { + CarUiUtils.makeAllViewsEnabled(mContentView, row.isEnabled()); + if (!row.isEnabled()) { + if (row.isClickableWhileDisabled() && (row.getDisabledClickAction() != null + || row.getDisabledClickActionHandler() != null)) { + mContentView.setOnClickListener(v -> { + fireAction(row, /* intent= */ null); + }); + } + } else if (row.getPrimaryAction() != null || row.getActionHandler() != null) { mContentView.setOnClickListener(v -> { fireAction(row, /* intent= */ null); }); @@ -235,6 +252,7 @@ public class QCRowView extends FrameLayout { initSlider(slider); } else { mSeekBarContainer.setVisibility(View.GONE); + mQCSlider = null; } int startItemCount = row.getStartItems().size(); @@ -286,10 +304,22 @@ public class QCRowView extends FrameLayout { actionView = createActionView(root, actionView, R.layout.qc_action_switch); switchView = actionView.requireViewById(android.R.id.switch_widget); } + CarUiUtils.makeAllViewsEnabled(switchView, action.isEnabled()); + boolean shouldEnableView = + (action.isEnabled() || action.isClickableWhileDisabled()) && action.isAvailable(); switchView.setOnCheckedChangeListener(null); - switchView.setEnabled(action.isEnabled()); + switchView.setEnabled(shouldEnableView); switchView.setChecked(action.isChecked()); + switchView.setOnTouchListener((v, event) -> { + if (!action.isEnabled()) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + fireAction(action, new Intent()); + } + return true; + } + return false; + }); switchView.setOnCheckedChangeListener( (buttonView, isChecked) -> { Intent intent = new Intent(); @@ -299,12 +329,14 @@ public class QCRowView extends FrameLayout { } private void initToggleView(QCActionItem action, ViewGroup root, View actionView) { - DrawableStateToggleButton toggleButton = + DrawableStateToggleButton tmpToggleButton = actionView == null ? null : actionView.findViewById(R.id.qc_toggle_button); - if (toggleButton == null) { + if (tmpToggleButton == null) { actionView = createActionView(root, actionView, R.layout.qc_action_toggle); - toggleButton = actionView.requireViewById(R.id.qc_toggle_button); + tmpToggleButton = actionView.requireViewById(R.id.qc_toggle_button); } + DrawableStateToggleButton toggleButton = tmpToggleButton; // must be effectively final + CarUiUtils.makeAllViewsEnabled(toggleButton, action.isEnabled()); toggleButton.setText(null); toggleButton.setTextOn(null); toggleButton.setTextOff(null); @@ -314,6 +346,15 @@ public class QCRowView extends FrameLayout { toggleButton.setButtonDrawable(icon); toggleButton.setChecked(action.isChecked()); toggleButton.setEnabled(action.isEnabled() && action.isAvailable()); + toggleButton.setOnTouchListener((v, event) -> { + if (!action.isEnabled()) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + fireAction(action, new Intent()); + } + return true; + } + return false; + }); toggleButton.setOnCheckedChangeListener( (buttonView, isChecked) -> { Intent intent = new Intent(); @@ -329,21 +370,36 @@ public class QCRowView extends FrameLayout { // remove current action view root.removeView(actionView); } - actionView = mLayoutInflater.inflate(resId, /* root = */ null); + actionView = mLayoutInflater.inflate(resId, /* root= */ null); root.addView(actionView); return actionView; } private void initSlider(QCSlider slider) { + mQCSlider = slider; mSeekBar.setOnSeekBarChangeListener(null); mSeekBar.setMin(slider.getMin()); mSeekBar.setMax(slider.getMax()); mSeekBar.setProgress(slider.getValue()); + mSeekBar.setEnabled(slider.isEnabled() || slider.isClickableWhileDisabled()); + CarUiUtils.makeAllViewsEnabled(mSeekBar, slider.isEnabled()); + if (!slider.isEnabled() && mInDirectManipulationMode) { + setInDirectManipulationMode(mSeekBarContainer, mSeekBar, false); + } if (mSeekbarChangeListener == null) { mSeekbarChangeListener = new QCSeekbarChangeListener(); } mSeekbarChangeListener.setSlider(slider); mSeekBar.setOnSeekBarChangeListener(mSeekbarChangeListener); + mSeekBar.setOnTouchListener((v, event) -> { + if (!slider.isEnabled()) { + if (event.getActionMasked() == MotionEvent.ACTION_UP) { + fireAction(slider, new Intent()); + } + return true; + } + return false; + }); // set up rotary support mSeekBarContainer.setOnKeyListener(mSeekBarKeyListener); mSeekBarContainer.setOnFocusChangeListener(mSeekBarFocusChangeListener); @@ -358,11 +414,30 @@ public class QCRowView extends FrameLayout { } private void fireAction(QCItem item, Intent intent) { + if (!item.isEnabled()) { + if (item.getDisabledClickAction() != null) { + try { + item.getDisabledClickAction().send(getContext(), 0, intent); + if (mActionListener != null) { + mActionListener.onQCAction(item, item.getDisabledClickAction()); + } + } catch (PendingIntent.CanceledException e) { + Log.d(TAG, "Error sending intent", e); + } + } else if (item.getDisabledClickActionHandler() != null) { + item.getDisabledClickActionHandler().onAction(item, getContext(), intent); + if (mActionListener != null) { + mActionListener.onQCAction(item, item.getDisabledClickActionHandler()); + } + } + return; + } + if (item.getPrimaryAction() != null) { try { item.getPrimaryAction().send(getContext(), 0, intent); if (mActionListener != null) { - mActionListener.onQCAction(item); + mActionListener.onQCAction(item, item.getPrimaryAction()); } } catch (PendingIntent.CanceledException e) { Log.d(TAG, "Error sending intent", e); @@ -370,7 +445,7 @@ public class QCRowView extends FrameLayout { } else if (item.getActionHandler() != null) { item.getActionHandler().onAction(item, getContext(), intent); if (mActionListener != null) { - mActionListener.onQCAction(item); + mActionListener.onQCAction(item, item.getActionHandler()); } } } diff --git a/car-qc-lib/src/com/android/car/qc/view/QCTileView.java b/car-qc-lib/src/com/android/car/qc/view/QCTileView.java index 233c81a..33c0eff 100644 --- a/car-qc-lib/src/com/android/car/qc/view/QCTileView.java +++ b/car-qc-lib/src/com/android/car/qc/view/QCTileView.java @@ -34,6 +34,7 @@ import androidx.lifecycle.Observer; import com.android.car.qc.QCItem; import com.android.car.qc.QCTile; import com.android.car.qc.R; +import com.android.car.ui.utils.CarUiUtils; import com.android.car.ui.uxr.DrawableStateToggleButton; /** @@ -82,7 +83,6 @@ public class QCTileView extends FrameLayout implements Observer<QCItem> { mToggleButton.setText(null); mToggleButton.setTextOn(null); mToggleButton.setTextOff(null); - } @Override @@ -97,11 +97,34 @@ public class QCTileView extends FrameLayout implements Observer<QCItem> { } QCTile qcTile = (QCTile) qcItem; mSubtitle.setText(qcTile.getSubtitle()); + CarUiUtils.makeAllViewsEnabled(mToggleButton, qcTile.isEnabled()); mToggleButton.setOnCheckedChangeListener(null); mToggleButton.setChecked(qcTile.isChecked()); - mToggleButton.setEnabled(qcTile.isEnabled()); - mTileWrapper.setEnabled(qcTile.isEnabled() && qcTile.isAvailable()); - mTileWrapper.setOnClickListener(v -> mToggleButton.toggle()); + mToggleButton.setEnabled(qcTile.isEnabled() || qcTile.isClickableWhileDisabled()); + mTileWrapper.setEnabled( + (qcTile.isEnabled() || qcTile.isClickableWhileDisabled()) && qcTile.isAvailable()); + mTileWrapper.setOnClickListener(v -> { + if (!qcTile.isEnabled()) { + if (qcTile.getDisabledClickAction() != null) { + try { + qcTile.getDisabledClickAction().send(getContext(), 0, new Intent()); + if (mActionListener != null) { + mActionListener.onQCAction(qcTile, qcTile.getDisabledClickAction()); + } + } catch (PendingIntent.CanceledException e) { + Log.d(TAG, "Error sending intent", e); + } + } else if (qcTile.getDisabledClickActionHandler() != null) { + qcTile.getDisabledClickActionHandler().onAction(qcTile, getContext(), + new Intent()); + if (mActionListener != null) { + mActionListener.onQCAction(qcTile, qcTile.getDisabledClickActionHandler()); + } + } + return; + } + mToggleButton.toggle(); + }); Drawable icon = QCViewUtils.getInstance(mContext).getToggleIcon( qcTile.getIcon(), qcTile.isAvailable()); mToggleButton.setButtonDrawable(icon); @@ -113,7 +136,7 @@ public class QCTileView extends FrameLayout implements Observer<QCItem> { try { qcTile.getPrimaryAction().send(getContext(), 0, intent); if (mActionListener != null) { - mActionListener.onQCAction(qcTile); + mActionListener.onQCAction(qcTile, qcTile.getPrimaryAction()); } } catch (PendingIntent.CanceledException e) { Log.d(TAG, "Error sending intent", e); @@ -121,7 +144,7 @@ public class QCTileView extends FrameLayout implements Observer<QCItem> { } else if (qcTile.getActionHandler() != null) { qcTile.getActionHandler().onAction(qcTile, getContext(), intent); if (mActionListener != null) { - mActionListener.onQCAction(qcTile); + mActionListener.onQCAction(qcTile, qcTile.getActionHandler()); } } }); diff --git a/car-qc-lib/src/com/android/car/qc/view/QCView.java b/car-qc-lib/src/com/android/car/qc/view/QCView.java index 73b909e..a757354 100644 --- a/car-qc-lib/src/com/android/car/qc/view/QCView.java +++ b/car-qc-lib/src/com/android/car/qc/view/QCView.java @@ -112,7 +112,9 @@ public class QCView extends FrameLayout implements Observer<QCItem> { /** * Called when an interaction has occurred with an element in this view. * @param item the specific item within the {@link QCItem} that was interacted with. + * @param action the action that was executed - is generally either a + * {@link android.app.PendingIntent} or {@link QCItem.ActionHandler} */ - void onQCAction(@NonNull QCItem item); + void onQCAction(@NonNull QCItem item, @NonNull Object action); } } 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 588144f..ff70540 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 @@ -37,64 +37,73 @@ public class QCActionItemTest extends QCItemTestCase<QCActionItem> { @Test public void onCreate_invalidType_throwsException() { assertThrows(IllegalArgumentException.class, - () -> createAction("INVALID_TYPE", /* action= */ null, /* icon= */ null)); + () -> createAction("INVALID_TYPE", /* action= */ null, + /* disabledAction= */ null, /* icon= */ null)); } @Test public void onCreateSwitch_hasCorrectType() { QCActionItem action = createAction(QC_TYPE_ACTION_SWITCH, /* action= */ null, - /* icon= */null); + /* disabledAction= */ null, /* icon= */null); assertThat(action.getType()).isEqualTo(QC_TYPE_ACTION_SWITCH); } @Test public void onCreateToggle_hasCorrectType() { QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, /* action= */ null, - /* icon= */ null); + /* disabledAction= */ null, /* icon= */ null); assertThat(action.getType()).isEqualTo(QC_TYPE_ACTION_TOGGLE); } @Test - public void onBundle_nullAction_noCrash() { - QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, /* action= */ null, mDefaultIcon); + public void onBundle_nullActions_noCrash() { + QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, /* action= */ null, + /* disabledAction= */ null, mDefaultIcon); writeAndLoadFromBundle(action); // Test passes if this doesn't crash } @Test public void onBundle_nullIcon_noCrash() { - QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, mDefaultAction, /* icon= */ null); + QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, mDefaultAction, + mDefaultDisabledAction, /* icon= */ null); writeAndLoadFromBundle(action); // Test passes if this doesn't crash } @Test public void onBundle_switch_accurateData() { - QCActionItem action = createAction(QC_TYPE_ACTION_SWITCH, mDefaultAction, /* icon= */ null); + QCActionItem action = createAction(QC_TYPE_ACTION_SWITCH, mDefaultAction, + mDefaultDisabledAction, /* icon= */ null); QCActionItem newAction = writeAndLoadFromBundle(action); assertThat(newAction.getType()).isEqualTo(QC_TYPE_ACTION_SWITCH); assertThat(newAction.isChecked()).isTrue(); assertThat(newAction.isEnabled()).isTrue(); + assertThat(newAction.isClickableWhileDisabled()).isFalse(); assertThat(newAction.getPrimaryAction()).isNotNull(); assertThat(newAction.getIcon()).isNull(); } @Test public void onBundle_toggle_accurateDate() { - QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, mDefaultAction, mDefaultIcon); + QCActionItem action = createAction(QC_TYPE_ACTION_TOGGLE, mDefaultAction, + mDefaultDisabledAction, mDefaultIcon); QCActionItem newAction = writeAndLoadFromBundle(action); assertThat(newAction.getType()).isEqualTo(QC_TYPE_ACTION_TOGGLE); assertThat(newAction.isChecked()).isTrue(); assertThat(newAction.isEnabled()).isTrue(); + assertThat(newAction.isClickableWhileDisabled()).isFalse(); assertThat(newAction.getPrimaryAction()).isNotNull(); assertThat(newAction.getIcon()).isNotNull(); } - private QCActionItem createAction(String type, PendingIntent action, Icon icon) { + private QCActionItem createAction(String type, PendingIntent action, + PendingIntent disabledAction, Icon icon) { return new QCActionItem.Builder(type) .setChecked(true) .setEnabled(true) .setAction(action) + .setDisabledClickAction(disabledAction) .setIcon(icon) .build(); } diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/QCItemTestCase.java b/car-qc-lib/tests/unit/src/com/android/car/qc/QCItemTestCase.java index fab8302..3481a85 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/QCItemTestCase.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/QCItemTestCase.java @@ -34,6 +34,8 @@ public abstract class QCItemTestCase<T extends QCItem> { protected PendingIntent mDefaultAction = PendingIntent.getActivity(mContext, /* requestCode= */ 0, new Intent(), PendingIntent.FLAG_IMMUTABLE); + protected PendingIntent mDefaultDisabledAction = PendingIntent.getActivity(mContext, + /* requestCode= */ 1, new Intent(), PendingIntent.FLAG_IMMUTABLE); protected Icon mDefaultIcon = Icon.createWithResource(mContext, R.drawable.btn_star); protected T writeAndLoadFromBundle(T item) { diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/QCRowTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/QCRowTest.java index 816c1d6..cd1ff7c 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/QCRowTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/QCRowTest.java @@ -37,27 +37,27 @@ public class QCRowTest extends QCItemTestCase<QCRow> { @Test public void onCreate_hasCorrectType() { - QCRow row = createRow(/* action= */ null, /* icon= */ null); + QCRow row = createRow(/* action= */ null, /* disabledAction= */ null, /* icon= */ null); assertThat(row.getType()).isEqualTo(QC_TYPE_ROW); } @Test - public void onBundle_nullAction_noCrash() { - QCRow row = createRow(/* action= */ null, mDefaultIcon); + public void onBundle_nullActions_noCrash() { + QCRow row = createRow(/* action= */ null, /* disabledAction= */ null, mDefaultIcon); writeAndLoadFromBundle(row); // Test passes if this doesn't crash } @Test public void onBundle_nullIcon_noCrash() { - QCRow row = createRow(mDefaultAction, /* icon= */ null); + QCRow row = createRow(mDefaultAction, mDefaultDisabledAction, /* icon= */ null); writeAndLoadFromBundle(row); // Test passes if this doesn't crash } @Test public void createFromParcel_accurateData() { - QCRow row = createRow(mDefaultAction, mDefaultIcon); + QCRow row = createRow(mDefaultAction, mDefaultDisabledAction, mDefaultIcon); QCRow newRow = writeAndLoadFromBundle(row); assertThat(newRow.getType()).isEqualTo(QC_TYPE_ROW); assertThat(newRow.getTitle()).isEqualTo(TEST_TITLE); @@ -70,8 +70,8 @@ public class QCRowTest extends QCItemTestCase<QCRow> { public void createFromParcel_accurateData_startItem() { QCActionItem item = new QCActionItem.Builder(QC_TYPE_ACTION_SWITCH).build(); - QCRow row = createRow(/* action= */ null, /* icon= */ null, Collections.singletonList(item), - Collections.emptyList(), Collections.emptyList()); + QCRow row = createRow(/* action= */ null, /* disabledAction= */ null, /* icon= */ null, + Collections.singletonList(item), Collections.emptyList(), Collections.emptyList()); QCRow newRow = writeAndLoadFromBundle(row); assertThat(newRow.getStartItems().size()).isEqualTo(1); } @@ -80,8 +80,8 @@ public class QCRowTest extends QCItemTestCase<QCRow> { public void createFromParcel_accurateData_endItem() { QCActionItem item = new QCActionItem.Builder(QC_TYPE_ACTION_SWITCH).build(); - QCRow row = createRow(/* action= */ null, /* icon= */ null, Collections.emptyList(), - Collections.singletonList(item), Collections.emptyList()); + QCRow row = createRow(/* action= */ null, /* disabledAction= */ null, /* icon= */ null, + Collections.emptyList(), Collections.singletonList(item), Collections.emptyList()); QCRow newRow = writeAndLoadFromBundle(row); assertThat(newRow.getEndItems().size()).isEqualTo(1); } @@ -90,24 +90,26 @@ public class QCRowTest extends QCItemTestCase<QCRow> { public void createFromParcel_accurateData_slider() { QCSlider slider = new QCSlider.Builder().build(); - QCRow row = createRow(/* action= */ null, /* icon= */ null, Collections.emptyList(), - Collections.emptyList(), Collections.singletonList(slider)); + QCRow row = createRow(/* action= */ null, /* disabledAction= */ null, /* icon= */ null, + Collections.emptyList(), Collections.emptyList(), + Collections.singletonList(slider)); QCRow newRow = writeAndLoadFromBundle(row); assertThat(newRow.getSlider()).isNotNull(); } - private QCRow createRow(PendingIntent action, Icon icon) { - return createRow(action, icon, Collections.emptyList(), Collections.emptyList(), - Collections.emptyList()); + private QCRow createRow(PendingIntent action, PendingIntent disabledAction, Icon icon) { + return createRow(action, disabledAction, icon, Collections.emptyList(), + Collections.emptyList(), Collections.emptyList()); } - private QCRow createRow(PendingIntent action, Icon icon, List<QCActionItem> startItems, - List<QCActionItem> endItems, List<QCSlider> sliders) { + private QCRow createRow(PendingIntent action, PendingIntent disabledAction, Icon icon, + List<QCActionItem> startItems, List<QCActionItem> endItems, List<QCSlider> sliders) { QCRow.Builder builder = new QCRow.Builder() .setTitle(TEST_TITLE) .setSubtitle(TEST_SUBTITLE) .setIcon(icon) - .setPrimaryAction(action); + .setPrimaryAction(action) + .setDisabledClickAction(disabledAction); for (QCActionItem item : startItems) { builder.addStartItem(item); } diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/QCSliderTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/QCSliderTest.java index 97bf191..533e41d 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/QCSliderTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/QCSliderTest.java @@ -35,34 +35,36 @@ public class QCSliderTest extends QCItemTestCase<QCSlider> { @Test public void onCreate_hasCorrectType() { - QCSlider slider = createSlider(/* action= */ null); + QCSlider slider = createSlider(/* action= */ null, /* disabledAction= */ null); assertThat(slider.getType()).isEqualTo(QC_TYPE_SLIDER); } @Test - public void onBundle_nullAction_noCrash() { - QCSlider slider = createSlider(/* action= */ null); + public void onBundle_nullActions_noCrash() { + QCSlider slider = createSlider(/* action= */ null, /* disabledAction= */ null); writeAndLoadFromBundle(slider); // Test passes if this doesn't crash } @Test public void createFromParcel_accurateData() { - QCSlider slider = createSlider(mDefaultAction); + QCSlider slider = createSlider(mDefaultAction, mDefaultDisabledAction); QCSlider newSlider = writeAndLoadFromBundle(slider); assertThat(newSlider.getType()).isEqualTo(QC_TYPE_SLIDER); assertThat(newSlider.getPrimaryAction()).isNotNull(); + assertThat(newSlider.getDisabledClickAction()).isNotNull(); assertThat(newSlider.getMin()).isEqualTo(MIN); assertThat(newSlider.getMax()).isEqualTo(MAX); assertThat(newSlider.getValue()).isEqualTo(VALUE); } - private QCSlider createSlider(PendingIntent action) { + private QCSlider createSlider(PendingIntent action, PendingIntent disabledAction) { return new QCSlider.Builder() .setMin(MIN) .setMax(MAX) .setValue(VALUE) .setInputAction(action) + .setDisabledClickAction(disabledAction) .build(); } } diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/QCTileTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/QCTileTest.java index e9530d5..5bed094 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/QCTileTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/QCTileTest.java @@ -33,42 +33,44 @@ public class QCTileTest extends QCItemTestCase<QCTile> { @Test public void onCreate_hasCorrectType() { - QCTile tile = createTile(/* action= */ null, /* icon= */ null); + QCTile tile = createTile(/* action= */ null, /* disabledAction= */ null, /* icon= */ null); assertThat(tile.getType()).isEqualTo(QC_TYPE_TILE); } @Test public void onBundle_nullAction_noCrash() { - QCTile tile = createTile(/* action= */ null, mDefaultIcon); + QCTile tile = createTile(/* action= */ null, /* disabledAction= */ null, mDefaultIcon); writeAndLoadFromBundle(tile); // Test passes if this doesn't crash } @Test public void onBundle_nullIcon_noCrash() { - QCTile tile = createTile(mDefaultAction, /* icon= */ null); + QCTile tile = createTile(mDefaultAction, mDefaultDisabledAction, /* icon= */ null); writeAndLoadFromBundle(tile); // Test passes if this doesn't crash } @Test public void createFromParcel_accurateData() { - QCTile tile = createTile(mDefaultAction, mDefaultIcon); + QCTile tile = createTile(mDefaultAction, mDefaultDisabledAction, mDefaultIcon); QCTile newTile = writeAndLoadFromBundle(tile); assertThat(newTile.getType()).isEqualTo(QC_TYPE_TILE); assertThat(newTile.getSubtitle()).isEqualTo(TEST_SUBTITLE); assertThat(newTile.isChecked()).isTrue(); assertThat(newTile.isEnabled()).isTrue(); assertThat(newTile.getPrimaryAction()).isNotNull(); + assertThat(newTile.getDisabledClickAction()).isNotNull(); assertThat(newTile.getIcon()).isNotNull(); } - private QCTile createTile(PendingIntent action, Icon icon) { + private QCTile createTile(PendingIntent action, PendingIntent disabledAction, Icon icon) { return new QCTile.Builder() .setSubtitle(TEST_SUBTITLE) .setChecked(true) .setEnabled(true) .setAction(action) + .setDisabledClickAction(disabledAction) .setIcon(icon) .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 6e1639c..647317a 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 @@ -107,6 +107,7 @@ public class QCRowViewTest { } @Test + @UiThreadTest public void setRow_createsStartItems() { QCRow row = new QCRow.Builder() .addStartItem(new QCActionItem.Builder(QC_TYPE_ACTION_SWITCH).build()) @@ -122,6 +123,7 @@ public class QCRowViewTest { } @Test + @UiThreadTest public void setRow_createsEndItems() { QCRow row = new QCRow.Builder() .addEndItem(new QCActionItem.Builder(QC_TYPE_ACTION_SWITCH).build()) diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCTileViewTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCTileViewTest.java index 9104520..e900441 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCTileViewTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCTileViewTest.java @@ -70,6 +70,7 @@ public class QCTileViewTest { } @Test + @UiThreadTest public void onChanged_setsSubtitleView() { String subtitle = "TEST_SUBTITLE"; QCTile tile = new QCTile.Builder().setSubtitle(subtitle).build(); @@ -89,6 +90,7 @@ public class QCTileViewTest { } @Test + @UiThreadTest public void onChanged_setsIcon() { Icon icon = Icon.createWithResource(mContext, android.R.drawable.btn_star); QCTile tile = new QCTile.Builder().setIcon(icon).build(); diff --git a/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCViewTest.java b/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCViewTest.java index b2090cb..9d3d9d7 100644 --- a/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCViewTest.java +++ b/car-qc-lib/tests/unit/src/com/android/car/qc/view/QCViewTest.java @@ -24,6 +24,7 @@ import static org.testng.Assert.assertThrows; import android.content.Context; +import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -69,6 +70,7 @@ public class QCViewTest { } @Test + @UiThreadTest public void onChanged_tile_createsTileView() { QCTile tile = new QCTile.Builder().build(); mView.onChanged(tile); @@ -77,6 +79,7 @@ public class QCViewTest { } @Test + @UiThreadTest public void onChanged_alreadyHasView_callsOnChanged() { QCTile tile = new QCTile.Builder().build(); mView.onChanged(tile); @@ -89,6 +92,7 @@ public class QCViewTest { } @Test + @UiThreadTest public void setActionListener_setsOnChildView() { QCTile tile = new QCTile.Builder().build(); mView.onChanged(tile); |