Merge "Add a DeviceConfig.Properties.Builder class."
diff --git a/apex/statsd/aidl/android/os/IStatsManager.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
similarity index 99%
rename from apex/statsd/aidl/android/os/IStatsManager.aidl
rename to apex/statsd/aidl/android/os/IStatsd.aidl
index cc62f07..cffc6ce 100644
--- a/apex/statsd/aidl/android/os/IStatsManager.aidl
+++ b/apex/statsd/aidl/android/os/IStatsd.aidl
@@ -24,7 +24,7 @@
   * Binder interface to communicate with the statistics management service.
   * {@hide}
   */
-interface IStatsManager {
+interface IStatsd {
     /**
      * Tell the stats daemon that the android system server is up and running.
      */
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 6fb3bc4..bc7716e 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -79,7 +79,7 @@
 import android.os.IBinder;
 import android.os.IPullAtomCallback;
 import android.os.IStatsCompanionService;
-import android.os.IStatsManager;
+import android.os.IStatsd;
 import android.os.IStoraged;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
@@ -268,7 +268,7 @@
     private final AlarmManager mAlarmManager;
     private final INetworkStatsService mNetworkStatsService;
     @GuardedBy("sStatsdLock")
-    private static IStatsManager sStatsd;
+    private static IStatsd sStatsd;
     private static final Object sStatsdLock = new Object();
 
     private final OnAlarmListener mAnomalyAlarmListener = new AnomalyAlarmListener();
@@ -2743,8 +2743,8 @@
      * Note: This should only be called from sayHiToStatsd. All other clients should use the cached
      * sStatsd with a null check.
      */
-    private static IStatsManager fetchStatsdService() {
-        return IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
+    private static IStatsd fetchStatsdService() {
+        return IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
     }
 
     public static final class Lifecycle extends SystemService {
diff --git a/api/current.txt b/api/current.txt
index 824aac5..d22e599 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -45602,6 +45602,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
     method public int getActiveModemCount();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+    method @NonNull public static int[] getAllNetworkTypes();
     method public int getCallState();
     method public int getCardIdForDefaultEuicc();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
diff --git a/api/system-current.txt b/api/system-current.txt
index 5279857..4684690 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1423,15 +1423,24 @@
 
   public final class BluetoothDevice implements android.os.Parcelable {
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean cancelBondProcess();
+    method public boolean cancelPairing();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getBatteryLevel();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getMessageAccessPermission();
     method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public byte[] getMetadata(int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getPhonebookAccessPermission();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getSimAccessPermission();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isBondingInitiatedLocally();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isConnected();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean isEncrypted();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInSilenceMode();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean removeBond();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean setAlias(@NonNull String);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMessageAccessPermission(int);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setMetadata(int, @NonNull byte[]);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPhonebookAccessPermission(int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPin(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSilenceMode(boolean);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setSimAccessPermission(int);
     field public static final int ACCESS_ALLOWED = 1; // 0x1
     field public static final int ACCESS_REJECTED = 2; // 0x2
     field public static final int ACCESS_UNKNOWN = 0; // 0x0
@@ -3410,6 +3419,14 @@
     field public static final int STATUS_OK = 0; // 0x0
   }
 
+  public static final class SoundTrigger.ModelParamRange implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModelParamRange> CREATOR;
+    field public final int end;
+    field public final int start;
+  }
+
   public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -4199,8 +4216,11 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerDetector createSoundTriggerDetector(java.util.UUID, @NonNull android.media.soundtrigger.SoundTriggerDetector.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID);
     method public int getDetectionServiceOperationsTimeout();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int getParameter(@NonNull java.util.UUID, int) throws java.lang.IllegalArgumentException, java.lang.UnsupportedOperationException;
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModelParamRange queryParameter(@Nullable java.util.UUID, int);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public int setParameter(@Nullable java.util.UUID, int, int) throws java.lang.IllegalArgumentException, java.lang.UnsupportedOperationException;
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
   }
 
@@ -9574,6 +9594,7 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 3c5ad42..4d38ba0 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -272,7 +272,7 @@
             }
             return NO_ERROR;
         }
-        default: { return BnStatsManager::onTransact(code, data, reply, flags); }
+        default: { return BnStatsd::onTransact(code, data, reply, flags); }
     }
 }
 
@@ -862,13 +862,13 @@
     int64_t trainVersion = strtoll(args[2].c_str(), nullptr, 10);
     int options = 0;
     if (args[3] == "1") {
-        options = options | IStatsManager::FLAG_REQUIRE_STAGING;
+        options = options | IStatsd::FLAG_REQUIRE_STAGING;
     }
     if (args[4] == "1") {
-        options = options | IStatsManager::FLAG_ROLLBACK_ENABLED;
+        options = options | IStatsd::FLAG_ROLLBACK_ENABLED;
     }
     if (args[5] == "1") {
-        options = options | IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
+        options = options | IStatsd::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
     }
     int32_t state = atoi(args[6].c_str());
     vector<int64_t> experimentIds;
@@ -1406,9 +1406,9 @@
     StorageManager::writeTrainInfo(trainVersionCode, trainNameUtf8, state, experimentIds);
 
     userid_t userId = multiuser_get_user_id(uid);
-    bool requiresStaging = options & IStatsManager::FLAG_REQUIRE_STAGING;
-    bool rollbackEnabled = options & IStatsManager::FLAG_ROLLBACK_ENABLED;
-    bool requiresLowLatencyMonitor = options & IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
+    bool requiresStaging = options & IStatsd::FLAG_REQUIRE_STAGING;
+    bool rollbackEnabled = options & IStatsd::FLAG_ROLLBACK_ENABLED;
+    bool requiresLowLatencyMonitor = options & IStatsd::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
     LogEvent event(trainNameUtf8, trainVersionCode, requiresStaging, rollbackEnabled,
                    requiresLowLatencyMonitor, state, experimentIdsProtoBuffer, userId);
     mProcessor->OnLogEvent(&event);
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 50b1014..9abf415 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -29,9 +29,9 @@
 
 #include <android/frameworks/stats/1.0/IStats.h>
 #include <android/frameworks/stats/1.0/types.h>
-#include <android/os/BnStatsManager.h>
+#include <android/os/BnStatsd.h>
 #include <android/os/IStatsCompanionService.h>
-#include <android/os/IStatsManager.h>
+#include <android/os/IStatsd.h>
 #include <binder/IResultReceiver.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <utils/Looper.h>
@@ -52,7 +52,7 @@
 
 using android::hardware::Return;
 
-class StatsService : public BnStatsManager,
+class StatsService : public BnStatsd,
                      public IStats,
                      public IBinder::DeathRecipient {
 public:
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index 90cd51f..f6e9569 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -27,8 +27,8 @@
 import android.os.IPullAtomCallback;
 import android.os.IPullAtomResultReceiver;
 import android.os.IStatsCompanionService;
-import android.os.IStatsManager;
 import android.os.IStatsPullerCallback;
+import android.os.IStatsd;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.util.AndroidException;
@@ -56,7 +56,7 @@
     private final Context mContext;
 
     @GuardedBy("sLock")
-    private IStatsManager mService;
+    private IStatsd mService;
 
     @GuardedBy("sLock")
     private IStatsCompanionService mStatsCompanion;
@@ -129,7 +129,7 @@
     public void addConfig(long configKey, byte[] config) throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 // can throw IllegalArgumentException
                 service.addConfiguration(configKey, config, mContext.getOpPackageName());
             } catch (RemoteException e) {
@@ -166,7 +166,7 @@
     public void removeConfig(long configKey) throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 service.removeConfiguration(configKey, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when removing configuration");
@@ -227,7 +227,7 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (pendingIntent != null) {
                     // Extracts IIntentSender from the PendingIntent and turns it into an IBinder.
                     IBinder intentSender = pendingIntent.getTarget().asBinder();
@@ -281,7 +281,7 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (pendingIntent == null) {
                     service.removeDataFetchOperation(configKey, mContext.getOpPackageName());
                 } else {
@@ -319,7 +319,7 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (pendingIntent == null) {
                     service.removeActiveConfigsChangedOperation(mContext.getOpPackageName());
                     return new long[0];
@@ -367,7 +367,7 @@
     public byte[] getReports(long configKey) throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 return service.getData(configKey, mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when getting data");
@@ -404,7 +404,7 @@
     public byte[] getStatsMetadata() throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 return service.getMetadata(mContext.getOpPackageName());
             } catch (RemoteException e) {
                 Slog.e(TAG, "Failed to connect to statsd when getting metadata");
@@ -439,7 +439,7 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (service == null) {
                     if (DEBUG) {
                         Slog.d(TAG, "Failed to find statsd when getting experiment IDs");
@@ -476,7 +476,7 @@
             throws StatsUnavailableException {
         synchronized (sLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (callback == null) {
                     service.unregisterPullerCallback(atomTag, mContext.getOpPackageName());
                 } else {
@@ -660,11 +660,11 @@
     }
 
     @GuardedBy("sLock")
-    private IStatsManager getIStatsManagerLocked() throws StatsUnavailableException {
+    private IStatsd getIStatsdLocked() throws StatsUnavailableException {
         if (mService != null) {
             return mService;
         }
-        mService = IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
+        mService = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
         if (mService == null) {
             throw new StatsUnavailableException("could not be found");
         }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 49187dc..323c7d1 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -33,8 +34,12 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.UUID;
 
 /**
@@ -771,6 +776,13 @@
     @UnsupportedAppUsage
     public static final String EXTRA_SDP_SEARCH_STATUS =
             "android.bluetooth.device.extra.SDP_SEARCH_STATUS";
+
+    /** @hide */
+    @IntDef(prefix = "ACCESS_", value = {ACCESS_UNKNOWN,
+            ACCESS_ALLOWED, ACCESS_REJECTED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AccessPermission{}
+
     /**
      * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
      * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
@@ -1096,15 +1108,14 @@
 
     /**
      * Get the most recent identified battery level of this Bluetooth device
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
      *
      * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if
      * Bluetooth is disabled, or device is disconnected, or does not have any battery reporting
      * service, or return value is invalid
      * @hide
      */
+    @SystemApi
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    @UnsupportedAppUsage
     public int getBatteryLevel() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1187,8 +1198,15 @@
         return false;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
+    /**
+     * Gets whether bonding was initiated locally
+     *
+     * @return true if bonding is initiated locally, false otherwise
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public boolean isBondingInitiatedLocally() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1480,15 +1498,20 @@
         return false;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
-    public boolean setPasskey(int passkey) {
-        //TODO(BT)
-        /*
-        try {
-            return sService.setPasskey(this, true, 4, passkey);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
-        return false;
+    /**
+     * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
+     *
+     * @return true pin has been set false for error
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setPin(@Nullable String pin) {
+        byte[] pinBytes = convertPinToBytes(pin);
+        if (pinBytes == null) {
+            return false;
+        }
+        return setPin(pinBytes);
     }
 
     /**
@@ -1511,22 +1534,18 @@
         return false;
     }
 
-    /** @hide */
-    public boolean setRemoteOutOfBandData() {
-        // TODO(BT)
-        /*
-        try {
-          return sService.setRemoteOutOfBandData(this);
-      } catch (RemoteException e) {Log.e(TAG, "", e);}*/
-        return false;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    public boolean cancelPairingUserInput() {
+    /**
+     * Cancels pairing to this device
+     *
+     * @return true if pairing cancelled successfully, false otherwise
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean cancelPairing() {
         final IBluetooth service = sService;
         if (service == null) {
-            Log.e(TAG, "BT not enabled. Cannot create pairing user input");
+            Log.e(TAG, "BT not enabled. Cannot cancel pairing");
             return false;
         }
         try {
@@ -1537,17 +1556,6 @@
         return false;
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
-    public boolean isBluetoothDock() {
-        // TODO(BT)
-        /*
-        try {
-            return sService.isBluetoothDock(this);
-        } catch (RemoteException e) {Log.e(TAG, "", e);}*/
-        return false;
-    }
-
     boolean isBluetoothEnabled() {
         boolean ret = false;
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -1558,13 +1566,14 @@
     }
 
     /**
-     * Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * Gets whether the phonebook access is allowed for this bluetooth device
      *
      * @return Whether the phonebook access is allowed to this device. Can be {@link
      * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPhonebookAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1667,14 +1676,14 @@
     }
 
     /**
-     * Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * Gets whether message access is allowed to this bluetooth device
      *
-     * @return Whether the message access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
-     * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
+     * @return Whether the message access is allowed to this device.
      * @hide
      */
-    @UnsupportedAppUsage
-    public int getMessageAccessPermission() {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @AccessPermission int getMessageAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
             return ACCESS_UNKNOWN;
@@ -1689,15 +1698,18 @@
 
     /**
      * Sets whether the message access is allowed to this device.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
      *
-     * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
-     * #ACCESS_REJECTED}.
+     * @param value is the value we are setting the message access permission to
      * @return Whether the value has been successfully set.
      * @hide
      */
-    @UnsupportedAppUsage
-    public boolean setMessageAccessPermission(int value) {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean setMessageAccessPermission(@AccessPermission int value) {
+        // Validates param value is one of the accepted constants
+        if (value != ACCESS_ALLOWED && value != ACCESS_REJECTED && value != ACCESS_UNKNOWN) {
+            throw new IllegalArgumentException(value + "is not a valid AccessPermission value");
+        }
         final IBluetooth service = sService;
         if (service == null) {
             return false;
@@ -1711,13 +1723,14 @@
     }
 
     /**
-     * Requires {@link android.Manifest.permission#BLUETOOTH}.
+     * Gets whether sim access is allowed for this bluetooth device
      *
-     * @return Whether the Sim access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
-     * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
+     * @return Whether the Sim access is allowed to this device.
      * @hide
      */
-    public int getSimAccessPermission() {
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @AccessPermission int getSimAccessPermission() {
         final IBluetooth service = sService;
         if (service == null) {
             return ACCESS_UNKNOWN;
@@ -1732,14 +1745,14 @@
 
     /**
      * Sets whether the Sim access is allowed to this device.
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
      *
      * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
      * #ACCESS_REJECTED}.
      * @return Whether the value has been successfully set.
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
     public boolean setSimAccessPermission(int value) {
         final IBluetooth service = sService;
         if (service == null) {
@@ -1970,7 +1983,7 @@
      * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
      * @hide
      */
-    @UnsupportedAppUsage
+    @VisibleForTesting
     public static byte[] convertPinToBytes(String pin) {
         if (pin == null) {
             return null;
diff --git a/core/java/android/hardware/soundtrigger/ModelParams.aidl b/core/java/android/hardware/soundtrigger/ModelParams.aidl
new file mode 100644
index 0000000..d90dc81
--- /dev/null
+++ b/core/java/android/hardware/soundtrigger/ModelParams.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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 android.hardware.soundtrigger;
+
+/**
+ * Model specific parameters to be used with parameter set and get APIs
+ * {@hide}
+ */
+@Backing(type="int")
+enum ModelParams {
+  /**
+   * Placeholder for invalid model parameter used for returning error or
+   * passing an invalid value.
+   */
+  INVALID = -1,
+  /**
+   * Controls the sensitivity threshold adjustment factor for a given model.
+   * Negative value corresponds to less sensitive model (high threshold) and
+   * a positive value corresponds to a more sensitive model (low threshold).
+   * Default value is 0.
+   */
+  THRESHOLD_FACTOR = 0,
+}
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
index 325a9ad..94c4216 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.aidl
@@ -24,5 +24,6 @@
 parcelable SoundTrigger.KeyphraseRecognitionExtra;
 parcelable SoundTrigger.KeyphraseSoundModel;
 parcelable SoundTrigger.GenericSoundModel;
+parcelable SoundTrigger.ModelParamRange;
 parcelable SoundTrigger.ModuleProperties;
 parcelable SoundTrigger.RecognitionConfig;
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index b1134e1..86f3eec 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -567,6 +567,65 @@
         }
     }
 
+    /*****************************************************************************
+     * A ModelParamRange is a representation of supported parameter range for a
+     * given loaded model.
+     ****************************************************************************/
+    public static final class ModelParamRange implements Parcelable {
+
+        /**
+         * start of supported range inclusive
+         */
+        public final int start;
+
+        /**
+         * end of supported range inclusive
+         */
+        public final int end;
+
+        ModelParamRange(int start, int end) {
+            this.start = start;
+            this.end = end;
+        }
+
+        private ModelParamRange(@NonNull Parcel in) {
+            this.start = in.readInt();
+            this.end = in.readInt();
+        }
+
+        @NonNull
+        public static final Creator<ModelParamRange> CREATOR = new Creator<ModelParamRange>() {
+            @Override
+            @NonNull
+            public ModelParamRange createFromParcel(@NonNull Parcel in) {
+                return new ModelParamRange(in);
+            }
+
+            @Override
+            @NonNull
+            public ModelParamRange[] newArray(int size) {
+                return new ModelParamRange[size];
+            }
+        };
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeInt(start);
+            dest.writeInt(end);
+        }
+
+        @Override
+        @NonNull
+        public String toString() {
+            return "ModelParamRange [start=" + start + ", end=" + end + "]";
+        }
+    }
+
     /**
      *  Modes for key phrase recognition
      */
diff --git a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
index 9113548..b16ef5c 100644
--- a/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
+++ b/core/java/android/hardware/soundtrigger/SoundTriggerModule.java
@@ -16,7 +16,9 @@
 
 package android.hardware.soundtrigger;
 
+import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
+import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -150,6 +152,57 @@
      */
     public native int getModelState(int soundModelHandle);
 
+    /**
+     * Set a model specific {@link ModelParams} with the given value. This
+     * parameter will keep its value for the duration the model is loaded regardless of starting and
+     * stopping recognition. Once the model is unloaded, the value will be lost.
+     * {@link SoundTriggerModule#isParameterSupported} should be checked first before calling this
+     * method.
+     *
+     * @param soundModelHandle handle of model to apply parameter
+     * @param modelParam   {@link ModelParams}
+     * @param value        Value to set
+     * @return - {@link SoundTrigger#STATUS_OK} in case of success
+     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
+     *         - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
+     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
+     *           if API is not supported by HAL
+     */
+    public native int setParameter(int soundModelHandle,
+            @ModelParams int modelParam, int value);
+
+    /**
+     * Get a model specific {@link ModelParams}. This parameter will keep its value
+     * for the duration the model is loaded regardless of starting and stopping recognition.
+     * Once the model is unloaded, the value will be lost. If the value is not set, a default
+     * value is returned. See {@link ModelParams} for parameter default values.
+     * {@link SoundTriggerModule#isParameterSupported} should be checked first before
+     * calling this method. Otherwise, an exception can be thrown.
+     *
+     * @param soundModelHandle handle of model to get parameter
+     * @param modelParam   {@link ModelParams}
+     * @return value of parameter
+     * @throws UnsupportedOperationException if hal or model do not support this API.
+     *         {@link SoundTriggerModule#isParameterSupported} should be checked first.
+     * @throws IllegalArgumentException if invalid model handle or parameter is passed.
+     *         {@link SoundTriggerModule#isParameterSupported} should be checked first.
+     */
+    public native int getParameter(int soundModelHandle,
+            @ModelParams int modelParam)
+            throws UnsupportedOperationException, IllegalArgumentException;
+
+    /**
+     * Determine if parameter control is supported for the given model handle.
+     * This method should be checked prior to calling {@link SoundTriggerModule#setParameter} or
+     * {@link SoundTriggerModule#getParameter}.
+     *
+     * @param soundModelHandle handle of model to get parameter
+     * @param modelParam {@link ModelParams}
+     * @return supported range of parameter, null if not supported
+     */
+    @Nullable
+    public native ModelParamRange queryParameter(int soundModelHandle, @ModelParams int modelParam);
+
     private class NativeEventHandlerDelegate {
         private final Handler mHandler;
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9fed269..4754444 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2422,7 +2422,7 @@
 
     public static final int DATA_CONNECTION_OUT_OF_SERVICE = 0;
     public static final int DATA_CONNECTION_EMERGENCY_SERVICE =
-            TelephonyManager.MAX_NETWORK_TYPE + 1;
+            TelephonyManager.getAllNetworkTypes().length + 1;
     public static final int DATA_CONNECTION_OTHER = DATA_CONNECTION_EMERGENCY_SERVICE + 1;
 
 
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
index 9ac4cf2..952d7cb 100644
--- a/core/java/android/util/StatsLog.java
+++ b/core/java/android/util/StatsLog.java
@@ -24,7 +24,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.os.IStatsManager;
+import android.os.IStatsd;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
@@ -36,7 +36,7 @@
     private static final String TAG = "StatsLog";
     private static final boolean DEBUG = false;
 
-    private static IStatsManager sService;
+    private static IStatsd sService;
 
     private static Object sLogLock = new Object();
 
@@ -52,7 +52,7 @@
     public static boolean logStart(int label) {
         synchronized (sLogLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (service == null) {
                     if (DEBUG) {
                         Slog.d(TAG, "Failed to find statsd when logging start");
@@ -81,7 +81,7 @@
     public static boolean logStop(int label) {
         synchronized (sLogLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (service == null) {
                     if (DEBUG) {
                         Slog.d(TAG, "Failed to find statsd when logging stop");
@@ -109,7 +109,7 @@
     public static boolean logEvent(int label) {
         synchronized (sLogLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (service == null) {
                     if (DEBUG) {
                         Slog.d(TAG, "Failed to find statsd when logging event");
@@ -151,7 +151,7 @@
             @NonNull long[] experimentIds) {
         synchronized (sLogLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (service == null) {
                     if (DEBUG) {
                         Slog.d(TAG, "Failed to find statsd when logging event");
@@ -191,7 +191,7 @@
             long packageVersionCode, int rollbackReason, String failingPackageName) {
         synchronized (sLogLock) {
             try {
-                IStatsManager service = getIStatsManagerLocked();
+                IStatsd service = getIStatsdLocked();
                 if (service == null) {
                     if (DEBUG) {
                         Slog.d(TAG, "Failed to find statsd when logging event");
@@ -215,11 +215,11 @@
     }
 
 
-    private static IStatsManager getIStatsManagerLocked() throws RemoteException {
+    private static IStatsd getIStatsdLocked() throws RemoteException {
         if (sService != null) {
             return sService;
         }
-        sService = IStatsManager.Stub.asInterface(ServiceManager.getService("stats"));
+        sService = IStatsd.Stub.asInterface(ServiceManager.getService("stats"));
         return sService;
     }
 
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7cec440..c571737 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -3473,10 +3473,18 @@
         return applyAsync(context, parent, executor, listener, null);
     }
 
+    private CancellationSignal startTaskOnExecutor(AsyncApplyTask task, Executor executor) {
+        CancellationSignal cancelSignal = new CancellationSignal();
+        cancelSignal.setOnCancelListener(task);
+
+        task.executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
+        return cancelSignal;
+    }
+
     /** @hide */
     public CancellationSignal applyAsync(Context context, ViewGroup parent,
             Executor executor, OnViewAppliedListener listener, OnClickHandler handler) {
-        return getAsyncApplyTask(context, parent, listener, handler).startTaskOnExecutor(executor);
+        return startTaskOnExecutor(getAsyncApplyTask(context, parent, listener, handler), executor);
     }
 
     private AsyncApplyTask getAsyncApplyTask(Context context, ViewGroup parent,
@@ -3487,7 +3495,6 @@
 
     private class AsyncApplyTask extends AsyncTask<Void, Void, ViewTree>
             implements CancellationSignal.OnCancelListener {
-        final CancellationSignal mCancelSignal = new CancellationSignal();
         final RemoteViews mRV;
         final ViewGroup mParent;
         final Context mContext;
@@ -3538,7 +3545,6 @@
 
         @Override
         protected void onPostExecute(ViewTree viewTree) {
-            mCancelSignal.setOnCancelListener(null);
             if (mError == null) {
                 if (mListener != null) {
                     mListener.onViewInflated(viewTree.mRoot);
@@ -3575,13 +3581,6 @@
         @Override
         public void onCancel() {
             cancel(true);
-            mCancelSignal.setOnCancelListener(null);
-        }
-
-        private CancellationSignal startTaskOnExecutor(Executor executor) {
-            mCancelSignal.setOnCancelListener(this);
-            executeOnExecutor(executor == null ? AsyncTask.THREAD_POOL_EXECUTOR : executor);
-            return mCancelSignal;
         }
     }
 
@@ -3647,8 +3646,8 @@
             }
         }
 
-        return new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
-                context, listener, handler, v).startTaskOnExecutor(executor);
+        return startTaskOnExecutor(new AsyncApplyTask(rvToApply, (ViewGroup) v.getParent(),
+                context, listener, handler, v), executor);
     }
 
     private void performApply(View v, ViewGroup parent, OnClickHandler handler) {
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
index ea24d5f..d94294f 100644
--- a/core/java/com/android/internal/app/ISoundTriggerService.aidl
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -20,6 +20,7 @@
 import android.content.ComponentName;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
+import android.hardware.soundtrigger.ModelParams;
 import android.os.Bundle;
 import android.os.ParcelUuid;
 
@@ -56,4 +57,16 @@
     int getModelState(in ParcelUuid soundModelId);
 
     @nullable SoundTrigger.ModuleProperties getModuleProperties();
+
+    int setParameter(in ParcelUuid soundModelId, in ModelParams modelParam,
+        int value);
+
+    /**
+     * @throws UnsupportedOperationException if hal or model do not support this API.
+     * @throws IllegalArgumentException if invalid model handle or parameter is passed.
+     */
+    int getParameter(in ParcelUuid soundModelId, in ModelParams modelParam);
+
+    @nullable SoundTrigger.ModelParamRange queryParameter(in ParcelUuid soundModelId,
+        in ModelParams modelParam);
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index bc44fcf..7140e7e 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5267,7 +5267,7 @@
         // Unknown is included in DATA_CONNECTION_OTHER.
         int bin = DATA_CONNECTION_OUT_OF_SERVICE;
         if (hasData) {
-            if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
+            if (dataType > 0 && dataType <= TelephonyManager.getAllNetworkTypes().length) {
                 bin = dataType;
             } else {
                 switch (serviceType) {
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 0002f8b..4376b0b 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -44,6 +44,13 @@
     jmethodID    toString;
 } gUUIDMethods;
 
+static const char* const kUnsupportedOperationExceptionClassPathName =
+     "java/lang/UnsupportedOperationException";
+static jclass gUnsupportedOperationExceptionClass;
+static const char* const kIllegalArgumentExceptionClassPathName =
+     "java/lang/IllegalArgumentException";
+static jclass gIllegalArgumentExceptionClass;
+
 static const char* const kSoundTriggerClassPathName = "android/hardware/soundtrigger/SoundTrigger";
 static jclass gSoundTriggerClass;
 
@@ -91,6 +98,11 @@
     jfieldID    keyphrases;
 } gKeyphraseSoundModelFields;
 
+static const char* const kModelParamRangeClassPathName =
+                                "android/hardware/soundtrigger/SoundTrigger$ModelParamRange";
+static jclass gModelParamRangeClass;
+static jmethodID gModelParamRangeCstor;
+
 static const char* const kRecognitionConfigClassPathName =
                                      "android/hardware/soundtrigger/SoundTrigger$RecognitionConfig";
 static jclass gRecognitionConfigClass;
@@ -164,6 +176,16 @@
     SOUNDTRIGGER_EVENT_SERVICE_STATE_CHANGE = 4,
 };
 
+static jint throwUnsupportedOperationException(JNIEnv *env)
+{
+    return env->ThrowNew(gUnsupportedOperationExceptionClass, nullptr);
+}
+
+static jint throwIllegalArgumentException(JNIEnv *env)
+{
+    return env->ThrowNew(gIllegalArgumentExceptionClass, nullptr);
+}
+
 // ----------------------------------------------------------------------------
 // ref-counted object for callbacks
 class JNISoundTriggerCallback: public SoundTriggerCallback
@@ -822,6 +844,69 @@
     return status;
 }
 
+static jint
+android_hardware_SoundTrigger_setParameter(JNIEnv *env, jobject thiz,
+                                            jint jHandle, jint jModelParam, jint jValue)
+{
+    ALOGV("setParameter");
+    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+    if (module == NULL) {
+        return SOUNDTRIGGER_STATUS_NO_INIT;
+    }
+    return module->setParameter(jHandle, (sound_trigger_model_parameter_t) jModelParam, jValue);
+}
+
+static jint
+android_hardware_SoundTrigger_getParameter(JNIEnv *env, jobject thiz,
+                                            jint jHandle, jint jModelParam)
+{
+    ALOGV("getParameter");
+    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+    if (module == NULL) {
+        throwUnsupportedOperationException(env);
+        return -1;
+    }
+
+    jint nValue;
+    jint status = module->getParameter(jHandle,
+            (sound_trigger_model_parameter_t) jModelParam, &nValue);
+
+    switch (status) {
+        case 0:
+            return nValue;
+        case -EINVAL:
+            throwIllegalArgumentException(env);
+            break;
+        default:
+            throwUnsupportedOperationException(env);
+            break;
+    }
+
+    return -1;
+}
+
+static jobject
+android_hardware_SoundTrigger_queryParameter(JNIEnv *env, jobject thiz,
+                                            jint jHandle, jint jModelParam)
+{
+    ALOGV("queryParameter");
+    sp<SoundTrigger> module = getSoundTrigger(env, thiz);
+    if (module == nullptr) {
+        return nullptr;
+    }
+
+    sound_trigger_model_parameter_range_t nRange;
+    jint nValue = module->queryParameter(jHandle,
+            (sound_trigger_model_parameter_t) jModelParam, &nRange);
+
+    if (nValue != 0) {
+        ALOGE("failed to query parameter error code: %d", nValue);
+        return nullptr;
+    }
+
+    return env->NewObject(gModelParamRangeClass, gModelParamRangeCstor, nRange.start, nRange.end);
+}
+
 static const JNINativeMethod gMethods[] = {
     {"listModules",
         "(Ljava/lang/String;Ljava/util/ArrayList;)I",
@@ -854,6 +939,15 @@
     {"getModelState",
         "(I)I",
         (void *)android_hardware_SoundTrigger_getModelState},
+    {"setParameter",
+         "(III)I",
+         (void *)android_hardware_SoundTrigger_setParameter},
+    {"getParameter",
+         "(II)I",
+         (void *)android_hardware_SoundTrigger_getParameter},
+    {"queryParameter",
+         "(II)Landroid/hardware/soundtrigger/SoundTrigger$ModelParamRange;",
+         (void *)android_hardware_SoundTrigger_queryParameter}
 };
 
 int register_android_hardware_SoundTrigger(JNIEnv *env)
@@ -866,6 +960,12 @@
     gUUIDClass = MakeGlobalRefOrDie(env, uuidClass);
     gUUIDMethods.toString = GetMethodIDOrDie(env, uuidClass, "toString", "()Ljava/lang/String;");
 
+    jclass exUClass = FindClassOrDie(env, kUnsupportedOperationExceptionClassPathName);
+    gUnsupportedOperationExceptionClass = MakeGlobalRefOrDie(env, exUClass);
+
+    jclass exIClass = FindClassOrDie(env, kIllegalArgumentExceptionClassPathName);
+    gIllegalArgumentExceptionClass = MakeGlobalRefOrDie(env, exIClass);
+
     jclass lClass = FindClassOrDie(env, kSoundTriggerClassPathName);
     gSoundTriggerClass = MakeGlobalRefOrDie(env, lClass);
 
@@ -906,6 +1006,10 @@
                                          "keyphrases",
                                          "[Landroid/hardware/soundtrigger/SoundTrigger$Keyphrase;");
 
+    jclass modelParamRangeClass = FindClassOrDie(env, kModelParamRangeClassPathName);
+    gModelParamRangeClass = MakeGlobalRefOrDie(env, modelParamRangeClass);
+    gModelParamRangeCstor = GetMethodIDOrDie(env, modelParamRangeClass, "<init>", "(II)V");
+
     jclass recognitionEventClass = FindClassOrDie(env, kRecognitionEventClassPathName);
     gRecognitionEventClass = MakeGlobalRefOrDie(env, recognitionEventClass);
     gRecognitionEventCstor = GetMethodIDOrDie(env, recognitionEventClass, "<init>",
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index b906d84..ed613c3 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -176,14 +176,12 @@
                         mDevice.setPin(mPin);
                         break;
                     case BluetoothDevice.PAIRING_VARIANT_PASSKEY:
-                        mDevice.setPasskey(mPasskey);
                         break;
                     case BluetoothDevice.PAIRING_VARIANT_PASSKEY_CONFIRMATION:
                     case BluetoothDevice.PAIRING_VARIANT_CONSENT:
                         mDevice.setPairingConfirmation(true);
                         break;
                     case BluetoothDevice.PAIRING_VARIANT_OOB_CONSENT:
-                        mDevice.setRemoteOutOfBandData();
                         break;
                 }
             } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(intent.getAction())) {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index dc400ad..61b3e76 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -26,9 +26,11 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
+import android.hardware.soundtrigger.ModelParams;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.hardware.soundtrigger.SoundTrigger.SoundModel;
 import android.os.Bundle;
@@ -67,7 +69,7 @@
     /**
      * @hide
      */
-    public SoundTriggerManager(Context context, ISoundTriggerService soundTriggerService ) {
+    public SoundTriggerManager(Context context, ISoundTriggerService soundTriggerService) {
         if (DBG) {
             Slog.i(TAG, "SoundTriggerManager created.");
         }
@@ -89,14 +91,22 @@
     }
 
     /**
-     * Returns the sound trigger model represented by the given UUID. An instance of {@link Model}
-     * is returned.
+     * Get {@link SoundTriggerManager.Model} which is registered with the passed UUID
+     *
+     * @param soundModelId UUID associated with a loaded model
+     * @return {@link SoundTriggerManager.Model} associated with UUID soundModelId
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @Nullable
     public Model getModel(UUID soundModelId) {
         try {
-            return new Model(mSoundTriggerService.getSoundModel(
-                    new ParcelUuid(soundModelId)));
+            GenericSoundModel model =
+                    mSoundTriggerService.getSoundModel(new ParcelUuid(soundModelId));
+            if (model == null) {
+                return null;
+            }
+
+            return new Model(model);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -399,4 +409,80 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Set a model specific {@link ModelParams} with the given value. This
+     * parameter will keep its value for the duration the model is loaded regardless of starting and
+     * stopping recognition. Once the model is unloaded, the value will be lost.
+     * {@link SoundTriggerManager#queryParameter} should be checked first before calling this
+     * method.
+     *
+     * @param soundModelId UUID of model to apply the parameter value to.
+     * @param modelParam   {@link ModelParams}
+     * @param value        Value to set
+     * @return - {@link SoundTrigger#STATUS_OK} in case of success
+     *         - {@link SoundTrigger#STATUS_NO_INIT} if the native service cannot be reached
+     *         - {@link SoundTrigger#STATUS_BAD_VALUE} invalid input parameter
+     *         - {@link SoundTrigger#STATUS_INVALID_OPERATION} if the call is out of sequence or
+     *           if API is not supported by HAL
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    public int setParameter(@Nullable UUID soundModelId,
+            @ModelParams int modelParam, int value)
+            throws UnsupportedOperationException, IllegalArgumentException {
+        try {
+            return mSoundTriggerService.setParameter(new ParcelUuid(soundModelId), modelParam,
+                    value);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Get a model specific {@link ModelParams}. This parameter will keep its value
+     * for the duration the model is loaded regardless of starting and stopping recognition.
+     * Once the model is unloaded, the value will be lost. If the value is not set, a default
+     * value is returned. See {@link ModelParams} for parameter default values.
+     * {@link SoundTriggerManager#queryParameter} should be checked first before
+     * calling this method. Otherwise, an exception can be thrown.
+     *
+     * @param soundModelId UUID of model to get parameter
+     * @param modelParam   {@link ModelParams}
+     * @return value of parameter
+     * @throws UnsupportedOperationException if hal or model do not support this API.
+     *         {@link SoundTriggerManager#queryParameter} should be checked first.
+     * @throws IllegalArgumentException if invalid model handle or parameter is passed.
+     *         {@link SoundTriggerManager#queryParameter} should be checked first.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    public int getParameter(@NonNull UUID soundModelId,
+            @ModelParams int modelParam)
+            throws UnsupportedOperationException, IllegalArgumentException {
+        try {
+            return mSoundTriggerService.getParameter(new ParcelUuid(soundModelId), modelParam);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Determine if parameter control is supported for the given model handle.
+     * This method should be checked prior to calling {@link SoundTriggerManager#setParameter} or
+     * {@link SoundTriggerManager#getParameter}.
+     *
+     * @param soundModelId handle of model to get parameter
+     * @param modelParam {@link ModelParams}
+     * @return supported range of parameter, null if not supported
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @Nullable
+    public ModelParamRange queryParameter(@Nullable UUID soundModelId,
+            @ModelParams int modelParam) {
+        try {
+            return mSoundTriggerService.queryParameter(new ParcelUuid(soundModelId),
+                    modelParam);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index c8f0ff1..79e4d8a 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -38,7 +38,7 @@
 // kPlayOnCallingThread = true prior to R.
 // Changing to false means calls to play() are almost instantaneous instead of taking around
 // ~10ms to launch the AudioTrack. It is perhaps 100x faster.
-static constexpr bool kPlayOnCallingThread = false;
+static constexpr bool kPlayOnCallingThread = true;
 
 // Amount of time for a StreamManager thread to wait before closing.
 static constexpr int64_t kWaitTimeBeforeCloseNs = 9 * NANOS_PER_SECOND;
@@ -170,6 +170,7 @@
                     if (stream->getSoundID() == soundID) {
                         ALOGV("%s: found soundID %d in restart queue", __func__, soundID);
                         newStream = stream;
+                        fromAvailableQueue = false;
                         break;
                     } else if (newStream == nullptr) {
                         ALOGV("%s: found stream in restart queue", __func__);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 0666596..747ceb1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -721,12 +721,8 @@
 
         refresh();
 
-        if (bondState == BluetoothDevice.BOND_BONDED) {
-            if (mDevice.isBluetoothDock()) {
-                onBondingDockConnect();
-            } else if (mDevice.isBondingInitiatedLocally()) {
-                connect(false);
-            }
+        if (bondState == BluetoothDevice.BOND_BONDED && mDevice.isBondingInitiatedLocally()) {
+            connect(false);
         }
     }
 
diff --git a/packages/SystemUI/plugin_core/Android.bp b/packages/SystemUI/plugin_core/Android.bp
index 42d6762..581fef7 100644
--- a/packages/SystemUI/plugin_core/Android.bp
+++ b/packages/SystemUI/plugin_core/Android.bp
@@ -16,4 +16,8 @@
     sdk_version: "current",
     name: "PluginCoreLib",
     srcs: ["src/**/*.java"],
+
+    // Enforce that the library is built against java 8 so that there are
+    // no compatibility issues with launcher
+    java_version: "1.8",
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 9dcfb6a..9a64b30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -38,6 +38,7 @@
 import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
 
 import java.util.ArrayList;
+import java.util.List;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -89,11 +90,22 @@
         }
         final RankingMap currentRanking = getCurrentRanking();
         mMainHandler.post(() -> {
+            // There's currently a race condition between the calls to getActiveNotifications() and
+            // getCurrentRanking(). It's possible for the ranking that we store here to not contain
+            // entries for every notification in getActiveNotifications(). To prevent downstream
+            // crashes, we temporarily fill in these missing rankings with stubs.
+            // See b/146011844 for long-term fix
+            final List<Ranking> newRankings = new ArrayList<>();
+            for (StatusBarNotification sbn : notifications) {
+                newRankings.add(getRankingOrTemporaryStandIn(currentRanking, sbn.getKey()));
+            }
+            final RankingMap completeMap = new RankingMap(newRankings.toArray(new Ranking[0]));
+
             for (StatusBarNotification sbn : notifications) {
                 if (mDownstreamListener != null) {
-                    mDownstreamListener.onNotificationPosted(sbn, currentRanking);
+                    mDownstreamListener.onNotificationPosted(sbn, completeMap);
                 }
-                mEntryManager.addNotification(sbn, currentRanking);
+                mEntryManager.addNotification(sbn, completeMap);
             }
         });
         NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
@@ -192,6 +204,35 @@
         }
     }
 
+    private static Ranking getRankingOrTemporaryStandIn(RankingMap rankingMap, String key) {
+        Ranking ranking = new Ranking();
+        if (!rankingMap.getRanking(key, ranking)) {
+            ranking.populate(
+                    key,
+                    0,
+                    false,
+                    0,
+                    0,
+                    0,
+                    null,
+                    null,
+                    null,
+                    new ArrayList<>(),
+                    new ArrayList<>(),
+                    false,
+                    0,
+                    false,
+                    0,
+                    false,
+                    new ArrayList<>(),
+                    new ArrayList<>(),
+                    false,
+                    false
+            );
+        }
+        return ranking;
+    }
+
     public interface NotificationSettingsListener {
 
         default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index b0cd90c..a6108a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -91,7 +91,8 @@
     @VisibleForTesting
     boolean mIsShowingIconGracefully = false;
     // Some specific carriers have 5GE network which is special LTE CA network.
-    private static final int NETWORK_TYPE_LTE_CA_5GE = TelephonyManager.MAX_NETWORK_TYPE + 1;
+    private static final int NETWORK_TYPE_LTE_CA_5GE =
+            TelephonyManager.getAllNetworkTypes().length + 1;
 
     // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
     // need listener lists anymore.
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java
new file mode 100644
index 0000000..264a683
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java
@@ -0,0 +1,474 @@
+/*
+ * 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.wm;
+
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.os.Process.SYSTEM_UID;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
+import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.util.Size;
+import android.view.Display;
+import android.view.DisplayCutout;
+import android.view.DisplayInfo;
+import android.view.Gravity;
+import android.view.Surface;
+
+import com.android.internal.R;
+
+import java.util.List;
+
+/**
+ * Contains information about the layout-properties of a display. This refers to internal layout
+ * like insets/cutout/rotation. In general, this can be thought of as the System-UI analog to
+ * DisplayPolicy.
+ */
+public class DisplayLayout {
+    // Navigation bar position values
+    private static final int NAV_BAR_LEFT = 1 << 0;
+    private static final int NAV_BAR_RIGHT = 1 << 1;
+    private static final int NAV_BAR_BOTTOM = 1 << 2;
+
+    private int mUiMode;
+    private int mWidth;
+    private int mHeight;
+    private DisplayCutout mCutout;
+    private int mRotation;
+    private int mDensityDpi;
+    private final Rect mNonDecorInsets = new Rect();
+    private final Rect mStableInsets = new Rect();
+    private boolean mHasNavigationBar = false;
+    private boolean mHasStatusBar = false;
+
+    /**
+     * Create empty layout.
+     */
+    public DisplayLayout() {
+    }
+
+    /**
+     * Construct a custom display layout using a DisplayInfo.
+     * @param info
+     * @param res
+     */
+    public DisplayLayout(DisplayInfo info, Resources res, boolean hasNavigationBar,
+            boolean hasStatusBar) {
+        init(info, res, hasNavigationBar, hasStatusBar);
+    }
+
+    /**
+     * Construct a display layout based on a live display.
+     * @param context Used for resources.
+     */
+    public DisplayLayout(@NonNull Context context, @NonNull Display rawDisplay) {
+        final int displayId = rawDisplay.getDisplayId();
+        DisplayInfo info = new DisplayInfo();
+        rawDisplay.getDisplayInfo(info);
+        init(info, context.getResources(), hasNavigationBar(info, context, displayId),
+                hasStatusBar(displayId));
+    }
+
+    public DisplayLayout(DisplayLayout dl) {
+        set(dl);
+    }
+
+    /** sets this DisplayLayout to a copy of another on. */
+    public void set(DisplayLayout dl) {
+        mUiMode = dl.mUiMode;
+        mWidth = dl.mWidth;
+        mHeight = dl.mHeight;
+        mCutout = dl.mCutout;
+        mRotation = dl.mRotation;
+        mDensityDpi = dl.mDensityDpi;
+        mHasNavigationBar = dl.mHasNavigationBar;
+        mHasStatusBar = dl.mHasStatusBar;
+        mNonDecorInsets.set(dl.mNonDecorInsets);
+        mStableInsets.set(dl.mStableInsets);
+    }
+
+    private void init(DisplayInfo info, Resources res, boolean hasNavigationBar,
+            boolean hasStatusBar) {
+        mUiMode = res.getConfiguration().uiMode;
+        mWidth = info.logicalWidth;
+        mHeight = info.logicalHeight;
+        mRotation = info.rotation;
+        mCutout = info.displayCutout;
+        mDensityDpi = info.logicalDensityDpi;
+        mHasNavigationBar = hasNavigationBar;
+        mHasStatusBar = hasStatusBar;
+        recalcInsets(res);
+    }
+
+    private void recalcInsets(Resources res) {
+        computeNonDecorInsets(res, mRotation, mWidth, mHeight, mCutout, mUiMode, mNonDecorInsets,
+                mHasNavigationBar);
+        mStableInsets.set(mNonDecorInsets);
+        if (mHasStatusBar) {
+            convertNonDecorInsetsToStableInsets(res, mStableInsets, mWidth, mHeight, mHasStatusBar);
+        }
+    }
+
+    /**
+     * Apply a rotation to this layout and its parameters.
+     * @param res
+     * @param targetRotation
+     */
+    public void rotateTo(Resources res, @Surface.Rotation int targetRotation) {
+        final int rotationDelta = (targetRotation - mRotation + 4) % 4;
+        final boolean changeOrient = (rotationDelta % 2) != 0;
+
+        final int origWidth = mWidth;
+        final int origHeight = mHeight;
+
+        mRotation = targetRotation;
+        if (changeOrient) {
+            mWidth = origHeight;
+            mHeight = origWidth;
+        }
+
+        if (mCutout != null && !mCutout.isEmpty()) {
+            mCutout = calculateDisplayCutoutForRotation(mCutout, rotationDelta, origWidth,
+                    origHeight);
+        }
+
+        recalcInsets(res);
+    }
+
+    /** Get this layout's non-decor insets. */
+    public Rect nonDecorInsets() {
+        return mNonDecorInsets;
+    }
+
+    /** Get this layout's stable insets. */
+    public Rect stableInsets() {
+        return mStableInsets;
+    }
+
+    /** Get this layout's width. */
+    public int width() {
+        return mWidth;
+    }
+
+    /** Get this layout's height. */
+    public int height() {
+        return mHeight;
+    }
+
+    /** Get this layout's display rotation. */
+    public int rotation() {
+        return mRotation;
+    }
+
+    /** Get this layout's display density. */
+    public int densityDpi() {
+        return mDensityDpi;
+    }
+
+    /** Get whether this layout is landscape. */
+    public boolean isLandscape() {
+        return mWidth > mHeight;
+    }
+
+    /** Gets the orientation of this layout */
+    public int getOrientation() {
+        return (mWidth > mHeight) ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
+    }
+
+    /** Gets the calculated stable-bounds for this layout */
+    public void getStableBounds(Rect outBounds) {
+        outBounds.set(0, 0, mWidth, mHeight);
+        outBounds.inset(mStableInsets);
+    }
+
+    /**
+     * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta`
+     * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and
+     * remains at 0,0 after rotation.
+     *
+     * Only 'bounds' is mutated.
+     */
+    public static void rotateBounds(Rect inOutBounds, Rect parentBounds, int delta) {
+        int rdelta = ((delta % 4) + 4) % 4;
+        int origLeft = inOutBounds.left;
+        switch (rdelta) {
+            case 0:
+                return;
+            case 1:
+                inOutBounds.left = inOutBounds.top;
+                inOutBounds.top = parentBounds.right - inOutBounds.right;
+                inOutBounds.right = inOutBounds.bottom;
+                inOutBounds.bottom = parentBounds.right - origLeft;
+                return;
+            case 2:
+                inOutBounds.left = parentBounds.right - inOutBounds.right;
+                inOutBounds.right = parentBounds.right - origLeft;
+                return;
+            case 3:
+                inOutBounds.left = parentBounds.bottom - inOutBounds.bottom;
+                inOutBounds.bottom = inOutBounds.right;
+                inOutBounds.right = parentBounds.bottom - inOutBounds.top;
+                inOutBounds.top = origLeft;
+                return;
+        }
+    }
+
+    /**
+     * Calculates the stable insets if we already have the non-decor insets.
+     */
+    private static void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
+            int displayWidth, int displayHeight, boolean hasStatusBar) {
+        if (!hasStatusBar) {
+            return;
+        }
+        int statusBarHeight = getStatusBarHeight(displayWidth > displayHeight, res);
+        inOutInsets.top = Math.max(inOutInsets.top, statusBarHeight);
+    }
+
+    /**
+     * Calculates the insets for the areas that could never be removed in Honeycomb, i.e. system
+     * bar or button bar.
+     *
+     * @param displayRotation the current display rotation
+     * @param displayWidth the current display width
+     * @param displayHeight the current display height
+     * @param displayCutout the current display cutout
+     * @param outInsets the insets to return
+     */
+    static void computeNonDecorInsets(Resources res, int displayRotation, int displayWidth,
+            int displayHeight, DisplayCutout displayCutout, int uiMode, Rect outInsets,
+            boolean hasNavigationBar) {
+        outInsets.setEmpty();
+
+        // Only navigation bar
+        if (hasNavigationBar) {
+            int position = navigationBarPosition(res, displayWidth, displayHeight, displayRotation);
+            int navBarSize =
+                    getNavigationBarSize(res, position, displayWidth > displayHeight, uiMode);
+            if (position == NAV_BAR_BOTTOM) {
+                outInsets.bottom = navBarSize;
+            } else if (position == NAV_BAR_RIGHT) {
+                outInsets.right = navBarSize;
+            } else if (position == NAV_BAR_LEFT) {
+                outInsets.left = navBarSize;
+            }
+        }
+
+        if (displayCutout != null) {
+            outInsets.left += displayCutout.getSafeInsetLeft();
+            outInsets.top += displayCutout.getSafeInsetTop();
+            outInsets.right += displayCutout.getSafeInsetRight();
+            outInsets.bottom += displayCutout.getSafeInsetBottom();
+        }
+    }
+
+    /**
+     * Calculates the stable insets without running a layout.
+     *
+     * @param displayRotation the current display rotation
+     * @param displayWidth the current display width
+     * @param displayHeight the current display height
+     * @param displayCutout the current display cutout
+     * @param outInsets the insets to return
+     */
+    static void computeStableInsets(Resources res, int displayRotation, int displayWidth,
+            int displayHeight, DisplayCutout displayCutout, int uiMode, Rect outInsets,
+            boolean hasNavigationBar, boolean hasStatusBar) {
+        outInsets.setEmpty();
+
+        // Navigation bar and status bar.
+        computeNonDecorInsets(res, displayRotation, displayWidth, displayHeight, displayCutout,
+                uiMode, outInsets, hasNavigationBar);
+        convertNonDecorInsetsToStableInsets(res, outInsets, displayWidth, displayHeight,
+                hasStatusBar);
+    }
+
+    /** Retrieve the statusbar height from resources. */
+    static int getStatusBarHeight(boolean landscape, Resources res) {
+        return landscape ? res.getDimensionPixelSize(
+                    com.android.internal.R.dimen.status_bar_height_landscape)
+                    : res.getDimensionPixelSize(
+                            com.android.internal.R.dimen.status_bar_height_portrait);
+    }
+
+    /** Calculate the DisplayCutout for a particular display size/rotation. */
+    public static DisplayCutout calculateDisplayCutoutForRotation(
+            DisplayCutout cutout, int rotation, int displayWidth, int displayHeight) {
+        if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
+            return null;
+        }
+        if (rotation == ROTATION_0) {
+            return computeSafeInsets(
+                    cutout, displayWidth, displayHeight);
+        }
+        final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
+        Rect[] cutoutRects = computeSafeInsets(cutout, displayWidth, displayHeight)
+                        .getBoundingRectsAll();
+        final Rect[] newBounds = new Rect[cutoutRects.length];
+        final Rect displayBounds = new Rect(0, 0, displayWidth, displayHeight);
+        for (int i = 0; i < cutoutRects.length; ++i) {
+            newBounds[i] = new Rect(cutoutRects[i]);
+            rotateBounds(newBounds[i], displayBounds, rotation);
+        }
+        return computeSafeInsets(DisplayCutout.fromBounds(newBounds),
+                rotated ? displayHeight : displayWidth,
+                rotated ? displayWidth : displayHeight);
+    }
+
+    /** Calculate safe insets. */
+    public static DisplayCutout computeSafeInsets(DisplayCutout inner,
+            int displayWidth, int displayHeight) {
+        if (inner == DisplayCutout.NO_CUTOUT || inner.isBoundsEmpty()) {
+            return null;
+        }
+
+        final Size displaySize = new Size(displayWidth, displayHeight);
+        final Rect safeInsets = computeSafeInsets(displaySize, inner);
+        return inner.replaceSafeInsets(safeInsets);
+    }
+
+    private static Rect computeSafeInsets(Size displaySize, DisplayCutout cutout) {
+        if (displaySize.getWidth() < displaySize.getHeight()) {
+            final List<Rect> boundingRects = cutout.replaceSafeInsets(
+                    new Rect(0, displaySize.getHeight() / 2, 0, displaySize.getHeight() / 2))
+                    .getBoundingRects();
+            int topInset = findInsetForSide(displaySize, boundingRects, Gravity.TOP);
+            int bottomInset = findInsetForSide(displaySize, boundingRects, Gravity.BOTTOM);
+            return new Rect(0, topInset, 0, bottomInset);
+        } else if (displaySize.getWidth() > displaySize.getHeight()) {
+            final List<Rect> boundingRects = cutout.replaceSafeInsets(
+                    new Rect(displaySize.getWidth() / 2, 0, displaySize.getWidth() / 2, 0))
+                    .getBoundingRects();
+            int leftInset = findInsetForSide(displaySize, boundingRects, Gravity.LEFT);
+            int right = findInsetForSide(displaySize, boundingRects, Gravity.RIGHT);
+            return new Rect(leftInset, 0, right, 0);
+        } else {
+            throw new UnsupportedOperationException("not implemented: display=" + displaySize
+                    + " cutout=" + cutout);
+        }
+    }
+
+    private static int findInsetForSide(Size display, List<Rect> boundingRects, int gravity) {
+        int inset = 0;
+        final int size = boundingRects.size();
+        for (int i = 0; i < size; i++) {
+            Rect boundingRect = boundingRects.get(i);
+            switch (gravity) {
+                case Gravity.TOP:
+                    if (boundingRect.top == 0) {
+                        inset = Math.max(inset, boundingRect.bottom);
+                    }
+                    break;
+                case Gravity.BOTTOM:
+                    if (boundingRect.bottom == display.getHeight()) {
+                        inset = Math.max(inset, display.getHeight() - boundingRect.top);
+                    }
+                    break;
+                case Gravity.LEFT:
+                    if (boundingRect.left == 0) {
+                        inset = Math.max(inset, boundingRect.right);
+                    }
+                    break;
+                case Gravity.RIGHT:
+                    if (boundingRect.right == display.getWidth()) {
+                        inset = Math.max(inset, display.getWidth() - boundingRect.left);
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("unknown gravity: " + gravity);
+            }
+        }
+        return inset;
+    }
+
+    static boolean hasNavigationBar(DisplayInfo info, Context context, int displayId) {
+        if (displayId == Display.DEFAULT_DISPLAY) {
+            // Allow a system property to override this. Used by the emulator.
+            final String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
+            if ("1".equals(navBarOverride)) {
+                return false;
+            } else if ("0".equals(navBarOverride)) {
+                return true;
+            }
+            return context.getResources().getBoolean(R.bool.config_showNavigationBar);
+        } else {
+            boolean isUntrustedVirtualDisplay = info.type == Display.TYPE_VIRTUAL
+                    && info.ownerUid != SYSTEM_UID;
+            final ContentResolver resolver = context.getContentResolver();
+            boolean forceDesktopOnExternal = Settings.Global.getInt(resolver,
+                    DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
+
+            return ((info.flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
+                    || (forceDesktopOnExternal && !isUntrustedVirtualDisplay));
+            // TODO(b/142569966): make sure VR2D and DisplayWindowSettings are moved here somehow.
+        }
+    }
+
+    static boolean hasStatusBar(int displayId) {
+        return displayId == Display.DEFAULT_DISPLAY;
+    }
+
+    /** Retrieve navigation bar position from resources based on rotation and size. */
+    public static int navigationBarPosition(Resources res, int displayWidth, int displayHeight,
+            int rotation) {
+        boolean navBarCanMove = displayWidth != displayHeight && res.getBoolean(
+                com.android.internal.R.bool.config_navBarCanMove);
+        if (navBarCanMove && displayWidth > displayHeight) {
+            if (rotation == Surface.ROTATION_90) {
+                return NAV_BAR_RIGHT;
+            } else {
+                return NAV_BAR_LEFT;
+            }
+        }
+        return NAV_BAR_BOTTOM;
+    }
+
+    /** Retrieve navigation bar size from resources based on side/orientation/ui-mode */
+    public static int getNavigationBarSize(Resources res, int navBarSide, boolean landscape,
+            int uiMode) {
+        final boolean carMode = (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR;
+        if (carMode) {
+            if (navBarSide == NAV_BAR_BOTTOM) {
+                return res.getDimensionPixelSize(landscape
+                        ? R.dimen.navigation_bar_height_landscape_car_mode
+                        : R.dimen.navigation_bar_height_car_mode);
+            } else {
+                return res.getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
+            }
+        } else {
+            if (navBarSide == NAV_BAR_BOTTOM) {
+                return res.getDimensionPixelSize(landscape
+                        ? R.dimen.navigation_bar_height_landscape
+                        : R.dimen.navigation_bar_height);
+            } else {
+                return res.getDimensionPixelSize(R.dimen.navigation_bar_width);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
index 19fff79..ae82115 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
@@ -16,16 +16,20 @@
 
 package com.android.systemui.wm;
 
+import android.annotation.Nullable;
+import android.content.Context;
 import android.content.res.Configuration;
+import android.hardware.display.DisplayManager;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.IDisplayWindowListener;
 import android.view.IDisplayWindowRotationCallback;
 import android.view.IDisplayWindowRotationController;
+import android.view.IWindowManager;
 import android.view.WindowContainerTransaction;
-import android.view.WindowManagerGlobal;
 
 import com.android.systemui.dagger.qualifiers.MainHandler;
 
@@ -45,6 +49,8 @@
     private static final String TAG = "DisplayWindowController";
 
     private final Handler mHandler;
+    private final Context mContext;
+    private final IWindowManager mWmService;
 
     private final ArrayList<OnDisplayWindowRotationController> mRotationControllers =
             new ArrayList<>();
@@ -76,6 +82,14 @@
                 }
             };
 
+    /**
+     * Get's a display by id from DisplayManager.
+     */
+    public Display getDisplay(int displayId) {
+        final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+        return displayManager.getDisplay(displayId);
+    }
+
     private final IDisplayWindowListener mDisplayContainerListener =
             new IDisplayWindowListener.Stub() {
                 @Override
@@ -87,6 +101,10 @@
                             }
                             DisplayRecord record = new DisplayRecord();
                             record.mDisplayId = displayId;
+                            Display display = getDisplay(displayId);
+                            record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
+                                    : mContext.createDisplayContext(display);
+                            record.mDisplayLayout = new DisplayLayout(record.mContext, display);
                             mDisplays.put(displayId, record);
                             for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
                                 mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
@@ -105,6 +123,13 @@
                                         + " display.");
                                 return;
                             }
+                            Display display = getDisplay(displayId);
+                            Context perDisplayContext = mContext;
+                            if (displayId != Display.DEFAULT_DISPLAY) {
+                                perDisplayContext = mContext.createDisplayContext(display);
+                            }
+                            dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
+                            dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
                             for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
                                 mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
                                         displayId, newConfig);
@@ -127,19 +152,36 @@
             };
 
     @Inject
-    public DisplayWindowController(@MainHandler Handler mainHandler) {
+    public DisplayWindowController(Context context, @MainHandler Handler mainHandler,
+            IWindowManager wmService) {
         mHandler = mainHandler;
+        mContext = context;
+        mWmService = wmService;
         try {
-            WindowManagerGlobal.getWindowManagerService().registerDisplayWindowListener(
-                    mDisplayContainerListener);
-            WindowManagerGlobal.getWindowManagerService().setDisplayWindowRotationController(
-                    mDisplayRotationController);
+            mWmService.registerDisplayWindowListener(mDisplayContainerListener);
+            mWmService.setDisplayWindowRotationController(mDisplayRotationController);
         } catch (RemoteException e) {
             throw new RuntimeException("Unable to register hierarchy listener");
         }
     }
 
     /**
+     * Gets the DisplayLayout associated with a display.
+     */
+    public @Nullable DisplayLayout getDisplayLayout(int displayId) {
+        final DisplayRecord r = mDisplays.get(displayId);
+        return r != null ? r.mDisplayLayout : null;
+    }
+
+    /**
+     * Gets a display-specific context for a display.
+     */
+    public @Nullable Context getDisplayContext(int displayId) {
+        final DisplayRecord r = mDisplays.get(displayId);
+        return r != null ? r.mContext : null;
+    }
+
+    /**
      * Add a display window-container listener. It will get notified whenever a display's
      * configuration changes or when displays are added/removed from the WM hierarchy.
      */
@@ -184,6 +226,8 @@
 
     private static class DisplayRecord {
         int mDisplayId;
+        Context mContext;
+        DisplayLayout mDisplayLayout;
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wm/DisplayLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/wm/DisplayLayoutTest.java
new file mode 100644
index 0000000..9596a73
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/wm/DisplayLayoutTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.wm;
+
+import static android.content.res.Configuration.UI_MODE_TYPE_NORMAL;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.view.DisplayCutout;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+
+@SmallTest
+public class DisplayLayoutTest extends SysuiTestCase {
+
+    @Test
+    public void testInsets() {
+        Resources res = createResources(40, 50, false, 30, 40);
+        // Test empty display, no bars or anything
+        DisplayInfo info = createDisplayInfo(1000, 1500, 0, ROTATION_0);
+        DisplayLayout dl = new DisplayLayout(info, res, false, false);
+        assertEquals(new Rect(0, 0, 0, 0), dl.stableInsets());
+        assertEquals(new Rect(0, 0, 0, 0), dl.nonDecorInsets());
+
+        // Test with bars
+        dl = new DisplayLayout(info, res, true, true);
+        assertEquals(new Rect(0, 40, 0, 50), dl.stableInsets());
+        assertEquals(new Rect(0, 0, 0, 50), dl.nonDecorInsets());
+
+        // Test just cutout
+        info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
+        dl = new DisplayLayout(info, res, false, false);
+        assertEquals(new Rect(0, 60, 0, 0), dl.stableInsets());
+        assertEquals(new Rect(0, 60, 0, 0), dl.nonDecorInsets());
+
+        // Test with bars and cutout
+        dl = new DisplayLayout(info, res, true, true);
+        assertEquals(new Rect(0, 60, 0, 50), dl.stableInsets());
+        assertEquals(new Rect(0, 60, 0, 50), dl.nonDecorInsets());
+    }
+
+    @Test
+    public void testRotate() {
+        // Basic rotate utility
+        Rect testParent = new Rect(0, 0, 1000, 600);
+        Rect testInner = new Rect(40, 20, 120, 80);
+        Rect testResult = new Rect(testInner);
+        DisplayLayout.rotateBounds(testResult, testParent, 1);
+        assertEquals(new Rect(20, 880, 80, 960), testResult);
+        testResult.set(testInner);
+        DisplayLayout.rotateBounds(testResult, testParent, 2);
+        assertEquals(new Rect(880, 20, 960, 80), testResult);
+        testResult.set(testInner);
+        DisplayLayout.rotateBounds(testResult, testParent, 3);
+        assertEquals(new Rect(520, 40, 580, 120), testResult);
+
+        Resources res = createResources(40, 50, false, 30, 40);
+        DisplayInfo info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
+        DisplayLayout dl = new DisplayLayout(info, res, true, true);
+        assertEquals(new Rect(0, 60, 0, 50), dl.stableInsets());
+        assertEquals(new Rect(0, 60, 0, 50), dl.nonDecorInsets());
+
+        // Rotate to 90
+        dl.rotateTo(res, ROTATION_90);
+        assertEquals(new Rect(60, 30, 0, 40), dl.stableInsets());
+        assertEquals(new Rect(60, 0, 0, 40), dl.nonDecorInsets());
+
+        // Rotate with moving navbar
+        res = createResources(40, 50, true, 30, 40);
+        dl = new DisplayLayout(info, res, true, true);
+        dl.rotateTo(res, ROTATION_270);
+        assertEquals(new Rect(40, 30, 60, 0), dl.stableInsets());
+        assertEquals(new Rect(40, 0, 60, 0), dl.nonDecorInsets());
+    }
+
+    private Resources createResources(
+            int navLand, int navPort, boolean navMoves, int statusLand, int statusPort) {
+        Configuration cfg = new Configuration();
+        cfg.uiMode = UI_MODE_TYPE_NORMAL;
+        Resources res = mock(Resources.class);
+        doReturn(navLand).when(res).getDimensionPixelSize(
+                R.dimen.navigation_bar_height_landscape_car_mode);
+        doReturn(navPort).when(res).getDimensionPixelSize(R.dimen.navigation_bar_height_car_mode);
+        doReturn(navLand).when(res).getDimensionPixelSize(R.dimen.navigation_bar_width_car_mode);
+        doReturn(navLand).when(res).getDimensionPixelSize(R.dimen.navigation_bar_height_landscape);
+        doReturn(navPort).when(res).getDimensionPixelSize(R.dimen.navigation_bar_height);
+        doReturn(navLand).when(res).getDimensionPixelSize(R.dimen.navigation_bar_width);
+        doReturn(navMoves).when(res).getBoolean(R.bool.config_navBarCanMove);
+        doReturn(statusLand).when(res).getDimensionPixelSize(R.dimen.status_bar_height_landscape);
+        doReturn(statusPort).when(res).getDimensionPixelSize(R.dimen.status_bar_height_portrait);
+        doReturn(cfg).when(res).getConfiguration();
+        return res;
+    }
+
+    private DisplayInfo createDisplayInfo(int width, int height, int cutoutHeight, int rotation) {
+        DisplayInfo info = new DisplayInfo();
+        info.logicalWidth = width;
+        info.logicalHeight = height;
+        info.rotation = rotation;
+        if (cutoutHeight > 0) {
+            info.displayCutout = new DisplayCutout(
+                    Insets.of(0, cutoutHeight, 0, 0) /* safeInsets */, null /* boundLeft */,
+                    new Rect(width / 2 - cutoutHeight, 0, width / 2 + cutoutHeight,
+                            cutoutHeight) /* boundTop */, null /* boundRight */,
+                    null /* boundBottom */);
+        } else {
+            info.displayCutout = DisplayCutout.NO_CUTOUT;
+        }
+        info.logicalDensityDpi = 300;
+        return info;
+    }
+}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index b560761..6bc117b 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -1313,7 +1313,8 @@
         // only CarrierService with carrier privilege rule should have the permission
         int[] subIds = Arrays.stream(SubscriptionManager.from(mContext)
                     .getActiveSubscriptionIdList(false))
-                    .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(i)).toArray();
+                    .filter(i -> TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext,
+                            i)).toArray();
         if (ArrayUtils.isEmpty(subIds)) {
             loge("notifyCarrierNetworkChange without carrier privilege");
             // the active subId does not have carrier privilege.
@@ -2304,7 +2305,7 @@
             return;
         }
 
-        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mContext,
                 SubscriptionManager.getDefaultSubscriptionId(), method);
     }
 
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
index d1e09db..f41c364 100644
--- a/services/core/java/com/android/server/am/LmkdConnection.java
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -18,6 +18,7 @@
 
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
 import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
@@ -35,9 +36,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.TimeUnit;
 
 /**
  * Lmkd connection to communicate with lowmemorykiller daemon.
@@ -46,7 +44,7 @@
     private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;
 
     // lmkd reply max size in bytes
-    private static final int LMKD_REPLY_MAX_SIZE = 8;
+    private static final int LMKD_REPLY_MAX_SIZE = 12;
 
     // connection listener interface
     interface LmkdConnectionListener {
@@ -64,6 +62,15 @@
          */
         public boolean isReplyExpected(ByteBuffer replyBuf, ByteBuffer dataReceived,
             int receivedLen);
+
+        /**
+         * Handle the received message if it's unsolicited.
+         *
+         * @param dataReceived The buffer holding received data
+         * @param receivedLen Size of the data received
+         * @return True if the message has been handled correctly, false otherwise.
+         */
+        boolean handleUnsolicitedMessage(ByteBuffer dataReceived, int receivedLen);
     }
 
     private final MessageQueue mMsgQueue;
@@ -187,17 +194,17 @@
                         mReplyBuf.rewind();
                         // wakeup the waiting thread
                         mReplyBufLock.notifyAll();
-                    } else {
-                        // received asynchronous or unexpected packet
+                    } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
+                        // received unexpected packet
                         // treat this as an error
                         mReplyBuf = null;
                         mReplyBufLock.notifyAll();
-                        Slog.e(TAG, "Received unexpected packet from lmkd");
+                        Slog.e(TAG, "Received an unexpected packet from lmkd");
                     }
-                } else {
+                } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
                     // received asynchronous communication from lmkd
-                    // we don't support this yet
-                    Slog.w(TAG, "Received an asynchronous packet from lmkd");
+                    // but we don't recognize it.
+                    Slog.w(TAG, "Received an unexpected packet from lmkd");
                 }
             }
         }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 209b1d2..5378f43 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -278,14 +278,16 @@
     // LMK_PROCREMOVE <pid>
     // LMK_PROCPURGE
     // LMK_GETKILLCNT
+    // LMK_PROCKILL
     static final byte LMK_TARGET = 0;
     static final byte LMK_PROCPRIO = 1;
     static final byte LMK_PROCREMOVE = 2;
     static final byte LMK_PROCPURGE = 3;
     static final byte LMK_GETKILLCNT = 4;
+    static final byte LMK_PROCKILL = 5; // Note: this is an unsolicated command
 
     // lmkd reconnect delay in msecs
-    private final static long LMDK_RECONNECT_DELAY_MS = 1000;
+    private static final long LMKD_RECONNECT_DELAY_MS = 1000;
 
     /**
      * How long between a process kill and we actually receive its death recipient
@@ -391,6 +393,12 @@
     ActiveUids mActiveUids;
 
     /**
+     * The listener who is intereted with the lmkd kills.
+     */
+    @GuardedBy("mService")
+    private LmkdKillListener mLmkdKillListener = null;
+
+    /**
      * The currently running isolated processes.
      */
     final SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<>();
@@ -408,6 +416,13 @@
 
     private PlatformCompat mPlatformCompat = null;
 
+    interface LmkdKillListener {
+        /**
+         * Called when there is a process kill by lmkd.
+         */
+        void onLmkdKillOccurred(int pid, int uid);
+    }
+
     final class IsolatedUidRange {
         @VisibleForTesting
         public final int mFirstUid;
@@ -560,7 +575,8 @@
 
     final class KillHandler extends Handler {
         static final int KILL_PROCESS_GROUP_MSG = 4000;
-        static final int LMDK_RECONNECT_MSG = 4001;
+        static final int LMKD_RECONNECT_MSG = 4001;
+        static final int LMKD_PROC_KILLED_MSG = 4002;
 
         public KillHandler(Looper looper) {
             super(looper, null, true);
@@ -574,15 +590,18 @@
                     Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
-                case LMDK_RECONNECT_MSG:
+                case LMKD_RECONNECT_MSG:
                     if (!sLmkdConnection.connect()) {
                         Slog.i(TAG, "Failed to connect to lmkd, retry after " +
-                                LMDK_RECONNECT_DELAY_MS + " ms");
-                        // retry after LMDK_RECONNECT_DELAY_MS
+                                LMKD_RECONNECT_DELAY_MS + " ms");
+                        // retry after LMKD_RECONNECT_DELAY_MS
                         sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
-                                KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
+                                KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
                     }
                     break;
+                case LMKD_PROC_KILLED_MSG:
+                    handleLmkdProcKilled(msg.arg1 /* pid */, msg.arg2 /* uid */);
+                    break;
 
                 default:
                     super.handleMessage(msg);
@@ -623,7 +642,7 @@
                             Slog.w(TAG, "Lost connection to lmkd");
                             // start reconnection after delay to let lmkd restart
                             sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
-                                    KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
+                                    KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
                         }
 
                         @Override
@@ -634,6 +653,26 @@
                             return (receivedLen == replyBuf.array().length &&
                                     dataReceived.getInt(0) == replyBuf.getInt(0));
                         }
+
+                        @Override
+                        public boolean handleUnsolicitedMessage(ByteBuffer dataReceived,
+                                int receivedLen) {
+                            if (receivedLen < 4) {
+                                return false;
+                            }
+                            switch (dataReceived.getInt(0)) {
+                                case LMK_PROCKILL:
+                                    if (receivedLen != 12) {
+                                        return false;
+                                    }
+                                    sKillHandler.obtainMessage(KillHandler.LMKD_PROC_KILLED_MSG,
+                                            dataReceived.getInt(4), dataReceived.getInt(8))
+                                            .sendToTarget();
+                                    return true;
+                                default:
+                                    return false;
+                            }
+                        }
                     }
             );
         }
@@ -1310,10 +1349,10 @@
         if (!sLmkdConnection.isConnected()) {
             // try to connect immediately and then keep retrying
             sKillHandler.sendMessage(
-                sKillHandler.obtainMessage(KillHandler.LMDK_RECONNECT_MSG));
+                    sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG));
 
             // wait for connection retrying 3 times (up to 3 seconds)
-            if (!sLmkdConnection.waitForConnection(3 * LMDK_RECONNECT_DELAY_MS)) {
+            if (!sLmkdConnection.waitForConnection(3 * LMKD_RECONNECT_DELAY_MS)) {
                 return false;
             }
         }
@@ -3405,4 +3444,28 @@
             }
         }
     }
+
+    void setLmkdKillListener(final LmkdKillListener listener) {
+        synchronized (mService) {
+            mLmkdKillListener = listener;
+        }
+    }
+
+    private void handleLmkdProcKilled(final int pid, final int uid) {
+        // Log only now
+        if (DEBUG_PROCESSES) {
+            Slog.i(TAG, "lmkd kill: pid=" + pid + " uid=" + uid);
+        }
+
+        if (mService == null) {
+            return;
+        }
+        // Notify any interesed party regarding the lmkd kills
+        synchronized (mService) {
+            final LmkdKillListener listener = mLmkdKillListener;
+            if (listener != null) {
+                mService.mHandler.post(()-> listener.onLmkdKillOccurred(pid, uid));
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 366766e..14f9654 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -20,6 +20,7 @@
 import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
 import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
 import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_COARSE_LOCATION;
 import static android.app.AppOpsManager.OP_FLAGS_ALL;
 import static android.app.AppOpsManager.OP_NONE;
 import static android.app.AppOpsManager.OP_PLAY_AUDIO;
@@ -1642,6 +1643,13 @@
             return;
         }
 
+        // STOPSHIP: Remove this check once we are sure no one is doing it.
+        if (code == OP_COARSE_LOCATION && mode != AppOpsManager.opToDefaultMode(code)) {
+            Slog.wtf(TAG, "Trying to setMode() instead of setUidMode(), " + "code=" + code
+                    + ", uid=" + uid + ", packageName=" + packageName + ", mode=" + mode
+                    + ", callingUid=" + Binder.getCallingUid(), new RuntimeException());
+        }
+
         synchronized (this) {
             UidState uidState = getUidStateLocked(uid, false);
             Op op = getOpLocked(code, uid, packageName, isPrivileged, true);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 661451b..9061586 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -68,9 +68,6 @@
 
     private @NonNull AudioDeviceBroker mDeviceBroker;
 
-    // cache of the address of the last dock the device was connected to
-    private String mDockAddress;
-
     // Monitoring of audio routes.  Protected by mAudioRoutes.
     final AudioRoutesInfo mCurAudioRoutes = new AudioRoutesInfo();
     final RemoteCallbackList<IAudioRoutesObserver> mRoutesObservers =
@@ -187,7 +184,7 @@
         int a2dpVolume = btInfo.getVolume();
         if (AudioService.DEBUG_DEVICES) {
             Log.d(TAG, "onSetA2dpSinkConnectionState btDevice=" + btDevice + " state="
-                    + state + " is dock=" + btDevice.isBluetoothDock() + " vol=" + a2dpVolume);
+                    + state + " vol=" + a2dpVolume);
         }
         String address = btDevice.getAddress();
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
@@ -215,42 +212,17 @@
                         mDeviceBroker.postBluetoothA2dpDeviceConfigChange(btDevice);
                     }
                 } else {
-                    if (btDevice.isBluetoothDock()) {
-                        if (state == BluetoothProfile.STATE_DISCONNECTED) {
-                            // introduction of a delay for transient disconnections of docks when
-                            // power is rapidly turned off/on, this message will be canceled if
-                            // we reconnect the dock under a preset delay
-                            makeA2dpDeviceUnavailableLater(address,
-                                    AudioDeviceBroker.BTA2DP_DOCK_TIMEOUT_MS);
-                            // the next time isConnected is evaluated, it will be false for the dock
-                        }
-                    } else {
-                        makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
-                    }
+                    makeA2dpDeviceUnavailableNow(address, di.mDeviceCodecFormat);
                 }
-            } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                if (btDevice.isBluetoothDock()) {
-                    // this could be a reconnection after a transient disconnection
-                    mDeviceBroker.cancelA2dpDockTimeout();
-                    mDockAddress = address;
-                } else {
-                    // this could be a connection of another A2DP device before the timeout of
-                    // a dock: cancel the dock timeout, and make the dock unavailable now
-                    if (mDeviceBroker.hasScheduledA2dpDockTimeout() && mDockAddress != null) {
-                        mDeviceBroker.cancelA2dpDockTimeout();
-                        makeA2dpDeviceUnavailableNow(mDockAddress,
-                                AudioSystem.AUDIO_FORMAT_DEFAULT);
-                    }
-                }
-                if (a2dpVolume != -1) {
-                    mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
-                            // convert index to internal representation in VolumeStreamState
-                            a2dpVolume * 10,
-                            AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
-                }
-                makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
-                        "onSetA2dpSinkConnectionState", a2dpCodec);
             }
+            if (a2dpVolume != -1) {
+                mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
+                        // convert index to internal representation in VolumeStreamState
+                        a2dpVolume * 10,
+                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, "onSetA2dpSinkConnectionState");
+            }
+            makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
+                    "onSetA2dpSinkConnectionState", a2dpCodec);
         }
     }
 
@@ -723,9 +695,6 @@
                 DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
         // Remove A2DP routes as well
         setCurrentAudioRouteNameIfPossible(null);
-        if (mDockAddress == address) {
-            mDockAddress = null;
-        }
     }
 
     @GuardedBy("mConnectedDevices")
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index c54fbd6..e199b2887 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -1144,6 +1144,7 @@
 
         // Trim the set of tasks to the active set
         trimInactiveRecentTasks();
+        notifyTaskPersisterLocked(task, false /* flush */);
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index b1cd931..09d7b54 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -41,8 +41,12 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -112,6 +116,7 @@
     @Before
     public void setUp() throws Exception {
         mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
+        spyOn(mTaskPersister);
         mDisplay = mRootActivityContainer.getActivityDisplay(DEFAULT_DISPLAY);
 
         // Set the recent tasks we should use for testing in this class.
@@ -171,6 +176,46 @@
     }
 
     @Test
+    public void testPersister() {
+        // Add some tasks, ensure the persister is woken
+        mRecentTasks.add(mTasks.get(0));
+        mRecentTasks.add(mTasks.get(1));
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(0)), anyBoolean());
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(1)), anyBoolean());
+        reset(mTaskPersister);
+
+        // Update a task, ensure the persister is woken
+        mRecentTasks.add(mTasks.get(0));
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(0)), anyBoolean());
+        reset(mTaskPersister);
+
+        // Remove some tasks, ensure the persister is woken
+        mRecentTasks.remove(mTasks.get(0));
+        mRecentTasks.remove(mTasks.get(1));
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(0)), anyBoolean());
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(1)), anyBoolean());
+        reset(mTaskPersister);
+    }
+
+    @Test
+    public void testPersisterTrimmed() {
+        mRecentTasks.setOnlyTestVisibleRange();
+
+        // Limit the global maximum number of recent tasks to a fixed size
+        mRecentTasks.setGlobalMaxNumTasks(1 /* globalMaxNumTasks */);
+
+        mRecentTasks.add(mTasks.get(0));
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(0)), anyBoolean());
+        reset(mTaskPersister);
+
+        // Add N+1 tasks to ensure the previous task is trimmed
+        mRecentTasks.add(mTasks.get(1));
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(0)), anyBoolean());
+        verify(mTaskPersister, times(1)).wakeup(eq(mTasks.get(1)), anyBoolean());
+        assertTrimmed(mTasks.get(0));
+    }
+
+    @Test
     public void testAddTasksNoMultiple_expectNoTrim() {
         // Add same non-multiple-task document tasks will remove the task (to re-add it) but not
         // trim it
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 735b9a1..198b4c3 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -16,11 +16,14 @@
 
 package com.android.server.soundtrigger;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.ModelParams;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.GenericRecognitionEvent;
 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
@@ -28,6 +31,7 @@
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionEvent;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionEvent;
@@ -605,6 +609,67 @@
         return STATUS_ERROR;
     }
 
