Merge "DO NOT MERGE - Added user flags to 'dumpsys user'" into qt-qpr1-dev
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index 591c418..36f3a1e 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -441,6 +441,43 @@
     }
 
     /**
+     * Checks whether a value set presented by a bitmask has zero or single bit
+     *
+     * @param valueSet the value set presented by a bitmask
+     * @return true if the valueSet contains zero or single bit, otherwise false.
+     */
+    private static boolean hasSingleBit(int valueSet) {
+        return (valueSet == 0 || (valueSet & (valueSet - 1)) == 0);
+    }
+
+    /**
+     * Checks whether the object contains none or single sample rate.
+     *
+     * @return true if the object contains none or single sample rate, otherwise false.
+     */
+    public boolean hasSingleSampleRate() {
+        return hasSingleBit(mSampleRate);
+    }
+
+    /**
+     * Checks whether the object contains none or single bits per sample.
+     *
+     * @return true if the object contains none or single bits per sample, otherwise false.
+     */
+    public boolean hasSingleBitsPerSample() {
+        return hasSingleBit(mBitsPerSample);
+    }
+
+    /**
+     * Checks whether the object contains none or single channel mode.
+     *
+     * @return true if the object contains none or single channel mode, otherwise false.
+     */
+    public boolean hasSingleChannelMode() {
+        return hasSingleBit(mChannelMode);
+    }
+
+    /**
      * Checks whether the audio feeding parameters are same.
      *
      * @param other the codec config to compare against
@@ -451,4 +488,58 @@
                 && other.mBitsPerSample == mBitsPerSample
                 && other.mChannelMode == mChannelMode);
     }
+
+    /**
+     * Checks whether another codec config has the similar feeding parameters.
+     * Any parameters with NONE value will be considered to be a wildcard matching.
+     *
+     * @param other the codec config to compare against
+     * @return true if the audio feeding parameters are similar, otherwise false.
+     */
+    public boolean similarCodecFeedingParameters(BluetoothCodecConfig other) {
+        if (other == null || mCodecType != other.mCodecType) {
+            return false;
+        }
+        int sampleRate = other.mSampleRate;
+        if (mSampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE
+                || sampleRate == BluetoothCodecConfig.SAMPLE_RATE_NONE) {
+            sampleRate = mSampleRate;
+        }
+        int bitsPerSample = other.mBitsPerSample;
+        if (mBitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE
+                || bitsPerSample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
+            bitsPerSample = mBitsPerSample;
+        }
+        int channelMode = other.mChannelMode;
+        if (mChannelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE
+                || channelMode == BluetoothCodecConfig.CHANNEL_MODE_NONE) {
+            channelMode = mChannelMode;
+        }
+        return sameAudioFeedingParameters(new BluetoothCodecConfig(
+                mCodecType, /* priority */ 0, sampleRate, bitsPerSample, channelMode,
+                /* specific1 */ 0, /* specific2 */ 0, /* specific3 */ 0,
+                /* specific4 */ 0));
+    }
+
+    /**
+     * Checks whether the codec specific parameters are the same.
+     *
+     * @param other the codec config to compare against
+     * @return true if the codec specific parameters are the same, otherwise false.
+     */
+    public boolean sameCodecSpecificParameters(BluetoothCodecConfig other) {
+        if (other == null && mCodecType != other.mCodecType) {
+            return false;
+        }
+        // Currently we only care about the LDAC Playback Quality at CodecSpecific1
+        switch (mCodecType) {
+            case SOURCE_CODEC_TYPE_LDAC:
+                if (mCodecSpecific1 != other.mCodecSpecific1) {
+                    return false;
+                }
+                // fall through
+            default:
+                return true;
+        }
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 58b6aea..58a764a 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -89,6 +89,43 @@
         return Arrays.asList(c1).containsAll(Arrays.asList(c2));
     }
 
