Merge "Schematize Car system properties"
diff --git a/res/drawable/ic_fan_direction_1.xml b/res/drawable/ic_fan_direction_1.xml
new file mode 100644
index 0000000..04295cb
--- /dev/null
+++ b/res/drawable/ic_fan_direction_1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:drawable="@drawable/ic_fan_direction_1_on"/>
+    <item android:drawable="@drawable/ic_fan_direction_1_off"/>
+</selector>
diff --git a/res/drawable/ic_fan_direction_1_off.xml b/res/drawable/ic_fan_direction_1_off.xml
index d41e16b..06309ec 100644
--- a/res/drawable/ic_fan_direction_1_off.xml
+++ b/res/drawable/ic_fan_direction_1_off.xml
@@ -18,6 +18,7 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:viewportWidth="108"
         android:viewportHeight="108"
+        android:alpha="0.5"
         android:width="108dp"
         android:height="108dp">
     <group
@@ -35,4 +36,4 @@
     <path
             android:pathData="M67.648549 39.158549c-2.1 -1.493334 -2.613334 -4.386667 -1.143334 -6.51 1.47 -2.1 4.386667 -2.613334 6.51 -1.143334 2.1 1.493334 2.613334 4.386667 1.143334 6.51 -1.493334 2.1 -4.386667 2.613334 -6.51 1.143334l0 0z"
             android:fillColor="#f5f5f5" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/res/drawable/ic_fan_direction_2.xml b/res/drawable/ic_fan_direction_2.xml
new file mode 100644
index 0000000..c99c487
--- /dev/null
+++ b/res/drawable/ic_fan_direction_2.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:drawable="@drawable/ic_fan_direction_2_on"/>
+    <item android:drawable="@drawable/ic_fan_direction_2_off"/>
+</selector>
diff --git a/res/drawable/ic_fan_direction_2_off.xml b/res/drawable/ic_fan_direction_2_off.xml
index 63bde96..6308a4d 100644
--- a/res/drawable/ic_fan_direction_2_off.xml
+++ b/res/drawable/ic_fan_direction_2_off.xml
@@ -18,6 +18,7 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:viewportWidth="108"
         android:viewportHeight="108"
+        android:alpha="0.5"
         android:width="108dp"
         android:height="108dp">
     <group
@@ -43,4 +44,4 @@
     <path
             android:pathData="M67.648549 39.158549c-2.1 -1.493334 -2.613334 -4.386667 -1.143334 -6.51 1.47 -2.1 4.386667 -2.613334 6.51 -1.143334 2.1 1.493334 2.613334 4.386667 1.143334 6.51 -1.493334 2.1 -4.386667 2.613334 -6.51 1.143334l0 0z"
             android:fillColor="#f5f5f5" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/res/drawable/ic_fan_direction_3.xml b/res/drawable/ic_fan_direction_3.xml
new file mode 100644
index 0000000..35ac244
--- /dev/null
+++ b/res/drawable/ic_fan_direction_3.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:drawable="@drawable/ic_fan_direction_3_on"/>
+    <item android:drawable="@drawable/ic_fan_direction_3_off"/>
+</selector>
diff --git a/res/drawable/ic_fan_direction_3_off.xml b/res/drawable/ic_fan_direction_3_off.xml
index 094708b..cfebad6 100644
--- a/res/drawable/ic_fan_direction_3_off.xml
+++ b/res/drawable/ic_fan_direction_3_off.xml
@@ -18,6 +18,7 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:viewportWidth="108"
         android:viewportHeight="108"
+        android:alpha="0.5"
         android:width="108dp"
         android:height="108dp">
     <group
@@ -34,4 +35,4 @@
     <path
             android:pathData="M67.648549 39.158549c-2.1 -1.493334 -2.613334 -4.386667 -1.143334 -6.51 1.47 -2.1 4.386667 -2.613334 6.51 -1.143334 2.1 1.493334 2.613334 4.386667 1.143334 6.51 -1.493334 2.1 -4.386667 2.613334 -6.51 1.143334l0 0z"
             android:fillColor="#f5f5f5" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/res/drawable/ic_fan_direction_4.xml b/res/drawable/ic_fan_direction_4.xml
