Add an option to display HVAC temp values in sysui

Bug: 77148007
Test: on device that has a real HVAC unit
Change-Id: I97b303dd947858157ede72c5d537ae6a1e40cc67
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 68293d9..df21151 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -56,7 +56,8 @@
     SystemUI-tags \
     SystemUI-proto
 
-LOCAL_JAVA_LIBRARIES := telephony-common
+LOCAL_JAVA_LIBRARIES := telephony-common \
+    android.car
 
 LOCAL_PACKAGE_NAME := SystemUI
 LOCAL_PRIVATE_PLATFORM_APIS := true
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3d49e5c..3488168 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -205,6 +205,9 @@
     <!-- Listen app op changes -->
     <uses-permission android:name="android.permission.WATCH_APPOPS" />
 
+    <!-- to read and change hvac values in a car -->
+    <uses-permission android:name="android.car.permission.ADJUST_CAR_CLIMATE" />
+
     <application
         android:name=".SystemUIApplication"
         android:persistent="true"
diff --git a/packages/SystemUI/res/layout/car_facet_button.xml b/packages/SystemUI/res/layout/car_facet_button.xml
index f432d36..ad86049 100644
--- a/packages/SystemUI/res/layout/car_facet_button.xml
+++ b/packages/SystemUI/res/layout/car_facet_button.xml
@@ -42,6 +42,7 @@
             android:layout_height="wrap_content"
             android:layout_width="match_parent"
             android:animateLayoutChanges="true"
+            android:src="@drawable/car_ic_arrow"
             android:background="@android:color/transparent"
             android:scaleType="fitCenter">
         </com.android.keyguard.AlphaOptimizedImageButton>
diff --git a/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
new file mode 100644
index 0000000..a65ff16
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_left_navigation_bar_unprovisioned.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:orientation="vertical"
+    android:background="@drawable/system_bar_background">
+
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:id="@+id/nav_buttons"
+        android:orientation="vertical"
+        android:gravity="top"
+        android:paddingTop="30dp"
+        android:layout_weight="1"
+        android:background="@drawable/system_bar_background"
+        android:animateLayoutChanges="true">
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+            android:src="@drawable/car_ic_overview"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/hvac"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+            systemui:broadcast="true"
+            android:src="@drawable/car_ic_hvac"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+    </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
new file mode 100644
index 0000000..b0488ae
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:background="@drawable/system_bar_background">
+
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+        android:orientation="horizontal"
+        android:id="@+id/nav_buttons"
+        android:gravity="left"
+        android:paddingLeft="30dp"
+        android:layout_weight="1"
+        android:animateLayoutChanges="true">
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_height="match_parent"
+            android:layout_width="wrap_content"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+            android:src="@drawable/car_ic_overview"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingLeft="30dp"
+            android:paddingRight="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/hvac"
+            android:layout_height="match_parent"
+            android:layout_width="wrap_content"
+            systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+            systemui:broadcast="true"
+            android:src="@drawable/car_ic_hvac"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingLeft="30dp"
+            android:paddingRight="30dp"
+        />
+    </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
+
diff --git a/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
new file mode 100644
index 0000000..a65ff16
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_right_navigation_bar_unprovisioned.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:orientation="vertical"
+    android:background="@drawable/system_bar_background">
+
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:id="@+id/nav_buttons"
+        android:orientation="vertical"
+        android:gravity="top"
+        android:paddingTop="30dp"
+        android:layout_weight="1"
+        android:background="@drawable/system_bar_background"
+        android:animateLayoutChanges="true">
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/home"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.HOME;end"
+            android:src="@drawable/car_ic_overview"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+
+        <com.android.systemui.statusbar.car.CarNavigationButton
+            android:id="@+id/hvac"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            systemui:intent="intent:#Intent;action=android.car.intent.action.TOGGLE_HVAC_CONTROLS;end"
+            systemui:broadcast="true"
+            android:src="@drawable/car_ic_hvac"
+            android:background="?android:attr/selectableItemBackground"
+            android:paddingTop="30dp"
+            android:paddingBottom="30dp"
+        />
+    </LinearLayout>
+</com.android.systemui.statusbar.car.CarNavigationBarView>
diff --git a/packages/SystemUI/res/layout/car_status_bar_header.xml b/packages/SystemUI/res/layout/car_status_bar_header.xml
index 158907e..f2ef301 100644
--- a/packages/SystemUI/res/layout/car_status_bar_header.xml
+++ b/packages/SystemUI/res/layout/car_status_bar_header.xml
@@ -13,7 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<!-- Extends RelativeLayout -->
+<!-- Extends LinearLayout -->
 <com.android.systemui.qs.car.CarStatusBarHeader
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res-auto"
@@ -23,22 +23,21 @@
     android:paddingStart="8dp"
     android:paddingEnd="8dp" >
 