+    /**
+     * Checks whether the codec config matches the selectable capabilities.
+     * Any parameters of the codec config with NONE value will be considered a wildcard matching.
+     *
+     * @param codecConfig the codec config to compare against
+     * @return true if the codec config matches, otherwise false
+     */
+    public boolean isCodecConfigSelectable(BluetoothCodecConfig codecConfig) {
+        if (codecConfig == null || !codecConfig.hasSingleSampleRate()
+                || !codecConfig.hasSingleBitsPerSample() || !codecConfig.hasSingleChannelMode()) {
+            return false;
+        }
+        for (BluetoothCodecConfig selectableConfig : mCodecsSelectableCapabilities) {
+            if (codecConfig.getCodecType() != selectableConfig.getCodecType()) {
+                continue;
+            }
+            int sampleRate = codecConfig.getSampleRate();
+            if ((sampleRate & selectableConfig.getSampleRate()) == 0
+                    && sampleRate != BluetoothCodecConfig.SAMPLE_RATE_NONE) {
+                continue;
+            }
+            int bitsPerSample = codecConfig.getBitsPerSample();
+            if ((bitsPerSample & selectableConfig.getBitsPerSample()) == 0
+                    && bitsPerSample != BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
+                continue;
+            }
+            int channelMode = codecConfig.getChannelMode();
+            if ((channelMode & selectableConfig.getChannelMode()) == 0
+                    && channelMode != BluetoothCodecConfig.CHANNEL_MODE_NONE) {
+                continue;
+            }
+            return true;
+        }
+        return false;
+    }
+
+
     @Override
     public int hashCode() {
         return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index c40c123..451a669 100755
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -23,9 +23,8 @@
 /**
  * A structure describing general information about a display, such as its
  * size, density, and font scaling.
- * <p>To access the DisplayMetrics members, initialize an object like this:</p>
- * <pre> DisplayMetrics metrics = new DisplayMetrics();
- * getWindowManager().getDefaultDisplay().getMetrics(metrics);</pre>
+ * <p>To access the DisplayMetrics members, retrieve display metrics like this:</p>
+ * <pre>context.getResources().getDisplayMetrics();</pre>
  */
 public class DisplayMetrics {
     /**
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 685e8de..ef68ce7 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1266,12 +1266,12 @@
      * current value is set to the {@link NumberPicker#getMaxValue()} value.
      * </p>
      * <p>
-     * If the argument is less than the {@link NumberPicker#getMaxValue()} and
+     * If the argument is more than the {@link NumberPicker#getMaxValue()} and
      * {@link NumberPicker#getWrapSelectorWheel()} is <code>false</code> the
      * current value is set to the {@link NumberPicker#getMaxValue()} value.
      * </p>
      * <p>
-     * If the argument is less than the {@link NumberPicker#getMaxValue()} and
+     * If the argument is more than the {@link NumberPicker#getMaxValue()} and
      * {@link NumberPicker#getWrapSelectorWheel()} is <code>true</code> the
      * current value is set to the {@link NumberPicker#getMinValue()} value.
      * </p>
diff --git a/core/res/res/values-mcc310-mnc170/config.xml b/core/res/res/values-mcc310-mnc170/config.xml
index 26b9192..12e448c 100644
--- a/core/res/res/values-mcc310-mnc170/config.xml
+++ b/core/res/res/values-mcc310-mnc170/config.xml
@@ -22,5 +22,9 @@
 <resources>
     <!-- Enable 5 bar signal strength icon -->
     <bool name="config_inflateSignalStrength">true</bool>
+
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">true</bool>
 </resources>
 
diff --git a/core/res/res/values-mcc310-mnc380/config.xml b/core/res/res/values-mcc310-mnc380/config.xml
index 26b9192..12e448c 100644
--- a/core/res/res/values-mcc310-mnc380/config.xml
+++ b/core/res/res/values-mcc310-mnc380/config.xml
@@ -22,5 +22,9 @@
 <resources>
     <!-- Enable 5 bar signal strength icon -->
     <bool name="config_inflateSignalStrength">true</bool>
+
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">true</bool>
 </resources>
 
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 3fb3f0f..22b8fef 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -52,4 +52,7 @@
     <!-- Enable 5 bar signal strength icon -->
     <bool name="config_inflateSignalStrength">true</bool>
 
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc560/config.xml b/core/res/res/values-mcc310-mnc560/config.xml
index 26b9192..12e448c 100644
--- a/core/res/res/values-mcc310-mnc560/config.xml
+++ b/core/res/res/values-mcc310-mnc560/config.xml
@@ -22,5 +22,9 @@
 <resources>
     <!-- Enable 5 bar signal strength icon -->
     <bool name="config_inflateSignalStrength">true</bool>
+
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">true</bool>
 </resources>
 
diff --git a/core/res/res/values-mcc311-mnc180/config.xml b/core/res/res/values-mcc311-mnc180/config.xml
index 26b9192..12e448c 100644
--- a/core/res/res/values-mcc311-mnc180/config.xml
+++ b/core/res/res/values-mcc311-mnc180/config.xml
@@ -22,5 +22,9 @@
 <resources>
     <!-- Enable 5 bar signal strength icon -->
     <bool name="config_inflateSignalStrength">true</bool>
+
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">true</bool>
 </resources>
 
diff --git a/core/res/res/values-mcc313-mnc100/config.xml b/core/res/res/values-mcc313-mnc100/config.xml
index ccd03f1..a8e481a 100644
--- a/core/res/res/values-mcc313-mnc100/config.xml
+++ b/core/res/res/values-mcc313-mnc100/config.xml
@@ -42,4 +42,8 @@
         <item>"#8"</item>
         <item>"#9"</item>
     </string-array>
+
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">true</bool>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bfcc8d4..f4b120a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4260,4 +4260,8 @@
          create additional screen real estate outside beyond the keyboard. Note that the user needs
          to have a confirmed way to dismiss the keyboard when desired. -->
     <bool name="config_automotiveHideNavBarForKeyboard">false</bool>
+
+    <!-- Boolean indicating whether frameworks needs to reset cell broadcast geo-fencing
+         check after reboot or airplane mode toggling -->
+    <bool translatable="false" name="reset_geo_fencing_check_after_boot_or_apm">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a6075dc..8e52301 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3840,4 +3840,5 @@
   <java-symbol type="layout" name="platlogo_layout" />
 
   <java-symbol type="bool" name="config_automotiveHideNavBarForKeyboard" />
+  <java-symbol type="bool" name="reset_geo_fencing_check_after_boot_or_apm" />
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
index c7654e8..a423554 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIFactory.java
@@ -20,6 +20,7 @@
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.car.CarServiceProvider;
 import com.android.systemui.statusbar.car.CarFacetButtonController;
 import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -36,6 +37,7 @@
 public class CarSystemUIFactory extends SystemUIFactory {
 
     private CarDependencyComponent mCarDependencyComponent;
+    private CarServiceProvider mCarServiceProvider;
 
     @Override
     protected SystemUIRootComponent buildSystemUIRootComponent(Context context) {
@@ -48,6 +50,14 @@
                 .build();
     }
 
+    /** Gets a {@link CarServiceProvider}. */
+    public CarServiceProvider getCarServiceProvider(Context context) {
+        if (mCarServiceProvider == null) {
+            mCarServiceProvider = new CarServiceProvider(context);
+        }
+        return mCarServiceProvider;
+    }
+
     public CarDependencyComponent getCarDependencyComponent() {
         return mCarDependencyComponent;
     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java b/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java
new file mode 100644
index 0000000..9ee368e
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarServiceProvider.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 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;
+
+import android.car.Car;
+import android.car.Car.CarServiceLifecycleListener;
+import android.content.Context;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Connects to the car service a single time for shared use across all of system ui.
+ */
+public class CarServiceProvider {
+
+    private final Context mContext;
+    private final List<CarServiceLifecycleListener> mListeners = new ArrayList<>();
+    private Car mCar;
+
+    public CarServiceProvider(Context context) {
+        mContext = context;
+        mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+                (car, ready) -> {
+                    mCar = car;
+
+                    synchronized (mListeners) {
+                        for (CarServiceLifecycleListener listener : mListeners) {
+                            listener.onLifecycleChanged(mCar, ready);
+                        }
+                    }
+                });
+    }
+
+    /**
+     * Let's other components hook into the connection to the car service. If we're already
+     * connected
+     * to the car service, the callback is immediately triggered.
+     */
+    public void addListener(CarServiceLifecycleListener listener) {
+        if (mCar.isConnected()) {
+            listener.onLifecycleChanged(mCar, /* ready= */ true);
+        }
+        mListeners.add(listener);
+    }
+}
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 1a1a8ea..4e98da6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -199,6 +199,10 @@
 
     @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);
+
         // get the provisioned state before calling the parent class since it's that flow that
         // builds the nav bar
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
@@ -482,11 +486,8 @@
 
         CarNotificationListener carNotificationListener = new CarNotificationListener();
         mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper();
-        // This can take time if car service is not ready up to this time.
-        // TODO(b/142808072) Refactor CarUxRestrictionManagerWrapper to allow setting
-        // CarUxRestrictionsManager later and switch to Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT.
-        Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER,
-                (car, ready) -> {
+        ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext)
+                .addListener((car, ready) -> {
                     if (!ready) {
                         return;
                     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
index cd87e78..76ad04f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
@@ -26,6 +26,9 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.systemui.CarSystemUIFactory;
+import com.android.systemui.SystemUIFactory;
+
 /**
  * Helper class for connecting to the {@link CarDrivingStateManager} and listening for driving state
  * changes.
@@ -35,7 +38,6 @@
 
     private final Context mContext;
     private CarDrivingStateManager mDrivingStateManager;
-    private Car mCar;
     private CarDrivingStateEventListener mDrivingStateHandler;
 
     public DrivingStateHelper(Context context,
@@ -64,8 +66,8 @@
      * Establishes connection with the Car service.
      */
     public void connectToCarService() {
-        mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
-                mCarServiceLifecycleListener);
+        ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext)
+                .addListener(mCarServiceLifecycleListener);
     }
 
     private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 31aced0..0ebfa84 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -34,7 +34,9 @@
 
 import androidx.recyclerview.widget.GridLayoutManager;
 
+import com.android.systemui.CarSystemUIFactory;
 import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
 import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
 
@@ -65,7 +67,6 @@
             mContext.unregisterReceiver(mUserUnlockReceiver);
         }
     };