new file mode 100644
index 0000000..5777c9f
--- /dev/null
+++ b/res/drawable/ic_fan_direction_4.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_selected="true" android:drawable="@drawable/ic_fan_direction_4_on"/>
+    <item android:drawable="@drawable/ic_fan_direction_4_off"/>
+</selector>
diff --git a/res/drawable/ic_fan_direction_4_off.xml b/res/drawable/ic_fan_direction_4_off.xml
index 92d3a2f..c86ac02 100644
--- a/res/drawable/ic_fan_direction_4_off.xml
+++ b/res/drawable/ic_fan_direction_4_off.xml
@@ -18,6 +18,7 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:viewportWidth="108"
         android:viewportHeight="108"
+        android:alpha="0.5"
         android:width="108dp"
         android:height="108dp">
     <group
@@ -46,4 +47,4 @@
     <path
             android:pathData="M58.865571 43.748823l-1.516285 -0.824117 3.63 -7.08C60.612857 35.418088 59.919857 34.705147 58.870714 33.998823 56.667 32.516471 54.018857 31.765147 51 31.765147c-3.018857 0 -5.667 0.751324 -7.870714 2.233676 -1.048715 0.705883 -1.741286 1.418383 -2.108572 1.846324L44.650286 42.924706 43.134 43.748823 39 35.685441 39.291 35.246029C39.433286 35.031618 42.862714 30 51 30c8.137286 0 11.566714 5.031618 11.709 5.246029L63 35.685441 58.865571 43.748823Z"
             android:fillColor="#f5f5f5" />
-</vector>
\ No newline at end of file
+</vector>
diff --git a/res/layout/fan_direction.xml b/res/layout/fan_direction.xml
index a3e15fc..1b07ee4 100644
--- a/res/layout/fan_direction.xml
+++ b/res/layout/fan_direction.xml
@@ -20,24 +20,24 @@
        android:layout_height="match_parent">
     <ImageView
             android:id="@+id/direction_1"
-            android:src="@drawable/ic_fan_direction_1_off"
+            android:src="@drawable/ic_fan_direction_1"
             style="@style/HvacButton.FanDirection"/>
     <View
             style="@style/HvacSpacerView"/>
     <ImageView
             android:id="@+id/direction_2"
-            android:src="@drawable/ic_fan_direction_2_off"
+            android:src="@drawable/ic_fan_direction_2"
             style="@style/HvacButton.FanDirection"/>
     <View
             style="@style/HvacSpacerView"/>
     <ImageView
             android:id="@+id/direction_3"
-            android:src="@drawable/ic_fan_direction_3_off"
+            android:src="@drawable/ic_fan_direction_3"
             style="@style/HvacButton.FanDirection"/>
     <View
             style="@style/HvacSpacerView"/>
     <ImageView
             android:id="@+id/direction_4"
-            android:src="@drawable/ic_fan_direction_4_off"
+            android:src="@drawable/ic_fan_direction_4"
             style="@style/HvacButton.FanDirection"/>
-</merge>
\ No newline at end of file
+</merge>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 1500c4b..482b50f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -83,7 +83,6 @@
     </style>
 
     <style name="HvacButton.FanDirection" parent="HvacButton">
-        <item name="android:alpha">0.5</item>
         <item name="android:layout_gravity">center</item>
         <item name="android:scaleType">fitCenter</item>
     </style>
diff --git a/src/com/android/car/hvac/controllers/FanDirectionButtonsController.java b/src/com/android/car/hvac/controllers/FanDirectionButtonsController.java
index f0721b8..9df731e 100644
--- a/src/com/android/car/hvac/controllers/FanDirectionButtonsController.java
+++ b/src/com/android/car/hvac/controllers/FanDirectionButtonsController.java
@@ -16,6 +16,7 @@
 package com.android.car.hvac.controllers;
 
 import android.car.hardware.hvac.CarHvacManager;
+import android.util.Log;
 import android.util.SparseIntArray;
 
 import com.android.car.hvac.HvacController;
@@ -27,11 +28,11 @@
  * constants in the vehicle hardware.
  */
 public class FanDirectionButtonsController {
-    private final static int FAN_DIRECTION_COUNT = 4;
-
+    private static final String TAG = "FanDirectionButtonsController";
     private final FanDirectionButtons mFanDirectionButtons;
     private final HvacController mHvacController;
-    private final SparseIntArray mFanDirectionMap = new SparseIntArray(FAN_DIRECTION_COUNT);
+    private final SparseIntArray mFanDirectionMap =
+            new SparseIntArray(FanDirectionButtons.FAN_DIRECTION_COUNT);
 
     public FanDirectionButtonsController(FanDirectionButtons speedBar, HvacController controller) {
         mFanDirectionButtons = speedBar;
@@ -51,6 +52,7 @@
         mFanDirectionMap.put(FanDirectionButtons.FAN_DIRECTION_FLOOR_DEFROSTER,
                 (CarHvacManager.FAN_DIRECTION_DEFROST | CarHvacManager.FAN_DIRECTION_FLOOR));
         mFanDirectionButtons.setFanDirectionClickListener(mListener);
+        mHvacController.registerCallback(mCallback);
     }
 
     private final FanDirectionButtons.FanDirectionClickListener mListener
@@ -60,4 +62,16 @@
             mHvacController.setFanDirection(mFanDirectionMap.get(direction));
         }
     };
+
+    private HvacController.Callback mCallback = new HvacController.Callback() {
+        @Override
+        public void onFanDirectionChange(int direction) {
+            int index = mFanDirectionMap.indexOfValue(direction);
+            if (index == -1) {
+                Log.w(TAG, "Unexpected fan direction: " + direction);
+                return;
+            }
+            mFanDirectionButtons.setFanDirection(mFanDirectionMap.keyAt(index));
+        }
+    };
 }
diff --git a/src/com/android/car/hvac/ui/FanDirectionButtons.java b/src/com/android/car/hvac/ui/FanDirectionButtons.java
index b07de9b..a7a6f3f 100644
--- a/src/com/android/car/hvac/ui/FanDirectionButtons.java
+++ b/src/com/android/car/hvac/ui/FanDirectionButtons.java
@@ -16,20 +16,14 @@
 package com.android.car.hvac.ui;
 
 import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Pair;
-import android.view.View;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
 import androidx.annotation.IntDef;
 
 import com.android.car.hvac.R;
-
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
 
 /**
  * A set of buttons that controls the fan direction of the vehicle. Turning on one state will
@@ -40,24 +34,28 @@
     public static final int FAN_DIRECTION_FACE_FLOOR = 1;
     public static final int FAN_DIRECTION_FLOOR = 2;
     public static final int FAN_DIRECTION_FLOOR_DEFROSTER = 3;
+    public static final int FAN_DIRECTION_COUNT = 4;
 
     @IntDef({FAN_DIRECTION_FACE, FAN_DIRECTION_FACE_FLOOR,
             FAN_DIRECTION_FLOOR, FAN_DIRECTION_FLOOR_DEFROSTER})
     public @interface FanDirection {}
 
     /**
+     * A resource id array for all fan direction buttons.
+     */
+    private static final int[] FAN_DIRECTION_BUTTON_IDS = { R.id.direction_1, R.id.direction_2,
+                                  R.id.direction_3, R.id.direction_4 };
+
+    /**
      * A listener that is notified when a fan direction button has been clicked.
      */
     public interface FanDirectionClickListener {
         void onFanDirectionClicked(@FanDirection int direction);
     }
 
-    private static final float UNSELECTED_BUTTON_ALPHA = 0.5f;
-    private static final float SELECTED_BUTTON_ALPHA = 1.0f;
+    private final ArrayList<ImageView> mButtonArray = new ArrayList<ImageView>();
 
-    private final Map<ImageView, Pair<Drawable, Drawable>> mFanMap = new HashMap<>();
-    private final Map<ImageView, Integer> mControlMap = new HashMap<>();
-
+    private int mCurrentDirection = -1;
     private FanDirectionClickListener mListener;
 
     public FanDirectionButtons(Context context) {
@@ -79,6 +77,12 @@
         mListener = listener;
     }
 
+    public void setFanDirection(@FanDirection int direction) {
+        if (direction != mCurrentDirection) {
+            updateFanButtonToOn(direction);
+        }
+    }
+
     private void init() {
         inflate(getContext(), R.layout.fan_direction, this);
     }
@@ -86,59 +90,30 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        Resources res = getResources();
-
         setOrientation(HORIZONTAL);
 
-        ImageView directionButton1 = (ImageView) findViewById(R.id.direction_1);
-        ImageView directionButton2 = (ImageView) findViewById(R.id.direction_2);
-        ImageView directionButton3 = (ImageView) findViewById(R.id.direction_3);
-        ImageView directionButton4 = (ImageView) findViewById(R.id.direction_4);
+        for (int i = 0; i < FAN_DIRECTION_COUNT; i++) {
+            ImageView button = (ImageView) findViewById(FAN_DIRECTION_BUTTON_IDS[i]);
+            button.setTag(i);
+            button.setOnClickListener(v -> {
+                int direction = (int) v.getTag();
+                if (direction != mCurrentDirection) {
+                    updateFanButtonToOn(direction);
+                    if (mListener != null) {
+                        mListener.onFanDirectionClicked(direction);
+                    }
+                }
+            });
 
-        Drawable directionOn1 = res.getDrawable(R.drawable.ic_fan_direction_1_on);
-        Drawable directionOn2 = res.getDrawable(R.drawable.ic_fan_direction_2_on);
-        Drawable directionOn3 = res.getDrawable(R.drawable.ic_fan_direction_3_on);
-        Drawable directionOn4 = res.getDrawable(R.drawable.ic_fan_direction_4_on);
-
-        Drawable directionOff1 = res.getDrawable(R.drawable.ic_fan_direction_1_off);
-        Drawable directionOff2 = res.getDrawable(R.drawable.ic_fan_direction_2_off);
-        Drawable directionOff3 = res.getDrawable(R.drawable.ic_fan_direction_3_off);
-        Drawable directionOff4 = res.getDrawable(R.drawable.ic_fan_direction_4_off);
-
-        mFanMap.put(directionButton1, new Pair(directionOn1, directionOff1));
-        mFanMap.put(directionButton2, new Pair(directionOn2, directionOff2));
-        mFanMap.put(directionButton3, new Pair(directionOn3, directionOff3));
-        mFanMap.put(directionButton4, new Pair(directionOn4, directionOff4));
-
-        mControlMap.put(directionButton1, FAN_DIRECTION_FACE);
-        mControlMap.put(directionButton2, FAN_DIRECTION_FACE_FLOOR);
-        mControlMap.put(directionButton3, FAN_DIRECTION_FLOOR);
-        mControlMap.put(directionButton4, FAN_DIRECTION_FLOOR_DEFROSTER);
-
-        for (ImageView v : mFanMap.keySet()) {
-            v.setOnClickListener(mFanDirectionClickListener);
+            mButtonArray.add(button);
         }
     }
 
-    private final OnClickListener mFanDirectionClickListener = new OnClickListener() {
-        @Override
-        public void onClick(View v) {
-            resetFanToOff();
-            v.setAlpha(SELECTED_BUTTON_ALPHA);
-            if (mFanMap.containsKey(v)) {
-                ((ImageView) v).setImageDrawable(mFanMap.get(v).first);
-                v.setAlpha(SELECTED_BUTTON_ALPHA);
-                @FanDirection int direction = mControlMap.get(v);
-                mListener.onFanDirectionClicked(direction);
-            }
+    private void updateFanButtonToOn(int directionToOn) {
+        if (mCurrentDirection != -1) {
+            mButtonArray.get(mCurrentDirection).setSelected(false);
         }
-    };
-
-    private void resetFanToOff() {
-        for (Map.Entry<ImageView, Pair<Drawable, Drawable>> entry : mFanMap.entrySet()) {
-            ImageView button = entry.getKey();
-            button.setImageDrawable(entry.getValue().second);
-            button.setAlpha(UNSELECTED_BUTTON_ALPHA);
-        }
+        mButtonArray.get(directionToOn).setSelected(true);
+        mCurrentDirection = directionToOn;
     }
 }