+    int setParameter(UUID modelId, @ModelParams int modelParam, int value) {
+        synchronized (mLock) {
+            MetricsLogger.count(mContext, "sth_set_parameter", 1);
+            if (modelId == null || mModule == null) {
+                return SoundTrigger.STATUS_ERROR;
+            }
+            ModelData modelData = mModelDataMap.get(modelId);
+            if (modelData == null) {
+                Slog.w(TAG, "SetParameter: Invalid model id:" + modelId);
+                return SoundTrigger.STATUS_BAD_VALUE;
+            }
+            if (!modelData.isModelLoaded()) {
+                Slog.i(TAG, "SetParameter: Given model is not loaded:" + modelId);
+                return SoundTrigger.STATUS_BAD_VALUE;
+            }
+
+            return mModule.setParameter(modelData.getHandle(), modelParam, value);
+        }
+    }
+
+    int getParameter(@NonNull UUID modelId, @ModelParams int modelParam)
+            throws UnsupportedOperationException, IllegalArgumentException {
+        synchronized (mLock) {
+            MetricsLogger.count(mContext, "sth_get_parameter", 1);
+            if (mModule == null) {
+                throw new UnsupportedOperationException("SoundTriggerModule not initialized");
+            }
+
+            ModelData modelData = mModelDataMap.get(modelId);
+            if (modelData == null) {
+                throw new IllegalArgumentException("Invalid model id:" + modelId);
+            }
+            if (!modelData.isModelLoaded()) {
+                throw new UnsupportedOperationException("Given model is not loaded:" + modelId);
+            }
+
+            return mModule.getParameter(modelData.getHandle(), modelParam);
+        }
+    }
+
+    @Nullable
+    ModelParamRange queryParameter(@NonNull UUID modelId, @ModelParams int modelParam) {
+        synchronized (mLock) {
+            MetricsLogger.count(mContext, "sth_query_parameter", 1);
+            if (mModule == null) {
+                return null;
+            }
+            ModelData modelData = mModelDataMap.get(modelId);
+            if (modelData == null) {
+                Slog.w(TAG, "queryParameter: Invalid model id:" + modelId);
+                return null;
+            }
+            if (!modelData.isModelLoaded()) {
+                Slog.i(TAG, "queryParameter: Given model is not loaded:" + modelId);
+                return null;
+            }
+
+            return mModule.queryParameter(modelData.getHandle(), modelParam);
+        }
+    }
+
     //---- SoundTrigger.StatusListener methods
     @Override
     public void onRecognition(RecognitionEvent event) {
@@ -653,15 +718,15 @@
         }
         ModelData model = getModelDataForLocked(event.soundModelHandle);
         if (model == null || !model.isGenericModel()) {
-            Slog.w(TAG, "Generic recognition event: Model does not exist for handle: " +
-                    event.soundModelHandle);
+            Slog.w(TAG, "Generic recognition event: Model does not exist for handle: "
+                    + event.soundModelHandle);
             return;
         }
 
         IRecognitionStatusCallback callback = model.getCallback();
         if (callback == null) {
-            Slog.w(TAG, "Generic recognition event: Null callback for model handle: " +
-                    event.soundModelHandle);
+            Slog.w(TAG, "Generic recognition event: Null callback for model handle: "
+                    + event.soundModelHandle);
             return;
         }
 
