Merge "DO NOT MERGE Defer Hvac initialization until after BOOT_COMPLETED event." into qt-qpr1-dev
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 261b9f5..c5da135 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -25,4 +25,6 @@
     <uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
     <!-- This permission is required to get bluetooth broadcast. -->
     <uses-permission android:name="android.permission.BLUETOOTH" />
+    <!--  Allows us to defer some actions until after the BOOT_COMPLETED event -->
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
 </manifest>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index db98c36..ec341460 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -28,7 +28,10 @@
 import android.car.drivingstate.CarUxRestrictionsManager;
 import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
 import android.car.media.CarAudioManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -246,12 +249,27 @@
                 }
             };
 
+    private boolean mBootCompleted = false;
+    private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            mBootCompleted = true;
+            String action = intent.getAction();
+            if (action != null && action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+                initHvac();
+            }
+        }
+    };
+
     @Override
     public void start() {
         // Non blocking call to connect to car service. Call this early so that we'll be connected
         // asap.
         ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext);
 
+        // Defer some actions for CarStatusBar initialization until after boot complete event
+        registerBootCompletedReceiver();
+
         // get the provisioned state before calling the parent class since it's that flow that
         // builds the nav bar
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
@@ -396,6 +414,16 @@
         // ignore.
     }
 
+    private void registerBootCompletedReceiver() {
+        IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+        bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+        mContext.registerReceiver(mBootCompletedReceiver, bootCompletedFilter);
+    }
+
+    private void unregisterBootCompletedListener() {
+        mContext.unregisterReceiver(mBootCompletedReceiver);
+    }
+
     /**
      * Remove all content from navbars and rebuild them. Used to allow for different nav bars
      * before and after the device is provisioned. . Also for change of density and font size.
@@ -403,7 +431,9 @@
     private void restartNavBars() {
         // remove and reattach all hvac components such that we don't keep a reference to unused
         // ui elements
-        mHvacController.removeAllComponents();
+        if (mHvacController != null) {
+            mHvacController.removeAllComponents();
+        }
         mCarFacetButtonController.removeAll();
 
         if (mNavigationBarWindow != null) {
@@ -422,6 +452,9 @@
         }
 
         buildNavBarContent();
+        if (mBootCompleted) {
+            initHvac();
+        }
         // If the UI was rebuilt (day/night change) while the keyguard was up we need to
         // correctly respect that state.
         if (mIsKeyguard) {
@@ -433,6 +466,8 @@
     }
 
     private void addTemperatureViewToController(View v) {
+        if (v == null) return;
+
         if (v instanceof TemperatureView) {
             mHvacController.addHvacTextView((TemperatureView) v);
         } else if (v instanceof ViewGroup) {
@@ -442,7 +477,6 @@
             }
         }
     }
-
     /**
      * Allows for showing or hiding just the navigation bars. This is indented to be used when
      * the full screen user selector is shown.
@@ -1034,7 +1068,6 @@
             throw new RuntimeException("Unable to build top nav bar due to missing layout");
         }
         mTopNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mTopNavigationBarView);
         mTopNavigationBarView.setStatusBarWindowTouchListener(mTopNavBarNotificationTouchListener);
     }
 
@@ -1049,7 +1082,6 @@
             throw new RuntimeException("Unable to build bottom nav bar due to missing layout");
         }
         mNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mNavigationBarView);
         mNavigationBarView.setStatusBarWindowTouchListener(mNavBarNotificationTouchListener);
     }
 
@@ -1061,7 +1093,6 @@
             throw new RuntimeException("Unable to build left nav bar due to missing layout");
         }
         mLeftNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mLeftNavigationBarView);
         mLeftNavigationBarView.setStatusBarWindowTouchListener(mNavBarNotificationTouchListener);
     }
 
@@ -1074,10 +1105,20 @@
             throw new RuntimeException("Unable to build right nav bar due to missing layout");
         }
         mRightNavigationBarView.setStatusBar(this);
-        addTemperatureViewToController(mRightNavigationBarView);
         mRightNavigationBarView.setStatusBarWindowTouchListener(mNavBarNotificationTouchListener);
     }
 
+    private void initHvac() {
+        if (mHvacController == null) {
+            mHvacController = Dependency.get(HvacController.class);
+            mHvacController.connectToCarService();
+        }
+        addTemperatureViewToController(mTopNavigationBarView);
+        addTemperatureViewToController(mNavigationBarView);
+        addTemperatureViewToController(mLeftNavigationBarView);
+        addTemperatureViewToController(mRightNavigationBarView);
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         //When executing dump() function simultaneously, we need to serialize them