-    private final Car mCar;
 
     public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) {
         mStatusBar = statusBar;
@@ -85,8 +86,8 @@
         mUnlockDialogHelper = new CarTrustAgentUnlockDialogHelper(mContext);
         mUserManager = mContext.getSystemService(UserManager.class);
 
-        mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
-                (car, ready) -> {
+        ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext)
+                .addListener((car, ready) -> {
                     if (!ready) {
                         return;
                     }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
index a27dd34..d87b54c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
@@ -24,6 +24,9 @@
 import android.content.Context;
 import android.util.Log;
 
+import com.android.systemui.CarSystemUIFactory;
+import com.android.systemui.SystemUIFactory;
+
 /**
  * Helper class for connecting to the {@link CarPowerManager} and listening for power state changes.
  */
@@ -33,7 +36,6 @@
     private final Context mContext;
     private final CarPowerStateListener mCarPowerStateListener;
 
-    private Car mCar;
     private CarPowerManager mCarPowerManager;
 
     private final CarServiceLifecycleListener mCarServiceLifecycleListener;
@@ -59,7 +61,7 @@
      * Connect to Car service.
      */
     void connectToCarService() {
-        mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
-                mCarServiceLifecycleListener);
+        ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext)
+                .addListener(mCarServiceLifecycleListener);
     }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index a8515f9..1d96750 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -26,9 +26,11 @@
 import android.car.hardware.hvac.CarHvacManager;
 import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
 import android.content.Context;
-import android.os.Handler;
 import android.util.Log;
 
+import com.android.systemui.CarSystemUIFactory;
+import com.android.systemui.SystemUIFactory;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -41,13 +43,9 @@
  * {@link TemperatureView}s
  */
 public class HvacController {
-
     public static final String TAG = "HvacController";
-    public static final int BIND_TO_HVAC_RETRY_DELAY = 5000;
 
     private Context mContext;
-    private Handler mHandler;
-    private Car mCar;
     private CarHvacManager mHvacManager;
     private HashMap<HvacKey, List<TemperatureView>> mTempComponents = new HashMap<>();
 
@@ -105,9 +103,8 @@
      * ({@link CarHvacManager}) will happen on the same thread this method was called from.
      */
     public void connectToCarService() {
-        mHandler = new Handler();
-        mCar = Car.createCar(mContext, /* handler= */ mHandler, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
-                mCarServiceLifecycleListener);
+        ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext)
+            .addListener(mCarServiceLifecycleListener);
     }
 
     /**
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 09223e8..0dad8e5 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -55,7 +55,9 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import com.android.systemui.CarSystemUIFactory;
 import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.plugins.VolumeDialog;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -95,7 +97,6 @@
     private CustomDialog mDialog;
     private RecyclerView mListView;
     private CarVolumeItemAdapter mVolumeItemsAdapter;
-    private Car mCar;
     private CarAudioManager mCarAudioManager;
     private boolean mHovering;
     private int mCurrentlyDisplayingGroupId;
@@ -196,8 +197,8 @@
     @Override
     public void init(int windowType, Callback callback) {
         initDialog();
-        mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
-                mCarServiceLifecycleListener);
+        ((CarSystemUIFactory) SystemUIFactory.getInstance()).getCarServiceProvider(mContext)
+                .addListener(mCarServiceLifecycleListener);
     }
 
     @Override
@@ -205,12 +206,6 @@
         mHandler.removeCallbacksAndMessages(/* token= */ null);
 
         cleanupAudioManager();