@@ -678,8 +743,8 @@
 
         RecognitionConfig config = model.getRecognitionConfig();
         if (config == null) {
-            Slog.w(TAG, "Generic recognition event: Null RecognitionConfig for model handle: " +
-                    event.soundModelHandle);
+            Slog.w(TAG, "Generic recognition event: Null RecognitionConfig for model handle: "
+                    + event.soundModelHandle);
             return;
         }
 
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 1dd3972..96d2df1 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -22,7 +22,9 @@
 import static android.content.pm.PackageManager.GET_META_DATA;
 import static android.content.pm.PackageManager.GET_SERVICES;
 import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
+import static android.hardware.soundtrigger.SoundTrigger.STATUS_BAD_VALUE;
 import static android.hardware.soundtrigger.SoundTrigger.STATUS_ERROR;
+import static android.hardware.soundtrigger.SoundTrigger.STATUS_NO_INIT;
 import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK;
 import static android.provider.Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY;
 import static android.provider.Settings.Global.SOUND_TRIGGER_DETECTION_SERVICE_OP_TIMEOUT;
@@ -39,9 +41,11 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
+import android.hardware.soundtrigger.ModelParams;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.hardware.soundtrigger.SoundTrigger.GenericSoundModel;
 import android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel;
+import android.hardware.soundtrigger.SoundTrigger.ModelParamRange;
 import android.hardware.soundtrigger.SoundTrigger.ModuleProperties;
 import android.hardware.soundtrigger.SoundTrigger.RecognitionConfig;
 import android.hardware.soundtrigger.SoundTrigger.SoundModel;
@@ -683,6 +687,101 @@
                 return properties;
             }
         }
+
+        @Override
+        public int setParameter(ParcelUuid soundModelId,
+                @ModelParams int modelParam, int value) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (!isInitialized()) return STATUS_NO_INIT;
+            if (DEBUG) {
+                Slog.d(TAG, "setParameter(): id=" + soundModelId
+                        + ", param=" + modelParam
+                        + ", value=" + value);
+            }
+
+            sEventLogger.log(new SoundTriggerLogger.StringEvent(
+                    "setParameter(): id=" + soundModelId
+                            + ", param=" + modelParam
+                            + ", value=" + value));
+
+            synchronized (mLock) {
+                SoundModel soundModel = mLoadedModels.get(soundModelId.getUuid());
+                if (soundModel == null) {
+                    Slog.e(TAG, soundModelId + " is not loaded. Loaded models: "
+                            + mLoadedModels.toString());
+
+                    sEventLogger.log(new SoundTriggerLogger.StringEvent("setParameter(): "
+                            + soundModelId + " is not loaded"));
+
+                    return STATUS_BAD_VALUE;
+                }
+
+                return mSoundTriggerHelper.setParameter(soundModel.uuid, modelParam, value);
+            }
+        }
+
+        @Override
+        public int getParameter(@NonNull ParcelUuid soundModelId,
+                @ModelParams int modelParam)
+                throws UnsupportedOperationException, IllegalArgumentException {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (!isInitialized()) {
+                throw new UnsupportedOperationException("SoundTriggerHelper not initialized");
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "getParameter(): id=" + soundModelId
+                        + ", param=" + modelParam);
+            }
+
+            sEventLogger.log(new SoundTriggerLogger.StringEvent(
+                    "getParameter(): id=" + soundModelId
+                            + ", param=" + modelParam));
+
+            synchronized (mLock) {
+                SoundModel soundModel = mLoadedModels.get(soundModelId.getUuid());
+                if (soundModel == null) {
+                    Slog.e(TAG, soundModelId + " is not loaded");
+
+                    sEventLogger.log(new SoundTriggerLogger.StringEvent("getParameter(): "
+                            + soundModelId + " is not loaded"));
+
+                    throw new IllegalArgumentException("sound model is not loaded");
+                }
+
+                return mSoundTriggerHelper.getParameter(soundModel.uuid, modelParam);
+            }
+        }
+
+        @Override
+        @Nullable
+        public ModelParamRange queryParameter(@NonNull ParcelUuid soundModelId,
+                @ModelParams int modelParam) {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (!isInitialized()) return null;
+            if (DEBUG) {
+                Slog.d(TAG, "queryParameter(): id=" + soundModelId
+                        + ", param=" + modelParam);
+            }
+
+            sEventLogger.log(new SoundTriggerLogger.StringEvent(
+                    "queryParameter(): id=" + soundModelId
+                            + ", param=" + modelParam));
+
+            synchronized (mLock) {
+                SoundModel soundModel = mLoadedModels.get(soundModelId.getUuid());
+                if (soundModel == null) {
+                    Slog.e(TAG, soundModelId + " is not loaded");
+
+                    sEventLogger.log(new SoundTriggerLogger.StringEvent(
+                            "queryParameter(): "
+                                    + soundModelId + " is not loaded"));
+
+                    return null;
+                }
+
+                return mSoundTriggerHelper.queryParameter(soundModel.uuid, modelParam);
+            }
+        }
     }
 
     /**
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 86630b0..4d01e33 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -27,8 +27,6 @@
 import android.os.Binder;
 import android.os.Build;
 import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
@@ -42,7 +40,6 @@
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.Supplier;
 
 /** Utility class for Telephony permission enforcement. */
 public final class TelephonyPermissions {
@@ -50,9 +47,6 @@
 
     private static final boolean DBG = false;
 
-    private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
-            ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
-
     /**
      * Whether to disable the new device identifier access restrictions.
      */
@@ -138,49 +132,6 @@
     public static boolean checkReadPhoneState(
             Context context, int subId, int pid, int uid, String callingPackage,
             @Nullable  String callingFeatureId, String message) {
-        return checkReadPhoneState(
-                context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingFeatureId,
-                message);
-    }
-
-    /**
-     * Check whether the calling packages has carrier privileges for the passing subscription.
-     * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
-     */
-    public static boolean checkCarrierPrivilegeForSubId(int subId) {
-        if (SubscriptionManager.isValidSubscriptionId(subId)
-                && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, Binder.getCallingUid())
-                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Check whether the app with the given pid/uid can read phone state.
-     *
-     * <p>This method behaves in one of the following ways:
-     * <ul>
-     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
-     *       READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
-     *   <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
-     *       apps which support runtime permissions, if the caller does not currently have any of
-     *       these permissions.
-     *   <li>return false: if the caller lacks all of these permissions and doesn't support runtime
-     *       permissions. This implies that the user revoked the ability to read phone state
-     *       manually (via AppOps). In this case we can't throw as it would break app compatibility,
-     *       so we return false to indicate that the calling function should return dummy data.
-     * </ul>
-     *
-     * <p>Note: for simplicity, this method always returns false for callers using legacy
-     * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
-     * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
-     * devices.
-     */
-    @VisibleForTesting
-    public static boolean checkReadPhoneState(
-            Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
-            String callingPackage, @Nullable String callingFeatureId, String message) {
         try {
             context.enforcePermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -195,7 +146,7 @@
                 // If we don't have the runtime permission, but do have carrier privileges, that
                 // suffices for reading phone state.
                 if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                    enforceCarrierPrivilege(telephonySupplier, subId, uid, message);
+                    enforceCarrierPrivilege(context, subId, uid, message);
                     return true;
                 }
                 throw phoneStateException;
@@ -210,6 +161,19 @@
     }
 
     /**
+     * Check whether the calling packages has carrier privileges for the passing subscription.
+     * @return {@code true} if the caller has carrier privileges, {@false} otherwise.
+     */
+    public static boolean checkCarrierPrivilegeForSubId(Context context, int subId) {
+        if (SubscriptionManager.isValidSubscriptionId(subId)
+                && getCarrierPrivilegeStatus(context, subId, Binder.getCallingUid())
+                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Check whether the app with the given pid/uid can read phone state, or has carrier
      * privileges on any active subscription.
      *
@@ -225,28 +189,6 @@
      */
     public static boolean checkReadPhoneStateOnAnyActiveSub(Context context, int pid, int uid,
             String callingPackage, @Nullable String callingFeatureId, String message) {
-        return checkReadPhoneStateOnAnyActiveSub(context, TELEPHONY_SUPPLIER, pid, uid,
-                callingPackage, callingFeatureId, message);
-    }
-
-    /**
-     * Check whether the app with the given pid/uid can read phone state, or has carrier
-     * privileges on any active subscription.
-     *
-     * <p>If the app does not have carrier privilege, this method will return {@code false} instead
-     * of throwing a SecurityException. Therefore, the callers cannot tell the difference
-     * between M+ apps which declare the runtime permission but do not have it, and pre-M apps
-     * which declare the static permission but had access revoked via AppOps. Apps in the former
-     * category expect SecurityExceptions; apps in the latter don't. So this method is suitable for
-     * use only if the behavior in both scenarios is meant to be identical.
-     *
-     * @return {@code true} if the app can read phone state or has carrier privilege;
-     *         {@code false} otherwise.
-     */
-    @VisibleForTesting
-    public static boolean checkReadPhoneStateOnAnyActiveSub(
-            Context context, Supplier<ITelephony> telephonySupplier, int pid, int uid,
-            String callingPackage, @Nullable String callingFeatureId, String message) {
         try {
             context.enforcePermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -260,7 +202,7 @@
             } catch (SecurityException phoneStateException) {
                 // If we don't have the runtime permission, but do have carrier privileges, that
                 // suffices for reading phone state.
-                return checkCarrierPrivilegeForAnySubId(context, telephonySupplier, uid);
+                return checkCarrierPrivilegeForAnySubId(context, uid);
             }
         }
 
@@ -375,12 +317,11 @@
         }
 
         // If the calling package has carrier privileges for specified sub, then allow access.
-        if (checkCarrierPrivilegeForSubId(subId)) return true;
+        if (checkCarrierPrivilegeForSubId(context, subId)) return true;
 
         // If the calling package has carrier privileges for any subscription
         // and allowCarrierPrivilegeOnAnySub is set true, then allow access.
-        if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(
-                context, TELEPHONY_SUPPLIER, uid)) {
+        if (allowCarrierPrivilegeOnAnySub && checkCarrierPrivilegeForAnySubId(context, uid)) {
             return true;
         }
 
@@ -468,7 +409,7 @@
                     uid) == PackageManager.PERMISSION_GRANTED) {
                 return false;
             }
-            if (checkCarrierPrivilegeForSubId(subId)) {
+            if (checkCarrierPrivilegeForSubId(context, subId)) {
                 return false;
             }
         }
@@ -484,26 +425,12 @@
     public static boolean checkReadCallLog(
             Context context, int subId, int pid, int uid, String callingPackage,
             @Nullable String callingPackageName) {
-        return checkReadCallLog(
-                context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, callingPackageName);
-    }
-
-    /**
-     * Check whether the app with the given pid/uid can read the call log.
-     * @return {@code true} if the specified app has the read call log permission and AppOpp granted
-     *      to it, {@code false} otherwise.
-     */
-    @VisibleForTesting
-    public static boolean checkReadCallLog(
-            Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
-            String callingPackage, @Nullable String callingFeatureId) {
-
         if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
                 != PERMISSION_GRANTED) {
             // If we don't have the runtime permission, but do have carrier privileges, that
             // suffices for being able to see the call phone numbers.
             if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog");
+                enforceCarrierPrivilege(context, subId, uid, "readCallLog");
                 return true;
             }
             return false;
@@ -513,7 +440,7 @@
         // revoked.
         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         return appOps.noteOp(AppOpsManager.OPSTR_READ_CALL_LOG, uid, callingPackage,
-                callingFeatureId, null) == AppOpsManager.MODE_ALLOWED;
+                callingPackageName, null) == AppOpsManager.MODE_ALLOWED;
     }
 
     /**
@@ -526,7 +453,7 @@
             Context context, int subId, String callingPackage, @Nullable String callingFeatureId,
             String message) {
         return checkReadPhoneNumber(
-                context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
+                context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
                 callingPackage, callingFeatureId, message);
     }
 
@@ -538,7 +465,7 @@
      */
     @VisibleForTesting
     public static boolean checkReadPhoneNumber(
-            Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+            Context context, int subId, int pid, int uid,
             String callingPackage, @Nullable String callingFeatureId, String message) {
         // Default SMS app can always read it.
         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -553,7 +480,7 @@
         // First, check if we can read the phone state.
         try {
             return checkReadPhoneState(
-                    context, telephonySupplier, subId, pid, uid, callingPackage, callingFeatureId,
+                    context, subId, pid, uid, callingPackage, callingFeatureId,
                     message);
         } catch (SecurityException readPhoneStateSecurityException) {
         }
@@ -595,7 +522,7 @@
         }
 
         if (DBG) Rlog.d(LOG_TAG, "No modify permission, check carrier privilege next.");
-        enforceCallingOrSelfCarrierPrivilege(subId, message);
+        enforceCallingOrSelfCarrierPrivilege(context, subId, message);
     }
 
     /**
@@ -615,7 +542,7 @@
             Rlog.d(LOG_TAG, "No READ_PHONE_STATE permission, check carrier privilege next.");
         }
 
-        enforceCallingOrSelfCarrierPrivilege(subId, message);
+        enforceCallingOrSelfCarrierPrivilege(context, subId, message);
     }
 
     /**
@@ -636,7 +563,7 @@
                     + "check carrier privilege next.");
         }
 
-        enforceCallingOrSelfCarrierPrivilege(subId, message);
+        enforceCallingOrSelfCarrierPrivilege(context, subId, message);
     }
 
     /**
@@ -644,21 +571,18 @@
      *
      * @throws SecurityException if the caller does not have the required privileges
      */
-    public static void enforceCallingOrSelfCarrierPrivilege(int subId, String message) {
+    public static void enforceCallingOrSelfCarrierPrivilege(
+            Context context, int subId, String message) {
         // NOTE: It's critical that we explicitly pass the calling UID here rather than call
         // TelephonyManager#hasCarrierPrivileges directly, as the latter only works when called from
         // the phone process. When called from another process, it will check whether that process
         // has carrier privileges instead.
-        enforceCarrierPrivilege(subId, Binder.getCallingUid(), message);
-    }
-
-    private static void enforceCarrierPrivilege(int subId, int uid, String message) {
-        enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message);
+        enforceCarrierPrivilege(context, subId, Binder.getCallingUid(), message);
     }
 
     private static void enforceCarrierPrivilege(
-            Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) {
-        if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid)
+            Context context, int subId, int uid, String message) {
+        if (getCarrierPrivilegeStatus(context, subId, uid)
                 != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
             if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege.");
             throw new SecurityException(message);
@@ -666,13 +590,12 @@
     }
 
     /** Returns whether the provided uid has carrier privileges for any active subscription ID. */
-    private static boolean checkCarrierPrivilegeForAnySubId(
-            Context context, Supplier<ITelephony> telephonySupplier, int uid) {
+    private static boolean checkCarrierPrivilegeForAnySubId(Context context, int uid) {
         SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         int[] activeSubIds = sm.getActiveSubscriptionIdList(/* visibleOnly */ false);
         for (int activeSubId : activeSubIds) {
-            if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+            if (getCarrierPrivilegeStatus(context, activeSubId, uid)
                     == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
                 return true;
             }
@@ -680,18 +603,10 @@
         return false;
     }
 
-    private static int getCarrierPrivilegeStatus(
-            Supplier<ITelephony> telephonySupplier, int subId, int uid) {
-        ITelephony telephony = telephonySupplier.get();
-        try {
-            if (telephony != null) {
-                return telephony.getCarrierPrivilegeStatusForUid(subId, uid);
-            }
-        } catch (RemoteException e) {
-            // Fallback below.
-        }
-        Rlog.e(LOG_TAG, "Phone process is down, cannot check carrier privileges");
-        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+    private static int getCarrierPrivilegeStatus(Context context, int subId, int uid) {
+        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(
+                Context.TELEPHONY_SERVICE);
+        return telephonyManager.createForSubscriptionId(subId).getCarrierPrivilegeStatus(uid);
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 09de999..5b7ad12 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2441,7 +2441,7 @@
 
     /*
      * When adding a network type to the list below, make sure to add the correct icon to
-     * MobileSignalController.mapIconSets().
+     * MobileSignalController.mapIconSets() as well as NETWORK_TYPES
      * Do not add negative types.
      */
     /** Network type is unknown */
@@ -2489,8 +2489,36 @@
     /** Current network is NR(New Radio) 5G. */
     public static final int NETWORK_TYPE_NR = TelephonyProtoEnums.NETWORK_TYPE_NR; // 20.
 
-    /** Max network type number. Update as new types are added. Don't add negative types. {@hide} */
-    public static final int MAX_NETWORK_TYPE = NETWORK_TYPE_NR;
+    private static final @NetworkType int[] NETWORK_TYPES = {
+            NETWORK_TYPE_GPRS,
+            NETWORK_TYPE_EDGE,
+            NETWORK_TYPE_UMTS,
+            NETWORK_TYPE_CDMA,
+            NETWORK_TYPE_EVDO_0,
+            NETWORK_TYPE_EVDO_A,
+            NETWORK_TYPE_1xRTT,
+            NETWORK_TYPE_HSDPA,
+            NETWORK_TYPE_HSUPA,
+            NETWORK_TYPE_HSPA,
+            NETWORK_TYPE_IDEN,
+            NETWORK_TYPE_EVDO_B,
+            NETWORK_TYPE_LTE,
+            NETWORK_TYPE_EHRPD,
+            NETWORK_TYPE_HSPAP,
+            NETWORK_TYPE_GSM,
+            NETWORK_TYPE_TD_SCDMA,
+            NETWORK_TYPE_IWLAN,
+            NETWORK_TYPE_LTE_CA,
+            NETWORK_TYPE_NR
+    };
+
+    /**
+     * Return a collection of all network types
+     * @return network types
+     */
+    public static @NonNull @NetworkType int[] getAllNetworkTypes() {
+        return NETWORK_TYPES;
+    }
 
     /**
      * Return the current data network type.
@@ -11740,6 +11768,32 @@
     }
 
     /**
+     * Get the calling application status about carrier privileges for the subscription created
+     * in TelephonyManager. Used by Telephony Module for permission checking.
+     *
+     * @param uid Uid to check.
+     * @return any value of {@link #CARRIER_PRIVILEGE_STATUS_HAS_ACCESS},
+     *         {@link #CARRIER_PRIVILEGE_STATUS_NO_ACCESS},
+     *         {@link #CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED}, or
+     *         {@link #CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES}
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public int getCarrierPrivilegeStatus(int uid) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getCarrierPrivilegeStatusForUid(getSubId(), uid);
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "getCarrierPrivilegeStatus RemoteException", ex);
+        }
+        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+    }
+
+    /**
      * Return whether data is enabled for certain APN type. This will tell if framework will accept
      * corresponding network requests on a subId.
      *