-    <include
-        layout="@layout/system_icons"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
-        android:layout_alignParentStart="true"
-        android:layout_centerVertical="true" />
+    <include layout="@layout/system_icons"
+             android:layout_width="wrap_content"
+             android:layout_height="match_parent"
+             android:gravity="center_vertical|end"
+             android:layout_weight="1"
+    />
 
     <com.android.systemui.statusbar.policy.Clock
         android:id="@+id/clock"
         android:textAppearance="@style/TextAppearance.StatusBar.Clock"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
-        android:layout_alignParentEnd="true"
-        android:layout_centerVertical="true"
         android:singleLine="true"
         android:paddingStart="@dimen/status_bar_clock_starting_padding"
         android:paddingEnd="@dimen/status_bar_clock_end_padding"
-        systemui:showDark="false" />
+        android:gravity="center_vertical|end"
+    />
 </com.android.systemui.qs.car.CarStatusBarHeader>
diff --git a/packages/SystemUI/res/layout/car_top_navigation_bar.xml b/packages/SystemUI/res/layout/car_top_navigation_bar.xml
new file mode 100644
index 0000000..e16014b
--- /dev/null
+++ b/packages/SystemUI/res/layout/car_top_navigation_bar.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+** Copyright 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.
+*/
+-->
+
+<com.android.systemui.statusbar.car.CarNavigationBarView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:background="@drawable/system_bar_background">
+
+    <com.android.systemui.statusbar.policy.Clock
+        android:id="@+id/clock"
+        android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:singleLine="true"
+        android:paddingStart="@dimen/status_bar_clock_starting_padding"
+        android:paddingEnd="@dimen/status_bar_clock_end_padding"
+        android:gravity="center_vertical"
+    />
+
+</com.android.systemui.statusbar.car.CarNavigationBarView>
+
diff --git a/packages/SystemUI/res/values/attrs_car.xml b/packages/SystemUI/res/values/attrs_car.xml
index b1097c3..5e4bd79 100644
--- a/packages/SystemUI/res/values/attrs_car.xml
+++ b/packages/SystemUI/res/values/attrs_car.xml
@@ -27,6 +27,13 @@
         <attr name="categories" format="string"/>
         <!-- package names that will be added as extras to the fired intents -->
         <attr name="packages" format="string" />
+        <!-- Alpha value to used when in selected state.  Defaults 1f  -->
+        <attr name="selectedAlpha" format="float" />
+        <!-- Alpha value to used when in un-selected state.  Defaults 0.7f  -->
+        <attr name="unselectedAlpha" format="float" />
+        <!-- Render a "more" icon. Defaults true  -->
+        <attr name="useMoreIcon" format="boolean" />
+
     </declare-styleable>
 
 
@@ -39,4 +46,11 @@
         <!-- start the intent as a broad cast instead of an activity if true-->
         <attr name="broadcast" format="boolean"/>
     </declare-styleable>
+
+    <!-- Custom attributes to configure hvac values -->
+    <declare-styleable name="TemperatureView">
+        <attr name="hvacAreaId" format="integer"/>
+        <attr name="hvacPropertyId" format="integer"/>
+        <attr name="hvacTempFormat" format="string"/>
+    </declare-styleable>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
index 245d240..9459ce1 100644
--- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java
@@ -21,6 +21,8 @@
 import com.android.systemui.Dependency.DependencyProvider;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.statusbar.NotificationEntryManager;