-        // unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup
-        // audio manager beforehand.
-        if (mCar != null) {
-            mCar.disconnect();
-            mCar = null;
-        }
     }
 
     private void initDialog() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
index 5c9a06f9..69f1c17 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
@@ -18,6 +18,7 @@
 import android.os.Handler;
 import android.os.Looper;
 
+import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
@@ -26,7 +27,7 @@
 
     private static volatile Thread sMainThread;
     private static volatile Handler sMainThreadHandler;
-    private static volatile ExecutorService sSingleThreadExecutor;
+    private static volatile ExecutorService sThreadExecutor;
 
     /**
      * Returns true if the current thread is the UI thread.
@@ -64,10 +65,16 @@
      * @Return A future of the task that can be monitored for updates or cancelled.
      */
     public static Future postOnBackgroundThread(Runnable runnable) {
-        if (sSingleThreadExecutor == null) {
-            sSingleThreadExecutor = Executors.newSingleThreadExecutor();
-        }
-        return sSingleThreadExecutor.submit(runnable);
+        return getThreadExecutor().submit(runnable);
+    }
+
+    /**
+     * Posts callable in background using shared background thread pool.
+     *
+     * @Return A future of the task that can be monitored for updates or cancelled.
+     */
+    public static Future postOnBackgroundThread(Callable callable) {
+        return getThreadExecutor().submit(callable);
     }
 
     /**
@@ -77,4 +84,11 @@
         getUiThreadHandler().post(runnable);
     }
 
+    private static synchronized ExecutorService getThreadExecutor() {
+        if (sThreadExecutor == null) {
+            sThreadExecutor = Executors.newFixedThreadPool(
+                    Runtime.getRuntime().availableProcessors());
+        }
+        return sThreadExecutor;
+    }
 }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
index 26db124..5114b00 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/utils/ThreadUtilsTest.java
@@ -50,7 +50,7 @@
     }
 
     @Test
-    public void testPostOnMainThread_shouldRunOnMainTread() {
+    public void testPostOnMainThread_shouldRunOnMainThread() {
         TestRunnable cr = new TestRunnable();
         ShadowLooper.pauseMainLooper();
         ThreadUtils.postOnMainThread(cr);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 48127a7..8d4a2cd 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -142,7 +142,7 @@
 
     public void startServicesIfNeeded() {
         String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
-        startServicesIfNeeded(names);
+        startServicesIfNeeded(/* metricsPrefix= */ "StartServices", names);
     }
 
     /**
@@ -154,10 +154,10 @@
     void startSecondaryUserServicesIfNeeded() {
         String[] names =
                   getResources().getStringArray(R.array.config_systemUIServiceComponentsPerUser);
-        startServicesIfNeeded(names);
+        startServicesIfNeeded(/* metricsPrefix= */ "StartSecondaryServices", names);
     }
 
-    private void startServicesIfNeeded(String[] services) {
+    private void startServicesIfNeeded(String metricsPrefix, String[] services) {
         if (mServicesStarted) {
             return;
         }
@@ -178,12 +178,12 @@
                 Process.myUserHandle().getIdentifier() + ".");
         TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
                 Trace.TRACE_TAG_APP);
-        log.traceBegin("StartServices");
+        log.traceBegin(metricsPrefix);
         final int N = services.length;
         for (int i = 0; i < N; i++) {
             String clsName = services[i];
             if (DEBUG) Log.d(TAG, "loading: " + clsName);
-            log.traceBegin("StartServices" + clsName);
+            log.traceBegin(metricsPrefix + clsName);
             long ti = System.currentTimeMillis();
             Class cls;
             try {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 54192a9..e8505fc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5262,7 +5262,7 @@
             storageManager.commitChanges();
         } catch (Exception e) {
             PowerManager pm = (PowerManager)
-                     mInjector.getContext().getSystemService(Context.POWER_SERVICE);
+                     mContext.getSystemService(Context.POWER_SERVICE);
             pm.reboot("Checkpoint commit failed");
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 6f9a918..b661a85 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -2186,8 +2186,10 @@
         final boolean success = (returnCode == PackageManager.INSTALL_SUCCEEDED);
 
         // Send broadcast to default launcher only if it's a new install
+        // TODO(b/144270665): Secure the usage of this broadcast.
         final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
-        if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()) {
+        if (success && isNewInstall && mPm.mInstallerService.okToSendBroadcasts()
+                && (params.installFlags & PackageManager.INSTALL_DRY_RUN) == 0) {
             mPm.sendSessionCommitBroadcast(generateInfo(), userId);
         }
 
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java
index fd26817b..e9fb37e 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkInfo.java
@@ -120,10 +120,12 @@
             new Creator<WifiAwareNetworkInfo>() {
                 @Override
                 public WifiAwareNetworkInfo createFromParcel(Parcel in) {
+                    byte[] addr = in.createByteArray();
+                    String interfaceName = in.readString();
+                    int port = in.readInt();
+                    int transportProtocol = in.readInt();
                     Inet6Address ipv6Addr;
                     try {
-                        byte[] addr = in.createByteArray();
-                        String interfaceName = in.readString();
                         NetworkInterface ni = null;
                         if (interfaceName != null) {
                             try {
@@ -137,9 +139,6 @@
                         e.printStackTrace();
                         return null;
                     }
-                    int port = in.readInt();
-                    int transportProtocol = in.readInt();
-
                     return new WifiAwareNetworkInfo(ipv6Addr, port, transportProtocol);
                 }