From 7f40cfb1f611b8aaeaa9896e6d94faa51db4aa49 Mon Sep 17 00:00:00 2001 From: Julia Kawano Date: Fri, 21 Aug 2020 21:37:47 +0000 Subject: [PATCH] Add HVAC temp with buttons to nav bar Created AdjustableTemperatureView class that implements the TemperatureView interface to display temperature with buttons to increment and decrement. Updated HvacController to only handle the set temperature HVAC property. Removed uses of deprecated CarHvacManager, using CarPropertyManager instead. Also modified and updated the hvac tests. UI changes: - Add driver and passenger HVAC views to nav bar - Use colored arrows with grey circle for hvac increase/decrease Test: atest :carsysui-presubmit --include-subdir Test: Manual - built on flame_car Bug: 162598687 Change-Id: I39151884f2307e861d290de7ad39ea2ec0c256e8 --- .../CarSystemUI/res/drawable/car_ic_apps.xml | 12 +- .../res/drawable/car_ic_apps_selected.xml | 6 +- .../CarSystemUI/res/drawable/car_ic_home.xml | 25 +++ .../res/drawable/car_ic_home_selected.xml | 25 +++ .../CarSystemUI/res/drawable/car_ic_hvac.xml | 44 +--- .../res/drawable/car_ic_hvac_selected.xml | 25 +++ .../res/drawable/car_ic_notification.xml | 8 +- .../res/drawable/hvac_decrease_button.xml | 53 +++++ .../res/drawable/hvac_increase_button.xml | 53 +++++ .../CarSystemUI/res/drawable/ic_mic_white.xml | 10 +- .../layout/adjustable_temperature_view.xml | 50 +++++ .../res/layout/car_navigation_bar.xml | 203 +++++++++--------- .../car_top_navigation_bar_unprovisioned.xml | 8 - packages/CarSystemUI/res/values/colors.xml | 1 + packages/CarSystemUI/res/values/dimens.xml | 14 +- packages/CarSystemUI/res/values/strings.xml | 2 + packages/CarSystemUI/res/values/styles.xml | 11 +- .../car/hvac/AdjustableTemperatureView.java | 108 ++++++++++ .../car/hvac/AnimatedTemperatureView.java | 48 ++--- .../systemui/car/hvac/HvacController.java | 179 +++++++-------- .../car/hvac/TemperatureTextView.java | 29 ++- .../systemui/car/hvac/TemperatureView.java | 29 +-- .../hvac/AdjustableTemperatureViewTest.java | 174 +++++++++++++++ .../systemui/car/hvac/HvacControllerTest.java | 76 ++++--- .../car/hvac/TemperatureTextViewTest.java | 107 +++++++++ 25 files changed, 945 insertions(+), 355 deletions(-) create mode 100644 packages/CarSystemUI/res/drawable/car_ic_home.xml create mode 100644 packages/CarSystemUI/res/drawable/car_ic_home_selected.xml create mode 100644 packages/CarSystemUI/res/drawable/car_ic_hvac_selected.xml create mode 100644 packages/CarSystemUI/res/drawable/hvac_decrease_button.xml create mode 100644 packages/CarSystemUI/res/drawable/hvac_increase_button.xml create mode 100644 packages/CarSystemUI/res/layout/adjustable_temperature_view.xml create mode 100644 packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java create mode 100644 packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java create mode 100644 packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java diff --git a/packages/CarSystemUI/res/drawable/car_ic_apps.xml b/packages/CarSystemUI/res/drawable/car_ic_apps.xml index a8d8a2f241f6c..e028a0ed45c94 100644 --- a/packages/CarSystemUI/res/drawable/car_ic_apps.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_apps.xml @@ -15,11 +15,11 @@ ~ limitations under the License --> - + android:viewportHeight="44"> + \ No newline at end of file diff --git a/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml index 2a4e91aa3cd9e..9504e61e53e42 100644 --- a/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_apps_selected.xml @@ -15,10 +15,10 @@ ~ limitations under the License --> + android:viewportHeight="44"> diff --git a/packages/CarSystemUI/res/drawable/car_ic_home.xml b/packages/CarSystemUI/res/drawable/car_ic_home.xml new file mode 100644 index 0000000000000..c78f0edd5594c --- /dev/null +++ b/packages/CarSystemUI/res/drawable/car_ic_home.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/packages/CarSystemUI/res/drawable/car_ic_home_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_home_selected.xml new file mode 100644 index 0000000000000..16192df866760 --- /dev/null +++ b/packages/CarSystemUI/res/drawable/car_ic_home_selected.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/packages/CarSystemUI/res/drawable/car_ic_hvac.xml b/packages/CarSystemUI/res/drawable/car_ic_hvac.xml index bdc44b38a1762..55c968eacc4d2 100644 --- a/packages/CarSystemUI/res/drawable/car_ic_hvac.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_hvac.xml @@ -1,3 +1,4 @@ + - - - - - - - - - \ No newline at end of file + android:width="@dimen/system_bar_icon_drawing_size" + android:height="@dimen/system_bar_icon_drawing_size" + android:viewportWidth="24" + android:viewportHeight="24"> + + diff --git a/packages/CarSystemUI/res/drawable/car_ic_hvac_selected.xml b/packages/CarSystemUI/res/drawable/car_ic_hvac_selected.xml new file mode 100644 index 0000000000000..817b7148ecdd9 --- /dev/null +++ b/packages/CarSystemUI/res/drawable/car_ic_hvac_selected.xml @@ -0,0 +1,25 @@ + + + + + \ No newline at end of file diff --git a/packages/CarSystemUI/res/drawable/car_ic_notification.xml b/packages/CarSystemUI/res/drawable/car_ic_notification.xml index 9d9ad0fdf9c59..aabf9161c11fe 100644 --- a/packages/CarSystemUI/res/drawable/car_ic_notification.xml +++ b/packages/CarSystemUI/res/drawable/car_ic_notification.xml @@ -15,10 +15,10 @@ ~ limitations under the License --> + android:width="@dimen/system_bar_icon_drawing_size" + android:height="@dimen/system_bar_icon_drawing_size" + android:viewportWidth="44" + android:viewportHeight="44"> diff --git a/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml b/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml new file mode 100644 index 0000000000000..469ac91073f99 --- /dev/null +++ b/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/CarSystemUI/res/drawable/hvac_increase_button.xml b/packages/CarSystemUI/res/drawable/hvac_increase_button.xml new file mode 100644 index 0000000000000..a3fca2233dddd --- /dev/null +++ b/packages/CarSystemUI/res/drawable/hvac_increase_button.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/CarSystemUI/res/drawable/ic_mic_white.xml b/packages/CarSystemUI/res/drawable/ic_mic_white.xml index 546b1a894e6ad..71fcc5302d75c 100644 --- a/packages/CarSystemUI/res/drawable/ic_mic_white.xml +++ b/packages/CarSystemUI/res/drawable/ic_mic_white.xml @@ -15,11 +15,11 @@ ~ limitations under the License --> - + \ No newline at end of file diff --git a/packages/CarSystemUI/res/layout/adjustable_temperature_view.xml b/packages/CarSystemUI/res/layout/adjustable_temperature_view.xml new file mode 100644 index 0000000000000..d19740932aa43 --- /dev/null +++ b/packages/CarSystemUI/res/layout/adjustable_temperature_view.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml index a49a6373a252b..b07dde582e5f6 100644 --- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml +++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml @@ -1,6 +1,6 @@ - - + + + android:layoutDirection="ltr"> - - + android:layout_alignParentStart="true" + android:background="@null" + systemui:broadcast="true" + systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"> + + + + + + + + + + + + + + + + + + + + + + - - + android:layout_alignParentEnd="true" + android:background="@null" + systemui:broadcast="true" + systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"> - - - - - - - - - - - - - - - - - - - + + + - \ No newline at end of file diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml index 9634950e47488..d9c149106451a 100644 --- a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml +++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml @@ -55,10 +55,6 @@ android:minEms="4" android:textAppearance="@style/TextAppearance.CarStatus" systemui:hvacAreaId="49" - systemui:hvacMaxText="@string/hvac_max_text" - systemui:hvacMaxValue="@dimen/hvac_max_value" - systemui:hvacMinText="@string/hvac_min_text" - systemui:hvacMinValue="@dimen/hvac_min_value" systemui:hvacPivotOffset="60dp" systemui:hvacPropertyId="358614275" systemui:hvacTempFormat="%.0f\u00B0" @@ -133,10 +129,6 @@ android:minEms="4" android:textAppearance="@style/TextAppearance.CarStatus" systemui:hvacAreaId="68" - systemui:hvacMaxText="@string/hvac_max_text" - systemui:hvacMaxValue="@dimen/hvac_max_value" - systemui:hvacMinText="@string/hvac_min_text" - systemui:hvacMinValue="@dimen/hvac_min_value" systemui:hvacPivotOffset="60dp" systemui:hvacPropertyId="358614275" systemui:hvacTempFormat="%.0f\u00B0" diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml index 98e31b31551ee..1e15affcbf489 100644 --- a/packages/CarSystemUI/res/values/colors.xml +++ b/packages/CarSystemUI/res/values/colors.xml @@ -33,6 +33,7 @@ #ffffff + #ffffff #33000000 @color/status_bar_background_color diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml index 5fb32aff27e82..f02a8e7648c0f 100644 --- a/packages/CarSystemUI/res/values/dimens.xml +++ b/packages/CarSystemUI/res/values/dimens.xml @@ -47,16 +47,22 @@ set here. See car_product overlay for car specific defaults--> 16dp - 36dp - 36dp + 36dp + 64dp + 44dp + 1.75 @*android:dimen/car_primary_icon_size + 16dp + 56sp + 8dp + 76dp - 0 - 126 + 0 + 126 diff --git a/packages/CarSystemUI/res/values/strings.xml b/packages/CarSystemUI/res/values/strings.xml index 67fd5bb685211..fbdb5167fadee 100644 --- a/packages/CarSystemUI/res/values/strings.xml +++ b/packages/CarSystemUI/res/values/strings.xml @@ -16,6 +16,8 @@ --> + + %.0f\u00B0 Min diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml index 5b042a4b83ec6..0db17ac42a779 100644 --- a/packages/CarSystemUI/res/values/styles.xml +++ b/packages/CarSystemUI/res/values/styles.xml @@ -34,17 +34,20 @@ \ No newline at end of file diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java new file mode 100644 index 0000000000000..4cac4456789d7 --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.car.hvac; + +import static com.android.systemui.car.hvac.HvacController.convertToCelsius; +import static com.android.systemui.car.hvac.HvacController.convertToFahrenheit; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.systemui.R; + +/** + * Displays temperature with a button to decrease and a button to increase on either side. + * Properties configured in the XML: + * hvacAreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1) + */ +public class AdjustableTemperatureView extends LinearLayout implements TemperatureView { + + private HvacController mHvacController; + private float mCurrentTempC; + private TextView mTempTextView; + private boolean mDisplayInFahrenheit = false; + + private final float mMinTempC; + private final float mMaxTempC; + private final int mAreaId; + private final String mTempFormat; + + public AdjustableTemperatureView(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TemperatureView); + mAreaId = typedArray.getInt(R.styleable.TemperatureView_hvacAreaId, -1); + + LayoutInflater.from(context).inflate(R.layout.adjustable_temperature_view, /* root= */this); + mTempFormat = getResources().getString(R.string.hvac_temperature_format); + mMinTempC = getResources().getFloat(R.dimen.hvac_min_value_celsius); + mMaxTempC = getResources().getFloat(R.dimen.hvac_max_value_celsius); + initializeButtons(); + } + + @Override + public void setHvacController(HvacController controller) { + mHvacController = controller; + } + + @Override + public void setTemperatureView(float tempC) { + if (tempC > mMaxTempC || tempC < mMinTempC) { + return; + } + if (mTempTextView == null) { + mTempTextView = findViewById(R.id.hvac_temperature_text); + } + mTempTextView.setText(String.format(mTempFormat, + mDisplayInFahrenheit ? convertToFahrenheit(tempC) : tempC)); + mCurrentTempC = tempC; + } + + @Override + public void setDisplayInFahrenheit(boolean displayFahrenheit) { + mDisplayInFahrenheit = displayFahrenheit; + setTemperatureView(mCurrentTempC); + } + + @Override + public int getAreaId() { + return mAreaId; + } + + private void initializeButtons() { + findViewById(R.id.hvac_decrease_button).setOnClickListener(v -> { + float newTemp = mDisplayInFahrenheit ? convertToCelsius( + convertToFahrenheit(mCurrentTempC) - 1) : (mCurrentTempC - 1); + setTemperature(newTemp, mAreaId); + }); + + findViewById(R.id.hvac_increase_button).setOnClickListener(v -> { + float newTemp = mDisplayInFahrenheit ? convertToCelsius( + convertToFahrenheit(mCurrentTempC) + 1) : (mCurrentTempC + 1); + setTemperature(newTemp, mAreaId); + }); + } + + private void setTemperature(float tempC, int zone) { + if (tempC < mMaxTempC && tempC > mMinTempC && mHvacController != null) { + mHvacController.setTemperature(tempC, zone); + } + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java index a7294317f46c3..567baa91cb59b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java @@ -16,6 +16,8 @@ package com.android.systemui.car.hvac; +import static com.android.systemui.car.hvac.HvacController.convertToFahrenheit; + import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.content.Context; @@ -40,9 +42,7 @@ import com.android.systemui.R; * Simple text display of HVAC properties, It is designed to show mTemperature and is configured in * the XML. * XML properties: - * hvacPropertyId - Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385) - * hvacAreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1) - * hvacTempFormat - Example: "%.1f\u00B0" (1 decimal and the degree symbol) + * hvacAreaId - Example: VehicleAreaSeat.SEAT_ROW_1_LEFT (1) * hvacOrientaion = Example: left */ public class AnimatedTemperatureView extends FrameLayout implements TemperatureView { @@ -84,7 +84,6 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV } private final int mAreaId; - private final int mPropertyId; private final int mPivotOffset; private final int mGravity; private final int mTextAppearanceRes; @@ -100,12 +99,13 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV private final TemperatureTextAnimator mTextAnimator; boolean mDisplayInFahrenheit = false; + private HvacController mHvacController; + public AnimatedTemperatureView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AnimatedTemperatureView); mAreaId = typedArray.getInt(R.styleable.AnimatedTemperatureView_hvacAreaId, -1); - mPropertyId = typedArray.getInt(R.styleable.AnimatedTemperatureView_hvacPropertyId, -1); mPivotOffset = typedArray.getDimensionPixelOffset( R.styleable.AnimatedTemperatureView_hvacPivotOffset, 0); @@ -115,11 +115,8 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV typedArray.getResourceId(R.styleable.AnimatedTemperatureView_android_textAppearance, 0); mMinEms = typedArray.getInteger(R.styleable.AnimatedTemperatureView_android_minEms, 0); - mMinValue = typedArray.getFloat(R.styleable.AnimatedTemperatureView_hvacMinValue, - Float.NaN); - mMaxValue = typedArray.getFloat(R.styleable.AnimatedTemperatureView_hvacMaxValue, - Float.NaN); - + mMinValue = getResources().getFloat(R.dimen.hvac_min_value_celsius); + mMaxValue = getResources().getFloat(R.dimen.hvac_max_value_celsius); mPaddingRect = new Rect(getPaddingLeft(), getPaddingTop(), getPaddingRight(), getPaddingBottom()); @@ -138,15 +135,10 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV mBackgroundAnimator = new TemperatureBackgroundAnimator(this, background); - - String format = typedArray.getString(R.styleable.AnimatedTemperatureView_hvacTempFormat); - format = (format == null) ? "%.1f\u00B0" : format; - CharSequence minText = typedArray.getString( - R.styleable.AnimatedTemperatureView_hvacMinText); - CharSequence maxText = typedArray.getString( - R.styleable.AnimatedTemperatureView_hvacMaxText); - mTextAnimator = new TemperatureTextAnimator(this, textSwitcher, format, mPivotOffset, - minText, maxText); + mTextAnimator = new TemperatureTextAnimator(this, textSwitcher, + getResources().getString(R.string.hvac_temperature_format), mPivotOffset, + getResources().getString(R.string.hvac_min_text), + getResources().getString(R.string.hvac_max_text)); addView(background, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); @@ -186,13 +178,18 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV return textView; } + @Override + public void setHvacController(HvacController controller) { + mHvacController = controller; + } + /** * Formats the float for display * * @param temp - The current temp or NaN */ @Override - public void setTemp(float temp) { + public void setTemperatureView(float temp) { if (mDisplayInFahrenheit) { temp = convertToFahrenheit(temp); } @@ -252,15 +249,7 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV } /** - * @return propertiyId Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (358614275) - */ - @Override - public int getPropertyId() { - return mPropertyId; - } - - /** - * @return hvac AreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1) + * @return hvac AreaId - Example: VehicleAreaSeat.SEAT_ROW_1_LEFT (1) */ @Override public int getAreaId() { @@ -272,6 +261,5 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV super.onDetachedFromWindow(); mBackgroundAnimator.stopAnimations(); } - } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java index a4b6bfc58d3c3..f7451dc6fdee7 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java @@ -18,12 +18,12 @@ package com.android.systemui.car.hvac; import static android.car.VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_SET; import android.car.Car; import android.car.VehicleUnit; import android.car.hardware.CarPropertyValue; -import android.car.hardware.hvac.CarHvacManager; -import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback; +import android.car.hardware.property.CarPropertyManager; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -34,10 +34,8 @@ import com.android.systemui.dagger.SysUISingleton; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Set; import javax.inject.Inject; @@ -54,49 +52,64 @@ public class HvacController { private final CarServiceProvider mCarServiceProvider; private final Set mRegisteredViews = new HashSet<>(); - private CarHvacManager mHvacManager; - private HashMap> mTempComponents = new HashMap<>(); + private CarPropertyManager mCarPropertyManager; + private HashMap> mTempComponents = new HashMap<>(); - /** - * Callback for getting changes from {@link CarHvacManager} and setting the UI elements to - * match. - */ - private final CarHvacEventCallback mHardwareCallback = new CarHvacEventCallback() { - @Override - public void onChangeEvent(final CarPropertyValue val) { - try { - int areaId = val.getAreaId(); - int propertyId = val.getPropertyId(); - List temperatureViews = mTempComponents.get( - new HvacKey(propertyId, areaId)); - if (temperatureViews != null && !temperatureViews.isEmpty()) { - float value = (float) val.getValue(); - if (DEBUG) { - Log.d(TAG, "onChangeEvent: " + areaId + ":" + propertyId + ":" + value); + private final CarPropertyManager.CarPropertyEventCallback mHvacTemperatureSetCallback = + new CarPropertyManager.CarPropertyEventCallback() { + @Override + public void onChangeEvent(CarPropertyValue value) { + try { + int areaId = value.getAreaId(); + List temperatureViews = mTempComponents.get(areaId); + if (temperatureViews != null && !temperatureViews.isEmpty()) { + float newTemp = (float) value.getValue(); + if (DEBUG) { + Log.d(TAG, "onChangeEvent: " + areaId + ":" + value); + } + for (TemperatureView view : temperatureViews) { + view.setTemperatureView(newTemp); + } + } + } catch (Exception e) { + Log.e(TAG, "Failed handling hvac change event", e); } - for (TemperatureView tempView : temperatureViews) { - tempView.setTemp(value); - } - } // else the data is not of interest - } catch (Exception e) { - // catch all so we don't take down the sysui if a new data type is - // introduced. - Log.e(TAG, "Failed handling hvac change event", e); - } - } + } - @Override - public void onErrorEvent(final int propertyId, final int zone) { - Log.d(TAG, "HVAC error event, propertyId: " + propertyId - + " zone: " + zone); - } - }; + @Override + public void onErrorEvent(int propId, int zone) { + Log.d(TAG, "HVAC error event, propertyId: " + propId + " zone: " + zone); + } + }; + + private final CarPropertyManager.CarPropertyEventCallback mTemperatureUnitChangeCallback = + new CarPropertyManager.CarPropertyEventCallback() { + @Override + public void onChangeEvent(CarPropertyValue value) { + if (!mRegisteredViews.isEmpty()) { + for (TemperatureView view : mRegisteredViews) { + view.setDisplayInFahrenheit( + value.getValue().equals(VehicleUnit.FAHRENHEIT)); + } + } + } + + @Override + public void onErrorEvent(int propId, int zone) { + Log.d(TAG, "HVAC error event, propertyId: " + propId + " zone: " + zone); + } + }; private final CarServiceProvider.CarServiceOnConnectedListener mCarServiceLifecycleListener = car -> { try { - mHvacManager = (CarHvacManager) car.getCarManager(Car.HVAC_SERVICE); - mHvacManager.registerCallback(mHardwareCallback); + mCarPropertyManager = (CarPropertyManager) car.getCarManager( + Car.PROPERTY_SERVICE); + mCarPropertyManager.registerCallback(mHvacTemperatureSetCallback, + HVAC_TEMPERATURE_SET, CarPropertyManager.SENSOR_RATE_ONCHANGE); + mCarPropertyManager.registerCallback(mTemperatureUnitChangeCallback, + HVAC_TEMPERATURE_DISPLAY_UNITS, + CarPropertyManager.SENSOR_RATE_ONCHANGE); initComponents(); } catch (Exception e) { Log.e(TAG, "Failed to correctly connect to HVAC", e); @@ -109,8 +122,7 @@ public class HvacController { } /** - * Create connection to the Car service. Note: call backs from the Car service - * ({@link CarHvacManager}) will happen on the same thread this method was called from. + * Create connection to the Car service. */ public void connectToCarService() { mCarServiceProvider.addListener(mCarServiceLifecycleListener); @@ -124,21 +136,18 @@ public class HvacController { return; } - HvacKey hvacKey = new HvacKey(temperatureView.getPropertyId(), temperatureView.getAreaId()); - if (!mTempComponents.containsKey(hvacKey)) { - mTempComponents.put(hvacKey, new ArrayList<>()); + int areaId = temperatureView.getAreaId(); + if (!mTempComponents.containsKey(areaId)) { + mTempComponents.put(areaId, new ArrayList<>()); } - mTempComponents.get(hvacKey).add(temperatureView); + mTempComponents.get(areaId).add(temperatureView); initComponent(temperatureView); mRegisteredViews.add(temperatureView); } private void initComponents() { - Iterator>> iterator = - mTempComponents.entrySet().iterator(); - while (iterator.hasNext()) { - Map.Entry> next = iterator.next(); + for (Map.Entry> next : mTempComponents.entrySet()) { List temperatureViews = next.getValue(); for (TemperatureView view : temperatureViews) { initComponent(view); @@ -147,29 +156,29 @@ public class HvacController { } private void initComponent(TemperatureView view) { - int id = view.getPropertyId(); int zone = view.getAreaId(); if (DEBUG) { - Log.d(TAG, "initComponent: " + zone + ":" + id); + Log.d(TAG, "initComponent: " + zone); } try { - if (mHvacManager != null - && mHvacManager.isPropertyAvailable(HVAC_TEMPERATURE_DISPLAY_UNITS, - VEHICLE_AREA_TYPE_GLOBAL)) { - if (mHvacManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, + if (mCarPropertyManager != null && mCarPropertyManager.isPropertyAvailable( + HVAC_TEMPERATURE_DISPLAY_UNITS, VEHICLE_AREA_TYPE_GLOBAL)) { + if (mCarPropertyManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, VEHICLE_AREA_TYPE_GLOBAL) == VehicleUnit.FAHRENHEIT) { view.setDisplayInFahrenheit(true); } - } - if (mHvacManager == null || !mHvacManager.isPropertyAvailable(id, zone)) { - view.setTemp(Float.NaN); + if (mCarPropertyManager == null || !mCarPropertyManager.isPropertyAvailable( + HVAC_TEMPERATURE_SET, zone)) { + view.setTemperatureView(Float.NaN); return; } - view.setTemp(mHvacManager.getFloatProperty(id, zone)); + view.setTemperatureView( + mCarPropertyManager.getFloatProperty(HVAC_TEMPERATURE_SET, zone)); + view.setHvacController(this); } catch (Exception e) { - view.setTemp(Float.NaN); + view.setTemperatureView(Float.NaN); Log.e(TAG, "Failed to get value from hvac service", e); } } @@ -199,30 +208,32 @@ public class HvacController { } /** - * Key for storing {@link TemperatureView}s in a hash map + * Set the temperature in Celsius of the specified zone */ - private static class HvacKey { - - int mPropertyId; - int mAreaId; - - private HvacKey(int propertyId, int areaId) { - mPropertyId = propertyId; - mAreaId = areaId; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - HvacKey hvacKey = (HvacKey) o; - return mPropertyId == hvacKey.mPropertyId - && mAreaId == hvacKey.mAreaId; - } - - @Override - public int hashCode() { - return Objects.hash(mPropertyId, mAreaId); + public void setTemperature(float tempC, int zone) { + if (mCarPropertyManager != null) { + // Internally, all temperatures are represented in floating point Celsius + mCarPropertyManager.setFloatProperty(HVAC_TEMPERATURE_SET, zone, tempC); } } + + /** + * Convert the given temperature in Celsius into Fahrenheit + * + * @param tempC - The temperature in Celsius + * @return Temperature in Fahrenheit. + */ + public static float convertToFahrenheit(float tempC) { + return (tempC * 9f / 5f) + 32; + } + + /** + * Convert the given temperature in Fahrenheit to Celsius + * + * @param tempF - The temperature in Fahrenheit. + * @return Temperature in Celsius. + */ + public static float convertToCelsius(float tempF) { + return (float) ((tempF - 32) * 0.55555555556); + } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java index 521a665da5f61..252f7830b72cc 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java @@ -16,6 +16,8 @@ package com.android.systemui.car.hvac; +import static com.android.systemui.car.hvac.HvacController.convertToFahrenheit; + import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; @@ -27,24 +29,25 @@ import com.android.systemui.R; * Simple text display of HVAC properties, It is designed to show temperature and is configured in * the XML. * XML properties: - * hvacPropertyId - Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385) - * hvacAreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1) - * hvacTempFormat - Example: "%.1f\u00B0" (1 decimal and the degree symbol) + * hvacAreaId - Example: VehicleAreaSeat.SEAT_ROW_1_LEFT (1) */ public class TemperatureTextView extends TextView implements TemperatureView { private final int mAreaId; - private final int mPropertyId; private final String mTempFormat; + private HvacController mHvacController; private boolean mDisplayFahrenheit = false; public TemperatureTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TemperatureView); mAreaId = typedArray.getInt(R.styleable.TemperatureView_hvacAreaId, -1); - mPropertyId = typedArray.getInt(R.styleable.TemperatureView_hvacPropertyId, -1); - String format = typedArray.getString(R.styleable.TemperatureView_hvacTempFormat); - mTempFormat = (format == null) ? "%.1f\u00B0" : format; + mTempFormat = getResources().getString(R.string.hvac_temperature_format); + } + + @Override + public void setHvacController(HvacController controller) { + mHvacController = controller; } /** @@ -53,7 +56,7 @@ public class TemperatureTextView extends TextView implements TemperatureView { * @param temp - The current temp or NaN */ @Override - public void setTemp(float temp) { + public void setTemperatureView(float temp) { if (Float.isNaN(temp)) { setText("--"); return; @@ -70,15 +73,7 @@ public class TemperatureTextView extends TextView implements TemperatureView { } /** - * @return propertiyId Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385) - */ - @Override - public int getPropertyId() { - return mPropertyId; - } - - /** - * @return hvac AreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1) + * @return hvac AreaId - Example: VehicleAreaSeat.SEAT_ROW_1_LEFT (1) */ @Override public int getAreaId() { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java index 6b903fad505ce..3c0e0acc446c1 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java @@ -17,15 +17,23 @@ package com.android.systemui.car.hvac; /** - * Interface for Views that display temperature HVAC properties + * Interface for Views that display temperature HVAC properties. */ public interface TemperatureView { + + /** + * Sets the {@link HvacController} to handle changes to HVAC properties. The View is only + * responsible for the UI to display temperature. It should not contain logic that makes direct + * changes to HVAC properties and instead use this {@link HvacController}. + */ + void setHvacController(HvacController controller); + /** * Formats the float for display * * @param temp - The current temp in Celsius or NaN */ - void setTemp(float temp); + void setTemperatureView(float temp); /** * Render the displayed temperature in Fahrenheit @@ -35,22 +43,7 @@ public interface TemperatureView { void setDisplayInFahrenheit(boolean displayFahrenheit); /** - * Convert the given temperature in Celsius into Fahrenheit - * - * @param realTemp - The temperature in Celsius - * @return Temperature in Fahrenheit. - */ - default float convertToFahrenheit(float realTemp) { - return (realTemp * 9f / 5f) + 32; - } - - /** - * @return propertiyId Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385) - */ - int getPropertyId(); - - /** - * @return hvac AreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1) + * @return hvac AreaId - Example: VehicleAreaSeat.SEAT_ROW_1_LEFT (1) */ int getAreaId(); } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java new file mode 100644 index 0000000000000..e8850def6bcd1 --- /dev/null +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.car.hvac; + +import static android.car.VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_SET; + +import static com.android.systemui.car.hvac.HvacController.convertToCelsius; +import static com.android.systemui.car.hvac.HvacController.convertToFahrenheit; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.car.Car; +import android.car.VehicleUnit; +import android.car.hardware.property.CarPropertyManager; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.widget.TextView; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.car.CarSystemUiTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@CarSystemUiTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +@SmallTest +public class AdjustableTemperatureViewTest extends SysuiTestCase { + + private static final float TEMP_CELSIUS = 22.0f; + private final String mFormat = getContext().getString(R.string.hvac_temperature_format); + private AdjustableTemperatureView mAdjustableTemperatureView; + private HvacController mHvacController; + + @Mock + private Car mCar; + @Mock + private CarPropertyManager mCarPropertyManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mCar.isConnected()).thenReturn(true); + when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager); + + CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar); + mHvacController = new HvacController(carServiceProvider); + mHvacController.connectToCarService(); + mAdjustableTemperatureView = new AdjustableTemperatureView(getContext(), /* attrs= */ null); + mAdjustableTemperatureView.setHvacController(mHvacController); + } + + @Test + public void addTemperatureViewToController_setsTemperatureView() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP_CELSIUS); + + mHvacController.addTemperatureViewToController(mAdjustableTemperatureView); + + TextView tempText = mAdjustableTemperatureView.findViewById(R.id.hvac_temperature_text); + assertEquals(tempText.getText(), String.format(mFormat, TEMP_CELSIUS)); + } + + @Test + public void setTemperatureToFahrenheit_callsViewSetDisplayInFahrenheit() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP_CELSIUS); + when(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(true); + when(mCarPropertyManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(VehicleUnit.FAHRENHEIT); + + mHvacController.addTemperatureViewToController(mAdjustableTemperatureView); + + TextView tempText = mAdjustableTemperatureView.findViewById(R.id.hvac_temperature_text); + assertEquals(tempText.getText(), String.format(mFormat, convertToFahrenheit(TEMP_CELSIUS))); + } + + @Test + public void adjustableViewIncreaseButton_setsTempWithCarPropertyManager() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP_CELSIUS); + mHvacController.addTemperatureViewToController(mAdjustableTemperatureView); + + mAdjustableTemperatureView.findViewById(R.id.hvac_increase_button).callOnClick(); + + verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), + eq(TEMP_CELSIUS + 1)); + } + + @Test + public void adjustableViewDecreaseButton_setsTempWithCarPropertyManager() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP_CELSIUS); + mHvacController.addTemperatureViewToController(mAdjustableTemperatureView); + + mAdjustableTemperatureView.findViewById(R.id.hvac_decrease_button).callOnClick(); + + verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), + eq(TEMP_CELSIUS - 1)); + } + + @Test + public void adjustableViewIncreaseButton_inFahrenheit_setsTempWithCarPropertyManager() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP_CELSIUS); + when(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(true); + when(mCarPropertyManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(VehicleUnit.FAHRENHEIT); + mHvacController.addTemperatureViewToController(mAdjustableTemperatureView); + + mAdjustableTemperatureView.findViewById(R.id.hvac_increase_button).callOnClick(); + + verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), + eq(convertToCelsius(convertToFahrenheit(TEMP_CELSIUS) + 1))); + } + + @Test + public void adjustableViewDecreaseButton_inFahrenheit_setsTempWithCarPropertyManager() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP_CELSIUS); + when(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(true); + when(mCarPropertyManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(VehicleUnit.FAHRENHEIT); + mHvacController.addTemperatureViewToController(mAdjustableTemperatureView); + + mAdjustableTemperatureView.findViewById(R.id.hvac_decrease_button).callOnClick(); + + verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), + eq(convertToCelsius(convertToFahrenheit(TEMP_CELSIUS) - 1))); + } +} diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java index e179ef1ce2a41..9912657d78e1b 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java @@ -16,7 +16,13 @@ package com.android.systemui.car.hvac; +import static android.car.VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_SET; + import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -24,7 +30,8 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.car.Car; -import android.car.hardware.hvac.CarHvacManager; +import android.car.VehicleUnit; +import android.car.hardware.property.CarPropertyManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -46,92 +53,91 @@ import org.mockito.MockitoAnnotations; @SmallTest public class HvacControllerTest extends SysuiTestCase { - private static final int PROPERTY_ID = 1; private static final int AREA_ID = 1; - private static final float VALUE = 72.0f; + private static final float TEMP = 72.0f; private HvacController mHvacController; - private CarServiceProvider mCarServiceProvider; @Mock private Car mCar; @Mock - private CarHvacManager mCarHvacManager; + private CarPropertyManager mCarPropertyManager; @Before public void setUp() { MockitoAnnotations.initMocks(this); when(mCar.isConnected()).thenReturn(true); - when(mCar.getCarManager(Car.HVAC_SERVICE)).thenReturn(mCarHvacManager); + when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager); - mCarServiceProvider = new CarServiceProvider(mContext, mCar); - mHvacController = new HvacController(mCarServiceProvider); + CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar); + mHvacController = new HvacController(carServiceProvider); mHvacController.connectToCarService(); } @Test public void connectToCarService_registersCallback() { - verify(mCarHvacManager).registerCallback(any()); + verify(mCarPropertyManager).registerCallback(any(), eq(HVAC_TEMPERATURE_SET), anyFloat()); + verify(mCarPropertyManager).registerCallback(any(), eq(HVAC_TEMPERATURE_DISPLAY_UNITS), + anyFloat()); } @Test public void addTemperatureViewToController_usingTemperatureView_registersView() { - TemperatureTextView v = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE); + TemperatureTextView v = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v); - verify(v).setTemp(VALUE); + verify(v).setTemperatureView(TEMP); } @Test public void addTemperatureViewToController_usingSameTemperatureView_registersFirstView() { - TemperatureTextView v = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE); + TemperatureTextView v = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v); - verify(v).setTemp(VALUE); - resetTemperatureView(v, PROPERTY_ID, AREA_ID); + verify(v).setTemperatureView(TEMP); + resetTemperatureView(v, AREA_ID); mHvacController.addTemperatureViewToController(v); - verify(v, never()).setTemp(VALUE); + verify(v, never()).setTemperatureView(TEMP); } @Test public void addTemperatureViewToController_usingDifferentTemperatureView_registersBothViews() { - TemperatureTextView v1 = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE); + TemperatureTextView v1 = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v1); - verify(v1).setTemp(VALUE); + verify(v1).setTemperatureView(TEMP); TemperatureTextView v2 = setupMockTemperatureTextView( - PROPERTY_ID + 1, AREA_ID + 1, - VALUE + 1); + TEMP + 1); mHvacController.addTemperatureViewToController(v2); - verify(v2).setTemp(VALUE + 1); + verify(v2).setTemperatureView(TEMP + 1); } @Test - public void removeAllComponents_ableToRegisterSameView() { - TemperatureTextView v = setupMockTemperatureTextView(PROPERTY_ID, AREA_ID, VALUE); - mHvacController.addTemperatureViewToController(v); - verify(v).setTemp(VALUE); - - mHvacController.removeAllComponents(); - resetTemperatureView(v, PROPERTY_ID, AREA_ID); + public void setTemperatureToFahrenheit_callsViewSetDisplayInFahrenheit() { + when(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(true); + when(mCarPropertyManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(VehicleUnit.FAHRENHEIT); + TemperatureTextView v = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v); - verify(v).setTemp(VALUE); + + verify(v).setDisplayInFahrenheit(true); + verify(v).setTemperatureView(TEMP); } - private TemperatureTextView setupMockTemperatureTextView(int propertyId, int areaId, - float value) { + private TemperatureTextView setupMockTemperatureTextView(int areaId, float value) { TemperatureTextView v = mock(TemperatureTextView.class); - resetTemperatureView(v, propertyId, areaId); - when(mCarHvacManager.isPropertyAvailable(propertyId, areaId)).thenReturn(true); - when(mCarHvacManager.getFloatProperty(propertyId, areaId)).thenReturn(value); + resetTemperatureView(v, areaId); + when(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_SET, areaId)).thenReturn( + true); + when(mCarPropertyManager.getFloatProperty(HVAC_TEMPERATURE_SET, areaId)).thenReturn(value); return v; } - private void resetTemperatureView(TemperatureTextView view, int propertyId, int areaId) { + private void resetTemperatureView(TemperatureTextView view, int areaId) { reset(view); - when(view.getPropertyId()).thenReturn(propertyId); when(view.getAreaId()).thenReturn(areaId); } } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java new file mode 100644 index 0000000000000..e97d9d9b3f6a9 --- /dev/null +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2020 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. + */ + +package com.android.systemui.car.hvac; + +import static android.car.VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS; +import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_SET; + +import static com.android.systemui.car.hvac.HvacController.convertToFahrenheit; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import android.car.Car; +import android.car.VehicleUnit; +import android.car.hardware.property.CarPropertyManager; +import android.content.Context; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.car.CarServiceProvider; +import com.android.systemui.car.CarSystemUiTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@CarSystemUiTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +@SmallTest +public class TemperatureTextViewTest extends SysuiTestCase { + private static final float TEMP = 72.0f; + private final String mFormat = getContext().getString(R.string.hvac_temperature_format); + private HvacController mHvacController; + private TemperatureTextView mTextView; + + @Mock + private Context mContext; + + @Mock + private Car mCar; + @Mock + private CarPropertyManager mCarPropertyManager; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mCar.isConnected()).thenReturn(true); + when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager); + + CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar); + mHvacController = new HvacController(carServiceProvider); + mHvacController.connectToCarService(); + mTextView = new TemperatureTextView(getContext(), /* attrs= */ null); + } + + @Test + public void addTemperatureViewToController_usingTemperatureView_registersView() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP); + + mHvacController.addTemperatureViewToController(mTextView); + + assertEquals(mTextView.getText(), String.format(mFormat, TEMP)); + } + + @Test + public void setTemperatureToFahrenheit_callsViewSetDisplayInFahrenheit() { + when(mCarPropertyManager.isPropertyAvailable(eq(HVAC_TEMPERATURE_SET), + anyInt())).thenReturn(true); + when(mCarPropertyManager.getFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt())).thenReturn( + TEMP); + when(mCarPropertyManager.isPropertyAvailable(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(true); + when(mCarPropertyManager.getIntProperty(HVAC_TEMPERATURE_DISPLAY_UNITS, + VEHICLE_AREA_TYPE_GLOBAL)).thenReturn(VehicleUnit.FAHRENHEIT); + + mHvacController.addTemperatureViewToController(mTextView); + + assertEquals(mTextView.getText(), String.format(mFormat, convertToFahrenheit(TEMP))); + } +}