+import com.android.systemui.statusbar.car.CarFacetButtonController;
+import com.android.systemui.statusbar.car.hvac.HvacController;
 
 /**
  * Class factory to provide car specific SystemUI components.
@@ -32,5 +34,7 @@
         super.injectDependencies(providers, context);
         providers.put(NotificationEntryManager.class,
                 () -> new CarNotificationEntryManager(context));
+        providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context));
+        providers.put(HvacController.class, () -> new HvacController(context));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
index 6797bb9..ec18376 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarStatusBarHeader.java
@@ -19,7 +19,7 @@
 import android.support.annotation.IdRes;
 import android.util.AttributeSet;
 import android.view.View;
-import android.widget.RelativeLayout;
+import android.widget.LinearLayout;
 
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
@@ -30,7 +30,7 @@
  * A view that forms the header of the notification panel. This view will ensure that any
  * status icons that are displayed are tinted accordingly to the current theme.
  */
-public class CarStatusBarHeader extends RelativeLayout {
+public class CarStatusBarHeader extends LinearLayout {
     public CarStatusBarHeader(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
index 53101a5..5f3e2e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java
@@ -3,6 +3,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -10,6 +11,7 @@
 import android.widget.LinearLayout;
 
 import com.android.keyguard.AlphaOptimizedImageButton;
+import com.android.systemui.Dependency;
 import com.android.systemui.R;
 
 /**
@@ -21,9 +23,6 @@
  * other music apps installed.
  */
 public class CarFacetButton extends LinearLayout {
-    private static final float SELECTED_ALPHA = 1f;
-    private static final float UNSELECTED_ALPHA = 0.7f;
-
     private static final String FACET_FILTER_DELIMITER = ";";
     /**
      * Extra information to be sent to a helper to make the decision of what app to launch when
@@ -42,6 +41,10 @@
     private String[] mFacetCategories;
     /** App packages that are allowed to be used with this widget */
     private String[] mFacetPackages;
+    private int mIconResourceId;
+    private boolean mUseMoreIcon = true;
+    private float mSelectedAlpha = 1f;
+    private float mUnselectedAlpha = 1f;
 
 
     public CarFacetButton(Context context, AttributeSet attrs) {
@@ -53,6 +56,10 @@
         TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton);
         setupIntents(typedArray);
         setupIcons(typedArray);
+        CarFacetButtonController carFacetButtonController = Dependency.get(
+                CarFacetButtonController.class);
+        carFacetButtonController.addFacetButton(this);
+
     }
 
     /**
@@ -96,21 +103,25 @@
 
 
     private void setupIcons(TypedArray styledAttributes) {
+        mSelectedAlpha = styledAttributes.getFloat(
+                R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha);
+        mUnselectedAlpha = styledAttributes.getFloat(
+                R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha);
         mIcon = findViewById(R.id.car_nav_button_icon);
         mIcon.setScaleType(ImageView.ScaleType.CENTER);
         mIcon.setClickable(false);
-        mIcon.setAlpha(UNSELECTED_ALPHA);
-        int iconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
-        if (iconResourceId == 0)  {
+        mIcon.setAlpha(mUnselectedAlpha);
+        mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0);
+        if (mIconResourceId == 0)  {
             throw new RuntimeException("specified icon resource was not found and is required");
         }
-        mIcon.setImageResource(iconResourceId);
+        mIcon.setImageResource(mIconResourceId);
 
         mMoreIcon = findViewById(R.id.car_nav_button_more_icon);
         mMoreIcon.setClickable(false);
-        mMoreIcon.setImageDrawable(getContext().getDrawable(R.drawable.car_ic_arrow));
-        mMoreIcon.setAlpha(UNSELECTED_ALPHA);
+        mMoreIcon.setAlpha(mSelectedAlpha);
         mMoreIcon.setVisibility(GONE);
+        mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true);
     }
 
     /**
@@ -145,17 +156,27 @@
     /**
      * Updates the visual state to let the user know if it's been selected.
      * @param selected true if should update the alpha of the icon to selected, false otherwise
-     * @param showMoreIcon true if the "more icon" should be shown, false otherwise
+     * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this
+     *                     is ignored if the attribute useMoreIcon is set to false
      */
     public void setSelected(boolean selected, boolean showMoreIcon) {
         mSelected = selected;
         if (selected) {
-            mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
-            mMoreIcon.setAlpha(SELECTED_ALPHA);
-            mIcon.setAlpha(SELECTED_ALPHA);
+            if (mUseMoreIcon) {
+                mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE);
+            }
+            mIcon.setAlpha(mSelectedAlpha);
         } else {
             mMoreIcon.setVisibility(GONE);
-            mIcon.setAlpha(UNSELECTED_ALPHA);
+            mIcon.setAlpha(mUnselectedAlpha);
+        }
+    }
+
+    public void setIcon(Drawable d) {
+        if (d != null) {
+            mIcon.setImageDrawable(d);
+        } else {
+            mIcon.setImageResource(mIconResourceId);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
index e8c9a5e..2841136 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -5,8 +5,6 @@
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.view.View;
-import android.view.ViewGroup;
 
 import java.util.HashMap;
 import java.util.List;
@@ -29,39 +27,25 @@
     }
 
     /**
-     * Goes through the supplied CarNavigationBarView and keeps track of all the CarFacetButtons
-     * such that it can select and unselect them based on running task chages
-     * @param bar that may contain CarFacetButtons
+     * Add facet button to this controller. The expected use is for the facet button
+     * to get a reference to this controller via {@link com.android.systemui.Dependency}
+     * and self add.
+     * @param facetButton
      */
-    public void addCarNavigationBar(CarNavigationBarView bar) {
-        findFacets(bar);
-    }
+    public void addFacetButton(CarFacetButton facetButton) {
+        String[] categories = facetButton.getCategories();
+        for (int j = 0; j < categories.length; j++) {
+            String category = categories[j];
+            mButtonsByCategory.put(category, facetButton);
+        }
 
-    private void findFacets(ViewGroup root) {
-        final int childCount = root.getChildCount();
-
-        for (int i = 0; i < childCount; ++i) {
-            final View v = root.getChildAt(i);
-            if (v instanceof CarFacetButton) {
-                CarFacetButton facetButton = (CarFacetButton) v;
-                String[] categories = facetButton.getCategories();
-                for (int j = 0; j < categories.length; j++) {
-                    String category = categories[j];
-                    mButtonsByCategory.put(category, facetButton);
-                }
-
-                String[] facetPackages = facetButton.getFacetPackages();
-                for (int j = 0; j < facetPackages.length; j++) {
-                    String facetPackage = facetPackages[j];
-                    mButtonsByPackage.put(facetPackage, facetButton);
-                }
-            } else if (v instanceof ViewGroup) {
-                findFacets((ViewGroup) v);
-            }
+        String[] facetPackages = facetButton.getFacetPackages();
+        for (int j = 0; j < facetPackages.length; j++) {
+            String facetPackage = facetPackages[j];
+            mButtonsByPackage.put(facetPackage, facetButton);
         }
     }
 
-
     /**
      * This will unselect the currently selected CarFacetButton and determine which one should be
      * selected next. It does this by reading the properties on the CarFacetButton and seeing if
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
index 1d9ef61..e73b173 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarNavigationBarView.java
@@ -22,6 +22,7 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import com.android.keyguard.AlphaOptimizedImageButton;
 import com.android.systemui.R;
@@ -36,9 +37,11 @@
     private LinearLayout mNavButtons;
     private AlphaOptimizedImageButton mNotificationsButton;
     private CarStatusBar mCarStatusBar;
+    private Context mContext;
 
     public CarNavigationBarView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mContext = context;
     }
 
     @Override
@@ -46,7 +49,9 @@
         mNavButtons = findViewById(R.id.nav_buttons);
 
         mNotificationsButton = findViewById(R.id.notifications);
-        mNotificationsButton.setOnClickListener(this::onNotificationsClick);
+        if (mNotificationsButton != null) {
+            mNotificationsButton.setOnClickListener(this::onNotificationsClick);
+        }
     }
 
     void setStatusBar(CarStatusBar carStatusBar) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index c15a013..a95d0a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -17,13 +17,9 @@
 package com.android.systemui.statusbar.car;
 
 import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.content.Intent;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.UserHandle;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.View;
@@ -45,8 +41,8 @@
 import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.car.hvac.HvacController;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
-import com.android.systemui.statusbar.phone.NavigationBarView;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -60,6 +56,8 @@
 public class CarStatusBar extends StatusBar implements
         CarBatteryController.BatteryViewHandler {
     private static final String TAG = "CarStatusBar";
+    public static final boolean ENABLE_HVAC_CONNECTION
+            = !SystemProperties.getBoolean("android.car.hvac.demo", true);
 
     private TaskStackListenerImpl mTaskStackListener;
 
@@ -93,6 +91,11 @@
 
         createBatteryController();
         mCarBatteryController.startListening();
+
+        if (ENABLE_HVAC_CONNECTION) {
+            Log.d(TAG, "Connecting to HVAC service");
+            Dependency.get(HvacController.class).connectToCarService();
+        }
     }
 
     @Override
@@ -164,7 +167,7 @@
 
     @Override
     protected void createNavigationBar() {
-        mCarFacetButtonController = new CarFacetButtonController(mContext);
+        mCarFacetButtonController = Dependency.get(CarFacetButtonController.class);
         if (mNavigationBarView != null) {
             return;
         }
@@ -225,7 +228,6 @@
         lp.windowAnimations = 0;
 
 
-        mCarFacetButtonController.addCarNavigationBar(mNavigationBarView);
         mWindowManager.addView(mNavigationBarWindow, lp);
     }
 
@@ -243,7 +245,6 @@
             throw new RuntimeException("Unable to build left nav bar due to missing layout");
         }
         mLeftNavigationBarView.setStatusBar(this);
-        mCarFacetButtonController.addCarNavigationBar(mLeftNavigationBarView);
 
         WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
                 widthForSides, LayoutParams.MATCH_PARENT,
@@ -275,7 +276,6 @@
             throw new RuntimeException("Unable to build right nav bar due to missing layout");
         }
         mRightNavigationBarView.setStatusBar(this);
-        mCarFacetButtonController.addCarNavigationBar(mRightNavigationBarView);
 
         WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
                 widthForSides, LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
new file mode 100644
index 0000000..23bf887
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.car.hvac;
+
+import android.car.Car;
+import android.car.CarNotConnectedException;
+import android.car.hardware.CarPropertyValue;
+import android.car.hardware.hvac.CarHvacManager;
+import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Manages the connection to the Car service and delegates value changes to the registered
+ * {@link TemperatureView}s
+ */
+public class HvacController {
+
+    public static final String TAG = "HvacController";
+    public final static int BIND_TO_HVAC_RETRY_DELAY = 5000;
+
+    private Context mContext;
+    private Handler mHandler;
+    private Car mCar;
+    private CarHvacManager mHvacManager;
+    private HashMap<HvacKey, TemperatureView> mTempComponents = new HashMap<>();
+
+    public HvacController(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * 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.
+     */
+    public void connectToCarService() {
+        mHandler = new Handler();
+        mCar = Car.createCar(mContext, mServiceConnection, mHandler);
+        if (mCar != null) {
+            // note: this connect call handles the retries
+            mCar.connect();
+        }
+    }
+
+    /**
+     * Registers callbacks and initializes components upon connection.
+     */
+    private ServiceConnection mServiceConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            try {
+                service.linkToDeath(mRestart, 0);
+                mHvacManager = (CarHvacManager) mCar.getCarManager(Car.HVAC_SERVICE);
+                mHvacManager.registerCallback(mHardwareCallback);
+                initComponents();
+            } catch (Exception e) {
+                Log.e(TAG, "Failed to correctly connect to HVAC", e);
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            destroyHvacManager();
+        }
+    };
+
+    private void destroyHvacManager() {
+        if (mHvacManager != null) {
+            mHvacManager.unregisterCallback(mHardwareCallback);
+            mHvacManager = null;
+        }
+    }
+
+    /**
+     * If the connection to car service goes away then restart it.
+     */
+    private final IBinder.DeathRecipient mRestart = new IBinder.DeathRecipient() {
+        @Override
+        public void binderDied() {
+            Log.d(TAG, "Death of HVAC triggering a restart");
+            if (mCar != null) {
+                mCar.disconnect();
+            }
+            destroyHvacManager();
+            mHandler.postDelayed(() -> mCar.connect(), BIND_TO_HVAC_RETRY_DELAY);
+        }
+    };
+
+    /**
+     * Add component to list and initialize it if the connection is up.
+     * @param temperatureView
+     */
+    public void addHvacTextView(TemperatureView temperatureView) {
+        mTempComponents.put(
+                new HvacKey(temperatureView.getPropertyId(), temperatureView.getAreaId()),
+                temperatureView);
+        initComponent(temperatureView);
+    }
+
+    private void initComponents() {
+        Iterator<Map.Entry<HvacKey, TemperatureView>> iterator =
+                mTempComponents.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<HvacKey, TemperatureView> next = iterator.next();
+            initComponent(next.getValue());
+        }
+    }
+
+
+    private void initComponent(TemperatureView view) {
+        int id = view.getPropertyId();
+        int zone = view.getAreaId();
+        try {
+            if (mHvacManager == null || !mHvacManager.isPropertyAvailable(id, zone)) {
+                view.setTemp(Float.NaN);
+                return;
+            }
+            view.setTemp(mHvacManager.getFloatProperty(id, zone));
+        } catch (CarNotConnectedException e) {
+            view.setTemp(Float.NaN);
+            Log.e(TAG, "Failed to get value from hvac service", e);
+        }
+    }
+
+    /**
+     * 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();
+                TemperatureView temperatureView = mTempComponents.get(
+                        new HvacKey(propertyId, areaId));
+                if (temperatureView != null) {
+                    float value = (float) val.getValue();
+                    temperatureView.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);
+        }
+    };
+
+    /**
+     * Key for storing {@link TemperatureView}s in a hash map
+     */
+    private static class HvacKey {
+
+        int mPropertyId;
+        int mAreaId;
+
+        public 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);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java
new file mode 100644
index 0000000..4049ec3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/TemperatureView.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.car.hvac;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.systemui.Dependency;
+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)
+ *
+ * Note: It registers itself with {@link HvacController}
+ */
+public class TemperatureView extends TextView {
+
+    private final int mAreaId;
+    private final int mPropertyId;
+    private final String mTempFormat;
+
+    public TemperatureView(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;
+
+        // register with controller
+        HvacController hvacController = Dependency.get(HvacController.class);
+        hvacController.addHvacTextView(this);
+    }
+
+    /**
+     * Formats the float for display
+     * @param temp - The current temp or NaN
+     */
+    public void setTemp(float temp) {
+        if (Float.isNaN(temp)) {
+            setText("--");
+            return;
+        }
+        setText(String.format(mTempFormat, temp));
+    }
+
+    /**
+     * @return propertiyId  Example: CarHvacManager.ID_ZONED_TEMP_SETPOINT (16385)
+     */
+    public int getPropertyId() {
+        return mPropertyId;
+    }
+
+    /**
+     * @return hvac AreaId - Example: VehicleSeat.SEAT_ROW_1_LEFT (1)
+     */
+    public int getAreaId() {
+        return mAreaId;
+    }
+}
+
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 107ce1e..a6b09ce 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -75,7 +75,7 @@
     android.test.runner \
     telephony-common \
     android.test.base \
-
+    android.car
 
 LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard