Merge "Import translations. DO NOT MERGE"
diff --git a/api/current.txt b/api/current.txt
index 4c88231..87295c8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -40313,7 +40313,7 @@
     method public boolean isHearingAidCompatibilitySupported();
     method public boolean isNetworkRoaming();
     method public boolean isSmsCapable();
-    method public boolean isTtyModeSupported();
+    method public deprecated boolean isTtyModeSupported();
     method public boolean isVoiceCapable();
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
diff --git a/api/system-current.txt b/api/system-current.txt
index 9437dfe..4e05661 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -43756,8 +43756,8 @@
   }
 
   public class TelephonyManager {
-    method public void answerRingingCall();
-    method public void call(java.lang.String, java.lang.String);
+    method public deprecated void answerRingingCall();
+    method public deprecated void call(java.lang.String, java.lang.String);
     method public boolean canChangeDtmfToneLength();
     method public int checkCarrierPrivilegesForPackage(java.lang.String);
     method public int checkCarrierPrivilegesForPackageAnyPhone(java.lang.String);
@@ -43767,7 +43767,7 @@
     method public boolean disableDataConnectivity();
     method public boolean enableDataConnectivity();
     method public void enableVideoCalling(boolean);
-    method public boolean endCall();
+    method public deprecated boolean endCall();
     method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
     method public int getCallState();
@@ -43842,7 +43842,7 @@
     method public boolean isRadioOn();
     method public boolean isRinging();
     method public boolean isSmsCapable();
-    method public boolean isTtyModeSupported();
+    method public deprecated boolean isTtyModeSupported();
     method public boolean isVideoCallingEnabled();
     method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isVoiceCapable();
@@ -43867,7 +43867,7 @@
     method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
     method public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
     method public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
-    method public void silenceRinger();
+    method public deprecated void silenceRinger();
     method public boolean supplyPin(java.lang.String);
     method public int[] supplyPinReportResult(java.lang.String);
     method public boolean supplyPuk(java.lang.String, java.lang.String);
diff --git a/api/test-current.txt b/api/test-current.txt
index 20a15f8..ec912ee 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -40573,7 +40573,7 @@
     method public boolean isHearingAidCompatibilitySupported();
     method public boolean isNetworkRoaming();
     method public boolean isSmsCapable();
-    method public boolean isTtyModeSupported();
+    method public deprecated boolean isTtyModeSupported();
     method public boolean isVoiceCapable();
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 833af1b..6bccad9 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2533,7 +2533,7 @@
      * @return Returns true if the password meets the current requirements, else false.
      * @throws SecurityException if the calling application does not own an active administrator
      *             that uses {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD}
-     * @throws InvalidStateException if the user is not unlocked.
+     * @throws IllegalStateException if the user is not unlocked.
      */
     public boolean isActivePasswordSufficient() {
         if (mService != null) {
diff --git a/core/java/android/app/admin/PasswordMetrics.java b/core/java/android/app/admin/PasswordMetrics.java
index ea3f560..4658a47 100644
--- a/core/java/android/app/admin/PasswordMetrics.java
+++ b/core/java/android/app/admin/PasswordMetrics.java
@@ -18,13 +18,11 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.app.admin.DevicePolicyManager;
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
-import java.io.IOException;
 
 /**
  * A class that represents the metrics of a password that are used to decide whether or not a
@@ -159,6 +157,22 @@
                 quality, length, letters, upperCase, lowerCase, numeric, symbols, nonLetter);
     }
 
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof PasswordMetrics)) {
+            return false;
+        }
+        PasswordMetrics o = (PasswordMetrics) other;
+        return this.quality == o.quality
+                && this.length == o.length
+                && this.letters == o.letters
+                && this.upperCase == o.upperCase
+                && this.lowerCase == o.lowerCase
+                && this.numeric == o.numeric
+                && this.symbols == o.symbols
+                && this.nonLetter == o.nonLetter;
+    }
+
     /*
      * Returns the maximum length of a sequential characters. A sequence is defined as
      * monotonically increasing characters with a constant interval or the same character repeated.
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 611531c..faab000 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -125,7 +125,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothA2dpSink mService;
+    private volatile IBluetoothA2dpSink mService;
     private BluetoothAdapter mAdapter;
 
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -240,15 +240,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -279,15 +280,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -297,15 +299,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -315,15 +318,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -333,16 +337,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -359,16 +363,16 @@
      */
     public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
         if (VDBG) log("getAudioConfig(" + device + ")");
-        if (mService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getAudioConfig(device);
+                return service.getAudioConfig(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return null;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -389,20 +393,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -421,16 +425,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.PRIORITY_OFF;
     }
 
@@ -442,16 +446,16 @@
      * @param device BluetoothDevice device
      */
     public boolean isA2dpPlaying(BluetoothDevice device) {
-        if (mService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothA2dpSink service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.isA2dpPlaying(device);
+                return service.isA2dpPlaying(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -485,7 +489,6 @@
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
                         BluetoothA2dpSink.this);
@@ -502,15 +505,11 @@
     };
 
     private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index 7528aa9..5f0e5d9 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -81,7 +81,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothAvrcpController mService;
+    private volatile IBluetoothAvrcpController mService;
     private BluetoothAdapter mAdapter;
 
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -179,15 +179,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -197,15 +198,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -215,16 +217,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -236,9 +238,10 @@
     public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getPlayerSettings");
         BluetoothAvrcpPlayerSettings settings = null;
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                settings = mService.getPlayerSettings(device);
+                settings = service.getPlayerSettings(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error talking to BT service in getMetadata() " + e);
                 return null;
@@ -253,15 +256,16 @@
      */
     public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
         if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.setPlayerApplicationSetting(plAppSetting);
+                return service.setPlayerApplicationSetting(plAppSetting);
             } catch (RemoteException e) {
                 Log.e(TAG, "Error talking to BT service in setPlayerApplicationSetting() " + e);
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -272,23 +276,23 @@
     public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
         Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
                 + keyState);
-        if (mService != null && isEnabled()) {
+        final IBluetoothAvrcpController service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.sendGroupNavigationCmd(device, keyCode, keyState);
+                service.sendGroupNavigationCmd(device, keyCode, keyState);
                 return;
             } catch (RemoteException e) {
                 Log.e(TAG, "Error talking to BT service in sendGroupNavigationCmd()", e);
                 return;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
     }
 
     private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
             mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
                         BluetoothAvrcpController.this);
@@ -305,15 +309,11 @@
     };
 
     private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 3ab2c4a..d982bb7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -712,7 +712,7 @@
      * getService() called.
      * TODO: Unify implementation of sService amongst BluetoothFoo API's
      */
-    private static IBluetooth sService;
+    private static volatile IBluetooth sService;
 
     private final String mAddress;
 
@@ -839,12 +839,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public String getName() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
             return null;
         }
         try {
-            return sService.getRemoteName(this);
+            return service.getRemoteName(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -859,12 +860,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getType() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
             return DEVICE_TYPE_UNKNOWN;
         }
         try {
-            return sService.getRemoteType(this);
+            return service.getRemoteType(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -879,12 +881,13 @@
      * @hide
      */
     public String getAlias() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
             return null;
         }
         try {
-            return sService.getRemoteAlias(this);
+            return service.getRemoteAlias(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -902,12 +905,13 @@
      * @hide
      */
     public boolean setAlias(String alias) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
             return false;
         }
         try {
-            return sService.setRemoteAlias(this, alias);
+            return service.setRemoteAlias(this, alias);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -942,12 +946,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getBatteryLevel() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
             return BATTERY_LEVEL_UNKNOWN;
         }
         try {
-            return sService.getBatteryLevel(this);
+            return service.getBatteryLevel(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -966,7 +971,8 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean createBond() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
             return false;
         }
@@ -974,7 +980,7 @@
             Log.i(TAG, "createBond() for device " + getAddress()
                     + " called by pid: " + Process.myPid()
                     + " tid: " + Process.myTid());
-            return sService.createBond(this, TRANSPORT_AUTO);
+            return service.createBond(this, TRANSPORT_AUTO);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -998,7 +1004,8 @@
      * @hide
      */
     public boolean createBond(int transport) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
             return false;
         }
@@ -1009,7 +1016,7 @@
             Log.i(TAG, "createBond() for device " + getAddress()
                     + " called by pid: " + Process.myPid()
                     + " tid: " + Process.myTid());
-            return sService.createBond(this, transport);
+            return service.createBond(this, transport);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1035,8 +1042,13 @@
      * @hide
      */
     public boolean createBondOutOfBand(int transport, OobData oobData) {
+        final IBluetooth service = sService;
+        if (service == null) {
+            Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
+            return false;
+        }
         try {
-            return sService.createBondOutOfBand(this, transport, oobData);
+            return service.createBondOutOfBand(this, transport, oobData);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1045,8 +1057,13 @@
 
     /** @hide */
     public boolean isBondingInitiatedLocally() {
+        final IBluetooth service = sService;
+        if (service == null) {
+            Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed");
+            return false;
+        }
         try {
-            return sService.isBondingInitiatedLocally(this);
+            return service.isBondingInitiatedLocally(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1082,7 +1099,8 @@
      * @hide
      */
     public boolean cancelBondProcess() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
             return false;
         }
@@ -1090,7 +1108,7 @@
             Log.i(TAG, "cancelBondProcess() for device " + getAddress()
                     + " called by pid: " + Process.myPid()
                     + " tid: " + Process.myTid());
-            return sService.cancelBondProcess(this);
+            return service.cancelBondProcess(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1108,7 +1126,8 @@
      * @hide
      */
     public boolean removeBond() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
             return false;
         }
@@ -1116,7 +1135,7 @@
             Log.i(TAG, "removeBond() for device " + getAddress()
                     + " called by pid: " + Process.myPid()
                     + " tid: " + Process.myTid());
-            return sService.removeBond(this);
+            return service.removeBond(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1134,19 +1153,15 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getBondState() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get bond state");
             return BOND_NONE;
         }
         try {
-            return sService.getBondState(this);
+            return service.getBondState(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
-        } catch (NullPointerException npe) {
-            // Handle case where bluetooth service proxy
-            // is already null.
-            Log.e(TAG, "NullPointerException for getBondState() of device ("
-                    + getAddress() + ")", npe);
         }
         return BOND_NONE;
     }
@@ -1160,12 +1175,13 @@
      */
     @SystemApi
     public boolean isConnected() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             // BT is not enabled, we cannot be connected.
             return false;
         }
         try {
-            return sService.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
+            return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
             return false;
@@ -1182,12 +1198,13 @@
      */
     @SystemApi
     public boolean isEncrypted() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             // BT is not enabled, we cannot be connected.
             return false;
         }
         try {
-            return sService.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
+            return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
             return false;
@@ -1201,12 +1218,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public BluetoothClass getBluetoothClass() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
             return null;
         }
         try {
-            int classInt = sService.getRemoteClass(this);
+            int classInt = service.getRemoteClass(this);
             if (classInt == BluetoothClass.ERROR) return null;
             return new BluetoothClass(classInt);
         } catch (RemoteException e) {
@@ -1227,12 +1245,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public ParcelUuid[] getUuids() {
-        if (sService == null || !isBluetoothEnabled()) {
+        final IBluetooth service = sService;
+        if (service == null || !isBluetoothEnabled()) {
             Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
             return null;
         }
         try {
-            return sService.getRemoteUuids(this);
+            return service.getRemoteUuids(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1254,7 +1273,7 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public boolean fetchUuidsWithSdp() {
-        IBluetooth service = sService;
+        final IBluetooth service = sService;
         if (service == null || !isBluetoothEnabled()) {
             Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp");
             return false;
@@ -1289,12 +1308,13 @@
      */
     /** @hide */
     public boolean sdpSearch(ParcelUuid uuid) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
             return false;
         }
         try {
-            return sService.sdpSearch(this, uuid);
+            return service.sdpSearch(this, uuid);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1308,12 +1328,13 @@
      * @return true pin has been set false for error
      */
     public boolean setPin(byte[] pin) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
             return false;
         }
         try {
-            return sService.setPin(this, true, pin.length, pin);
+            return service.setPin(this, true, pin.length, pin);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1337,12 +1358,13 @@
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
     public boolean setPairingConfirmation(boolean confirm) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
             return false;
         }
         try {
-            return sService.setPairingConfirmation(this, confirm);
+            return service.setPairingConfirmation(this, confirm);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1361,12 +1383,13 @@
 
     /** @hide */
     public boolean cancelPairingUserInput() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             Log.e(TAG, "BT not enabled. Cannot create pairing user input");
             return false;
         }
         try {
-            return sService.cancelBondProcess(this);
+            return service.cancelBondProcess(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1400,11 +1423,12 @@
      * @hide
      */
     public int getPhonebookAccessPermission() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return ACCESS_UNKNOWN;
         }
         try {
-            return sService.getPhonebookAccessPermission(this);
+            return service.getPhonebookAccessPermission(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1421,11 +1445,12 @@
      * @hide
      */
     public boolean setPhonebookAccessPermission(int value) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return false;
         }
         try {
-            return sService.setPhonebookAccessPermission(this, value);
+            return service.setPhonebookAccessPermission(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1440,11 +1465,12 @@
      * @hide
      */
     public int getMessageAccessPermission() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return ACCESS_UNKNOWN;
         }
         try {
-            return sService.getMessageAccessPermission(this);
+            return service.getMessageAccessPermission(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1461,11 +1487,12 @@
      * @hide
      */
     public boolean setMessageAccessPermission(int value) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return false;
         }
         try {
-            return sService.setMessageAccessPermission(this, value);
+            return service.setMessageAccessPermission(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1480,11 +1507,12 @@
      * @hide
      */
     public int getSimAccessPermission() {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return ACCESS_UNKNOWN;
         }
         try {
-            return sService.getSimAccessPermission(this);
+            return service.getSimAccessPermission(this);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
@@ -1501,11 +1529,12 @@
      * @hide
      */
     public boolean setSimAccessPermission(int value) {
-        if (sService == null) {
+        final IBluetooth service = sService;
+        if (service == null) {
             return false;
         }
         try {
-            return sService.setSimAccessPermission(this, value);
+            return service.setSimAccessPermission(this, value);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
         }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index be1ce63..85550c7 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -306,7 +306,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothHeadset mService;
+    private volatile IBluetoothHeadset mService;
     private BluetoothAdapter mAdapter;
 
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -418,15 +418,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -457,15 +458,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -475,15 +477,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -493,15 +496,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -511,15 +515,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -540,19 +545,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -571,15 +577,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -605,14 +612,15 @@
      */
     public boolean startVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("startVoiceRecognition()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.startVoiceRecognition(device);
+                return service.startVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -627,14 +635,15 @@
      */
     public boolean stopVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("stopVoiceRecognition()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.stopVoiceRecognition(device);
+                return service.stopVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -648,14 +657,15 @@
      */
     public boolean isAudioConnected(BluetoothDevice device) {
         if (VDBG) log("isAudioConnected()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.isAudioConnected(device);
+                return service.isAudioConnected(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -674,14 +684,15 @@
      */
     public int getBatteryUsageHint(BluetoothDevice device) {
         if (VDBG) log("getBatteryUsageHint()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getBatteryUsageHint(device);
+                return service.getBatteryUsageHint(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return -1;
     }
 
@@ -704,9 +715,10 @@
      */
     public boolean acceptIncomingConnect(BluetoothDevice device) {
         if (DBG) log("acceptIncomingConnect");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.acceptIncomingConnect(device);
+                return service.acceptIncomingConnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -724,9 +736,10 @@
      */
     public boolean rejectIncomingConnect(BluetoothDevice device) {
         if (DBG) log("rejectIncomingConnect");
-        if (mService != null) {
+        final IBluetoothHeadset service = mService;
+        if (service != null) {
             try {
-                return mService.rejectIncomingConnect(device);
+                return service.rejectIncomingConnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -745,9 +758,10 @@
      */
     public int getAudioState(BluetoothDevice device) {
         if (VDBG) log("getAudioState");
-        if (mService != null && !isDisabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && !isDisabled()) {
             try {
-                return mService.getAudioState(device);
+                return service.getAudioState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -770,9 +784,10 @@
      */
     public void setAudioRouteAllowed(boolean allowed) {
         if (VDBG) log("setAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.setAudioRouteAllowed(allowed);
+                service.setAudioRouteAllowed(allowed);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -790,9 +805,10 @@
      */
     public boolean getAudioRouteAllowed() {
         if (VDBG) log("getAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getAudioRouteAllowed();
+                return service.getAudioRouteAllowed();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -812,9 +828,10 @@
      */
     public void setForceScoAudio(boolean forced) {
         if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.setForceScoAudio(forced);
+                service.setForceScoAudio(forced);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -834,14 +851,15 @@
      */
     public boolean isAudioOn() {
         if (VDBG) log("isAudioOn()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.isAudioOn();
+                return service.isAudioOn();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
 
     }
@@ -855,9 +873,10 @@
      * @hide
      */
     public boolean connectAudio() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.connectAudio();
+                return service.connectAudio();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -877,9 +896,10 @@
      * @hide
      */
     public boolean disconnectAudio() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.disconnectAudio();
+                return service.disconnectAudio();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -903,9 +923,10 @@
      */
     public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
         if (DBG) log("startScoUsingVirtualVoiceCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.startScoUsingVirtualVoiceCall(device);
+                return service.startScoUsingVirtualVoiceCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -926,9 +947,10 @@
      */
     public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
         if (DBG) log("stopScoUsingVirtualVoiceCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.stopScoUsingVirtualVoiceCall(device);
+                return service.stopScoUsingVirtualVoiceCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -949,9 +971,10 @@
      */
     public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
             int type) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.phoneStateChanged(numActive, numHeld, callState, number, type);
+                service.phoneStateChanged(numActive, numHeld, callState, number, type);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -968,9 +991,10 @@
      */
     public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
             String number, int type) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.clccResponse(index, direction, status, mode, mpty, number, type);
+                service.clccResponse(index, direction, status, mode, mpty, number, type);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1006,14 +1030,15 @@
         if (command == null) {
             throw new IllegalArgumentException("command is null");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendVendorSpecificResultCode(device, command, arg);
+                return service.sendVendorSpecificResultCode(device, command, arg);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -1027,9 +1052,10 @@
      * @hide
      */
     public boolean enableWBS() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.enableWBS();
+                return service.enableWBS();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1048,9 +1074,10 @@
      * @hide
      */
     public boolean disableWBS() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.disableWBS();
+                return service.disableWBS();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1083,9 +1110,10 @@
      * @hide
      */
     public void bindResponse(int indId, boolean indStatus) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadset service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.bindResponse(indId, indStatus);
+                service.bindResponse(indId, indStatus);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1115,20 +1143,15 @@
     };
 
     private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
     private boolean isDisabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_OFF) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_OFF;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 7ed2d2e..031287f 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -76,8 +76,8 @@
      * Intent sent whenever audio state changes.
      *
      * <p>It includes two mandatory extras:
-     * {@link BluetoothProfile.EXTRA_STATE},
-     * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE},
+     * {@link BluetoothProfile#EXTRA_STATE},
+     * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},
      * with possible values:
      * {@link #STATE_AUDIO_CONNECTING},
      * {@link #STATE_AUDIO_CONNECTED},
@@ -367,7 +367,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothHeadsetClient mService;
+    private volatile IBluetoothHeadsetClient mService;
     private BluetoothAdapter mAdapter;
 
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -478,15 +478,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -499,15 +500,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -519,15 +521,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -541,15 +544,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -562,15 +566,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -581,19 +586,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -602,15 +608,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -627,14 +634,15 @@
      */
     public boolean startVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("startVoiceRecognition()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.startVoiceRecognition(device);
+                return service.startVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -651,14 +659,15 @@
      */
     public boolean stopVoiceRecognition(BluetoothDevice device) {
         if (DBG) log("stopVoiceRecognition()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.stopVoiceRecognition(device);
+                return service.stopVoiceRecognition(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -670,14 +679,15 @@
      */
     public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
         if (DBG) log("getCurrentCalls()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getCurrentCalls(device);
+                return service.getCurrentCalls(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -689,14 +699,15 @@
      */
     public Bundle getCurrentAgEvents(BluetoothDevice device) {
         if (DBG) log("getCurrentCalls()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getCurrentAgEvents(device);
+                return service.getCurrentAgEvents(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -711,14 +722,15 @@
      */
     public boolean acceptCall(BluetoothDevice device, int flag) {
         if (DBG) log("acceptCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.acceptCall(device, flag);
+                return service.acceptCall(device, flag);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -731,14 +743,15 @@
      */
     public boolean holdCall(BluetoothDevice device) {
         if (DBG) log("holdCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.holdCall(device);
+                return service.holdCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -755,14 +768,15 @@
      */
     public boolean rejectCall(BluetoothDevice device) {
         if (DBG) log("rejectCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.rejectCall(device);
+                return service.rejectCall(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -784,14 +798,15 @@
      */
     public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
         if (DBG) log("terminateCall()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.terminateCall(device, call);
+                return service.terminateCall(device, call);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -811,14 +826,15 @@
      */
     public boolean enterPrivateMode(BluetoothDevice device, int index) {
         if (DBG) log("enterPrivateMode()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.enterPrivateMode(device, index);
+                return service.enterPrivateMode(device, index);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -837,14 +853,15 @@
      */
     public boolean explicitCallTransfer(BluetoothDevice device) {
         if (DBG) log("explicitCallTransfer()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.explicitCallTransfer(device);
+                return service.explicitCallTransfer(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -859,14 +876,15 @@
      */
     public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
         if (DBG) log("dial()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.dial(device, number);
+                return service.dial(device, number);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return null;
     }
 
@@ -882,14 +900,15 @@
      */
     public boolean sendDTMF(BluetoothDevice device, byte code) {
         if (DBG) log("sendDTMF()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendDTMF(device, code);
+                return service.sendDTMF(device, code);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -907,14 +926,15 @@
      */
     public boolean getLastVoiceTagNumber(BluetoothDevice device) {
         if (DBG) log("getLastVoiceTagNumber()");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getLastVoiceTagNumber(device);
+                return service.getLastVoiceTagNumber(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -925,9 +945,10 @@
      */
     public int getAudioState(BluetoothDevice device) {
         if (VDBG) log("getAudioState");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getAudioState(device);
+                return service.getAudioState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -947,9 +968,10 @@
      */
     public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
         if (VDBG) log("setAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                mService.setAudioRouteAllowed(device, allowed);
+                service.setAudioRouteAllowed(device, allowed);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -968,9 +990,10 @@
      */
     public boolean getAudioRouteAllowed(BluetoothDevice device) {
         if (VDBG) log("getAudioRouteAllowed");
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getAudioRouteAllowed(device);
+                return service.getAudioRouteAllowed(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -991,9 +1014,10 @@
      * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
      */
     public boolean connectAudio(BluetoothDevice device) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.connectAudio(device);
+                return service.connectAudio(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1014,9 +1038,10 @@
      * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
      */
     public boolean disconnectAudio(BluetoothDevice device) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.disconnectAudio(device);
+                return service.disconnectAudio(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1034,9 +1059,10 @@
      * @return bundle of AG features; null if no service or AG not connected
      */
     public Bundle getCurrentAgFeatures(BluetoothDevice device) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHeadsetClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getCurrentAgFeatures(device);
+                return service.getCurrentAgFeatures(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -1048,7 +1074,7 @@
     }
 
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         @Override
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
@@ -1071,15 +1097,11 @@
     };
 
     private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothHealth.java b/core/java/android/bluetooth/BluetoothHealth.java
index dc5f381..57a0197 100644
--- a/core/java/android/bluetooth/BluetoothHealth.java
+++ b/core/java/android/bluetooth/BluetoothHealth.java
@@ -176,9 +176,10 @@
         BluetoothHealthAppConfiguration config =
                 new BluetoothHealthAppConfiguration(name, dataType, role, channelType);
 
-        if (mService != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null) {
             try {
-                result = mService.registerAppConfiguration(config, wrapper);
+                result = service.registerAppConfiguration(config, wrapper);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -200,9 +201,10 @@
      */
     public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
         boolean result = false;
-        if (mService != null && isEnabled() && config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && config != null) {
             try {
-                result = mService.unregisterAppConfiguration(config);
+                result = service.unregisterAppConfiguration(config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -228,9 +230,10 @@
      */
     public boolean connectChannelToSource(BluetoothDevice device,
             BluetoothHealthAppConfiguration config) {
-        if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.connectChannelToSource(device, config);
+                return service.connectChannelToSource(device, config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -256,9 +259,10 @@
      */
     public boolean connectChannelToSink(BluetoothDevice device,
             BluetoothHealthAppConfiguration config, int channelType) {
-        if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.connectChannelToSink(device, config, channelType);
+                return service.connectChannelToSink(device, config, channelType);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -284,9 +288,10 @@
      */
     public boolean disconnectChannel(BluetoothDevice device,
             BluetoothHealthAppConfiguration config, int channelId) {
-        if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.disconnectChannel(device, config, channelId);
+                return service.disconnectChannel(device, config, channelId);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -312,9 +317,10 @@
      */
     public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
             BluetoothHealthAppConfiguration config) {
-        if (mService != null && isEnabled() && isValidDevice(device) && config != null) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device) && config != null) {
             try {
-                return mService.getMainChannelFd(device, config);
+                return service.getMainChannelFd(device, config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -341,9 +347,10 @@
      */
     @Override
     public int getConnectionState(BluetoothDevice device) {
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getHealthDeviceConnectionState(device);
+                return service.getHealthDeviceConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -370,15 +377,16 @@
      */
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedHealthDevices();
+                return service.getConnectedHealthDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -401,15 +409,16 @@
      */
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
-        if (mService != null && isEnabled()) {
+        final IBluetoothHealth service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getHealthDevicesMatchingConnectionStates(states);
+                return service.getHealthDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -455,7 +464,7 @@
 
     private Context mContext;
     private ServiceListener mServiceListener;
-    private IBluetoothHealth mService;
+    private volatile IBluetoothHealth mService;
     BluetoothAdapter mAdapter;
 
     /**
@@ -540,11 +549,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private boolean checkAppParam(String name, int role, int channelType,
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index a9a9010..3261576 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -222,7 +222,7 @@
     private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetoothInputDevice mService;
+    private volatile IBluetoothInputDevice mService;
 
     private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
             new IBluetoothStateChangeCallback.Stub() {
@@ -331,15 +331,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -370,15 +371,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -388,15 +390,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -406,15 +409,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -424,15 +428,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -453,19 +458,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -484,15 +490,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.PRIORITY_OFF;
     }
 
@@ -517,18 +524,13 @@
     };
 
     private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
-
     /**
      * Initiate virtual unplug for a HID input device.
      *
@@ -540,16 +542,17 @@
      */
     public boolean virtualUnplug(BluetoothDevice device) {
         if (DBG) log("virtualUnplug(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.virtualUnplug(device);
+                return service.virtualUnplug(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
 
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
 
     }
@@ -565,15 +568,16 @@
      */
     public boolean getProtocolMode(BluetoothDevice device) {
         if (VDBG) log("getProtocolMode(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getProtocolMode(device);
+                return service.getProtocolMode(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -588,15 +592,16 @@
      */
     public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
         if (DBG) log("setProtocolMode(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.setProtocolMode(device, protocolMode);
+                return service.setProtocolMode(device, protocolMode);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -615,19 +620,19 @@
     public boolean getReport(BluetoothDevice device, byte reportType, byte reportId,
             int bufferSize) {
         if (VDBG) {
-            log(
-                    "getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
-                            + "bufferSize=" + bufferSize);
+            log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
+                    + "bufferSize=" + bufferSize);
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getReport(device, reportType, reportId, bufferSize);
+                return service.getReport(device, reportType, reportId, bufferSize);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -644,15 +649,16 @@
      */
     public boolean setReport(BluetoothDevice device, byte reportType, String report) {
         if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.setReport(device, reportType, report);
+                return service.setReport(device, reportType, report);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -668,15 +674,16 @@
      */
     public boolean sendData(BluetoothDevice device, String report) {
         if (DBG) log("sendData(" + device + "), report=" + report);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendData(device, report);
+                return service.sendData(device, report);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -691,15 +698,16 @@
      */
     public boolean getIdleTime(BluetoothDevice device) {
         if (DBG) log("getIdletime(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getIdleTime(device);
+                return service.getIdleTime(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -715,15 +723,16 @@
      */
     public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
         if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothInputDevice service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.setIdleTime(device, idleTime);
+                return service.setIdleTime(device, idleTime);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
diff --git a/core/java/android/bluetooth/BluetoothInputHost.java b/core/java/android/bluetooth/BluetoothInputHost.java
index 15303dc..37f0427 100644
--- a/core/java/android/bluetooth/BluetoothInputHost.java
+++ b/core/java/android/bluetooth/BluetoothInputHost.java
@@ -113,7 +113,7 @@
 
     private ServiceListener mServiceListener;
 
-    private IBluetoothInputHost mService;
+    private volatile IBluetoothInputHost mService;
 
     private BluetoothAdapter mAdapter;
 
@@ -202,24 +202,18 @@
                 }
             };
 
-    private ServiceConnection mConnection = new ServiceConnection() {
-
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             Log.d(TAG, "onServiceConnected()");
-
             mService = IBluetoothInputHost.Stub.asInterface(service);
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.INPUT_HOST,
                         BluetoothInputHost.this);
             }
         }
-
         public void onServiceDisconnected(ComponentName className) {
             Log.d(TAG, "onServiceDisconnected()");
-
             mService = null;
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceDisconnected(BluetoothProfile.INPUT_HOST);
             }
@@ -291,9 +285,10 @@
     public List<BluetoothDevice> getConnectedDevices() {
         Log.v(TAG, "getConnectedDevices()");
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -311,9 +306,10 @@
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         Log.v(TAG, "getDevicesMatchingConnectionStates(): states=" + Arrays.toString(states));
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -331,9 +327,10 @@
     public int getConnectionState(BluetoothDevice device) {
         Log.v(TAG, "getConnectionState(): device=" + device);
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -370,13 +367,14 @@
             return false;
         }
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
                 BluetoothHidDeviceAppConfiguration config =
                         new BluetoothHidDeviceAppConfiguration();
                 BluetoothHidDeviceCallbackWrapper cbw =
                         new BluetoothHidDeviceCallbackWrapper(callback);
-                result = mService.registerApp(config, sdp, inQos, outQos, cbw);
+                result = service.registerApp(config, sdp, inQos, outQos, cbw);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -403,9 +401,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.unregisterApp(config);
+                result = service.unregisterApp(config);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -427,9 +426,10 @@
     public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.sendReport(device, id, data);
+                result = service.sendReport(device, id, data);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -454,9 +454,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.replyReport(device, type, id, data);
+                result = service.replyReport(device, type, id, data);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -479,9 +480,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.reportError(device, error);
+                result = service.reportError(device, error);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -502,9 +504,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.unplug(device);
+                result = service.unplug(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -526,9 +529,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.connect(device);
+                result = service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -549,9 +553,10 @@
 
         boolean result = false;
 
-        if (mService != null) {
+        final IBluetoothInputHost service = mService;
+        if (service != null) {
             try {
-                result = mService.disconnect(device);
+                result = service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 26a9106..5b55b23 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -43,7 +43,7 @@
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
 
-    private IBluetoothMap mService;
+    private volatile IBluetoothMap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -161,9 +161,10 @@
      */
     public int getState() {
         if (VDBG) log("getState()");
-        if (mService != null) {
+        final IBluetoothMap service = mService;
+        if (service != null) {
             try {
-                return mService.getState();
+                return service.getState();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -182,9 +183,10 @@
      */
     public BluetoothDevice getClient() {
         if (VDBG) log("getClient()");
-        if (mService != null) {
+        final IBluetoothMap service = mService;
+        if (service != null) {
             try {
-                return mService.getClient();
+                return service.getClient();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -202,9 +204,10 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) log("isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothMap service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
+                return service.isConnected(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -232,15 +235,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -272,15 +276,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -291,15 +296,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -310,15 +316,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -335,19 +342,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -363,15 +371,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -403,13 +412,8 @@
         log("Bluetooth is Not enabled");
         return false;
     }
-
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
-
 }
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 3e0c365..af3b662 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -59,7 +59,7 @@
     public static final String EXTRA_SENDER_CONTACT_NAME =
             "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
 
-    private IBluetoothMapClient mService;
+    private volatile IBluetoothMapClient mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -176,9 +176,10 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothMapClient service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
+                return service.isConnected(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -195,9 +196,10 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
-        if (mService != null) {
+        final IBluetoothMapClient service = mService;
+        if (service != null) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -216,14 +218,15 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -235,15 +238,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) Log.d(TAG, "getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<>();
     }
 
@@ -255,15 +259,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<>();
     }
 
@@ -275,15 +280,16 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -298,19 +304,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -326,15 +333,16 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
@@ -353,9 +361,10 @@
     public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
             PendingIntent sentIntent, PendingIntent deliveredIntent) {
         if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
+                return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -372,9 +381,10 @@
      */
     public boolean getUnreadMessages(BluetoothDevice device) {
         if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothMapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getUnreadMessages(device);
+                return service.getUnreadMessages(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -409,12 +419,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
-
 }
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 63e83d2..866b063 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -123,7 +123,7 @@
     private Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
-    private IBluetoothPan mPanService;
+    private volatile IBluetoothPan mPanService;
 
     /**
      * Create a BluetoothPan proxy object for interacting with the local
@@ -238,15 +238,16 @@
      */
     public boolean connect(BluetoothDevice device) {
         if (DBG) log("connect(" + device + ")");
-        if (mPanService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mPanService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -277,15 +278,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mPanService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mPanService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -295,15 +297,16 @@
     @Override
     public List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                return mPanService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -313,15 +316,16 @@
     @Override
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                return mPanService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -331,25 +335,25 @@
     @Override
     public int getConnectionState(BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
-        if (mPanService != null && isEnabled()
-                && isValidDevice(device)) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mPanService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mPanService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
     public void setBluetoothTethering(boolean value) {
         if (DBG) log("setBluetoothTethering(" + value + ")");
-
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                mPanService.setBluetoothTethering(value);
+                service.setBluetoothTethering(value);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
             }
@@ -358,10 +362,10 @@
 
     public boolean isTetheringOn() {
         if (VDBG) log("isTetheringOn()");
-
-        if (mPanService != null && isEnabled()) {
+        final IBluetoothPan service = mPanService;
+        if (service != null && isEnabled()) {
             try {
-                return mPanService.isTetheringOn();
+                return service.isTetheringOn();
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
             }
@@ -373,7 +377,6 @@
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
             mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
-
             if (mServiceListener != null) {
                 mServiceListener.onServiceConnected(BluetoothProfile.PAN,
                         BluetoothPan.this);
@@ -390,15 +393,11 @@
     };
 
     private boolean isEnabled() {
-        if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
-        return false;
+        return mAdapter.getState() == BluetoothAdapter.STATE_ON;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) return false;
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 78b7c7b..19f5198 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -68,7 +68,7 @@
     public static final String PBAP_STATE_CHANGED_ACTION =
             "android.bluetooth.pbap.intent.action.PBAP_STATE_CHANGED";
 
-    private IBluetoothPbap mService;
+    private volatile IBluetoothPbap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -214,9 +214,10 @@
      */
     public int getState() {
         if (VDBG) log("getState()");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                return mService.getState();
+                return service.getState();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -235,9 +236,10 @@
      */
     public BluetoothDevice getClient() {
         if (VDBG) log("getClient()");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                return mService.getClient();
+                return service.getClient();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -255,9 +257,10 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) log("isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
+                return service.isConnected(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -275,9 +278,10 @@
      */
     public boolean disconnect() {
         if (DBG) log("disconnect()");
-        if (mService != null) {
+        final IBluetoothPbap service = mService;
+        if (service != null) {
             try {
-                mService.disconnect();
+                service.disconnect();
                 return true;
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index b9b372c..00a15f3 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -42,7 +42,7 @@
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
 
-    private IBluetoothPbapClient mService;
+    private volatile IBluetoothPbapClient mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -173,15 +173,16 @@
         if (DBG) {
             log("connect(" + device + ") for PBAP Client.");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.connect(device);
+                return service.connect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -197,16 +198,17 @@
         if (DBG) {
             log("disconnect(" + device + ")" + new Exception());
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                mService.disconnect(device);
+                service.disconnect(device);
                 return true;
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -223,15 +225,16 @@
         if (DBG) {
             log("getConnectedDevices()");
         }
-        if (mService != null && isEnabled()) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return new ArrayList<BluetoothDevice>();
@@ -247,15 +250,16 @@
         if (DBG) {
             log("getDevicesMatchingStates()");
         }
-        if (mService != null && isEnabled()) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return new ArrayList<BluetoothDevice>();
@@ -271,15 +275,16 @@
         if (DBG) {
             log("getConnectionState(" + device + ")");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return BluetoothProfile.STATE_DISCONNECTED;
@@ -321,14 +326,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) {
-            return false;
-        }
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
-            return true;
-        }
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
     /**
@@ -339,26 +338,27 @@
      * {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
-     * @param priority
+     * @param priority Priority of this profile
      * @return true if priority is set, false on error
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) {
             log("setPriority(" + device + ", " + priority + ")");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return false;
@@ -378,15 +378,16 @@
         if (VDBG) {
             log("getPriority(" + device + ")");
         }
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothPbapClient service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) {
+        if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
         return PRIORITY_OFF;
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index bcdf493..4848162 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -68,7 +68,7 @@
     public static final String ACTION_CONNECTION_STATE_CHANGED =
             "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
 
-    private IBluetoothSap mService;
+    private volatile IBluetoothSap mService;
     private final Context mContext;
     private ServiceListener mServiceListener;
     private BluetoothAdapter mAdapter;
@@ -202,9 +202,10 @@
      */
     public int getState() {
         if (VDBG) log("getState()");
-        if (mService != null) {
+        final IBluetoothSap service = mService;
+        if (service != null) {
             try {
-                return mService.getState();
+                return service.getState();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -224,9 +225,10 @@
      */
     public BluetoothDevice getClient() {
         if (VDBG) log("getClient()");
-        if (mService != null) {
+        final IBluetoothSap service = mService;
+        if (service != null) {
             try {
-                return mService.getClient();
+                return service.getClient();
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -246,9 +248,10 @@
      */
     public boolean isConnected(BluetoothDevice device) {
         if (VDBG) log("isConnected(" + device + ")");
-        if (mService != null) {
+        final IBluetoothSap service = mService;
+        if (service != null) {
             try {
-                return mService.isConnected(device);
+                return service.isConnected(device);
             } catch (RemoteException e) {
                 Log.e(TAG, e.toString());
             }
@@ -279,15 +282,16 @@
      */
     public boolean disconnect(BluetoothDevice device) {
         if (DBG) log("disconnect(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.disconnect(device);
+                return service.disconnect(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -299,15 +303,16 @@
      */
     public List<BluetoothDevice> getConnectedDevices() {
         if (DBG) log("getConnectedDevices()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getConnectedDevices();
+                return service.getConnectedDevices();
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -319,15 +324,16 @@
      */
     public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
         if (DBG) log("getDevicesMatchingStates()");
-        if (mService != null && isEnabled()) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled()) {
             try {
-                return mService.getDevicesMatchingConnectionStates(states);
+                return service.getDevicesMatchingConnectionStates(states);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return new ArrayList<BluetoothDevice>();
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return new ArrayList<BluetoothDevice>();
     }
 
@@ -339,15 +345,16 @@
      */
     public int getConnectionState(BluetoothDevice device) {
         if (DBG) log("getConnectionState(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getConnectionState(device);
+                return service.getConnectionState(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return BluetoothProfile.STATE_DISCONNECTED;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return BluetoothProfile.STATE_DISCONNECTED;
     }
 
@@ -363,19 +370,20 @@
      */
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             if (priority != BluetoothProfile.PRIORITY_OFF
                     && priority != BluetoothProfile.PRIORITY_ON) {
                 return false;
             }
             try {
-                return mService.setPriority(device, priority);
+                return service.setPriority(device, priority);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return false;
     }
 
@@ -388,19 +396,20 @@
      */
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
-        if (mService != null && isEnabled() && isValidDevice(device)) {
+        final IBluetoothSap service = mService;
+        if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return mService.getPriority(device);
+                return service.getPriority(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return PRIORITY_OFF;
             }
         }
-        if (mService == null) Log.w(TAG, "Proxy not attached to service");
+        if (service == null) Log.w(TAG, "Proxy not attached to service");
         return PRIORITY_OFF;
     }
 
-    private ServiceConnection mConnection = new ServiceConnection() {
+    private final ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) log("Proxy object connected");
             mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
@@ -432,15 +441,8 @@
         return false;
     }
 
-    private boolean isValidDevice(BluetoothDevice device) {
-        if (device == null) {
-            return false;
-        }
-
-        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
-            return true;
-        }
-        return false;
+    private static boolean isValidDevice(BluetoothDevice device) {
+        return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress());
     }
 
 }
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index c8ed7ef..7fc79d7 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -99,7 +99,9 @@
 
     /**
      * Start Bluetooth LE scan with default parameters and no filters. The scan results will be
-     * delivered through {@code callback}.
+     * delivered through {@code callback}. For unfiltered scans, scanning is stopped on screen
+     * off to save power. Scanning is resumed when screen is turned on again. To avoid this, use
+     * {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}.
      * <p>
      * An app must hold
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
@@ -116,6 +118,9 @@
 
     /**
      * Start Bluetooth LE scan. The scan results will be delivered through {@code callback}.
+     * For unfiltered scans, scanning is stopped on screen off to save power. Scanning is
+     * resumed when screen is turned on again. To avoid this, do filetered scanning by
+     * using proper {@link ScanFilter}.
      * <p>
      * An app must hold
      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 4703af0..cceb949 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -317,13 +317,7 @@
     private static final HashMap<Class, Integer> EMPTY_CLASS_LIMIT_MAP =
             new HashMap<Class, Integer>();
 
-    /**
-     * The current VmPolicy in effect.
-     *
-     * <p>TODO: these are redundant (mask is in VmPolicy). Should remove sVmPolicyMask.
-     */
-    private static volatile int sVmPolicyMask = 0;
-
+    /** The current VmPolicy in effect. */
     private static volatile VmPolicy sVmPolicy = VmPolicy.LAX;
 
     /** {@hide} */
@@ -1168,7 +1162,12 @@
      * @hide
      */
     public static void enableDeathOnFileUriExposure() {
-        sVmPolicyMask |= DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE;
+        sVmPolicy =
+                new VmPolicy(
+                        sVmPolicy.mask
+                                | DETECT_VM_FILE_URI_EXPOSURE
+                                | PENALTY_DEATH_ON_FILE_URI_EXPOSURE,
+                        sVmPolicy.classInstanceLimit);
     }
 
     /**
@@ -1178,7 +1177,12 @@
      * @hide
      */
     public static void disableDeathOnFileUriExposure() {
-        sVmPolicyMask &= ~(DETECT_VM_FILE_URI_EXPOSURE | PENALTY_DEATH_ON_FILE_URI_EXPOSURE);
+        sVmPolicy =
+                new VmPolicy(
+                        sVmPolicy.mask
+                                & ~(DETECT_VM_FILE_URI_EXPOSURE
+                                        | PENALTY_DEATH_ON_FILE_URI_EXPOSURE),
+                        sVmPolicy.classInstanceLimit);
     }
 
     /**
@@ -1709,14 +1713,13 @@
     public static void setVmPolicy(final VmPolicy policy) {
         synchronized (StrictMode.class) {
             sVmPolicy = policy;
-            sVmPolicyMask = policy.mask;
             setCloseGuardEnabled(vmClosableObjectLeaksEnabled());
 
             Looper looper = Looper.getMainLooper();
             if (looper != null) {
                 MessageQueue mq = looper.mQueue;
                 if (policy.classInstanceLimit.size() == 0
-                        || (sVmPolicyMask & VM_PENALTY_MASK) == 0) {
+                        || (sVmPolicy.mask & VM_PENALTY_MASK) == 0) {
                     mq.removeIdleHandler(sProcessIdleHandler);
                     sIsIdlerRegistered = false;
                 } else if (!sIsIdlerRegistered) {
@@ -1726,9 +1729,9 @@
             }
 
             int networkPolicy = NETWORK_POLICY_ACCEPT;
-            if ((sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
-                if ((sVmPolicyMask & PENALTY_DEATH) != 0
-                        || (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
+            if ((sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0) {
+                if ((sVmPolicy.mask & PENALTY_DEATH) != 0
+                        || (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0) {
                     networkPolicy = NETWORK_POLICY_REJECT;
                 } else {
                     networkPolicy = NETWORK_POLICY_LOG;
@@ -1771,37 +1774,37 @@
 
     /** @hide */
     public static boolean vmSqliteObjectLeaksEnabled() {
-        return (sVmPolicyMask & DETECT_VM_CURSOR_LEAKS) != 0;
+        return (sVmPolicy.mask & DETECT_VM_CURSOR_LEAKS) != 0;
     }
 
     /** @hide */
     public static boolean vmClosableObjectLeaksEnabled() {
-        return (sVmPolicyMask & DETECT_VM_CLOSABLE_LEAKS) != 0;
+        return (sVmPolicy.mask & DETECT_VM_CLOSABLE_LEAKS) != 0;
     }
 
     /** @hide */
     public static boolean vmRegistrationLeaksEnabled() {
-        return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
+        return (sVmPolicy.mask & DETECT_VM_REGISTRATION_LEAKS) != 0;
     }
 
     /** @hide */
     public static boolean vmFileUriExposureEnabled() {
-        return (sVmPolicyMask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
+        return (sVmPolicy.mask & DETECT_VM_FILE_URI_EXPOSURE) != 0;
     }
 
     /** @hide */
     public static boolean vmCleartextNetworkEnabled() {
-        return (sVmPolicyMask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
+        return (sVmPolicy.mask & DETECT_VM_CLEARTEXT_NETWORK) != 0;
     }
 
     /** @hide */
     public static boolean vmContentUriWithoutPermissionEnabled() {
-        return (sVmPolicyMask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
+        return (sVmPolicy.mask & DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION) != 0;
     }
 
     /** @hide */
     public static boolean vmUntaggedSocketEnabled() {
-        return (sVmPolicyMask & DETECT_VM_UNTAGGED_SOCKET) != 0;
+        return (sVmPolicy.mask & DETECT_VM_UNTAGGED_SOCKET) != 0;
     }
 
     /** @hide */
@@ -1827,7 +1830,7 @@
     /** @hide */
     public static void onFileUriExposed(Uri uri, String location) {
         final String message = uri + " exposed beyond app through " + location;
-        if ((sVmPolicyMask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
+        if ((sVmPolicy.mask & PENALTY_DEATH_ON_FILE_URI_EXPOSURE) != 0) {
             throw new FileUriExposedException(message);
         } else {
             onVmPolicyViolation(null, new Throwable(message));
@@ -1873,7 +1876,7 @@
             }
         }
 
-        final boolean forceDeath = (sVmPolicyMask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
+        final boolean forceDeath = (sVmPolicy.mask & PENALTY_DEATH_ON_CLEARTEXT_NETWORK) != 0;
         onVmPolicyViolation(
                 HexDump.dumpHexString(firstPacket).trim(), new Throwable(msg), forceDeath);
     }
@@ -1898,10 +1901,10 @@
     /** @hide */
     public static void onVmPolicyViolation(
             String message, Throwable originStack, boolean forceDeath) {
-        final boolean penaltyDropbox = (sVmPolicyMask & PENALTY_DROPBOX) != 0;
-        final boolean penaltyDeath = ((sVmPolicyMask & PENALTY_DEATH) != 0) || forceDeath;
-        final boolean penaltyLog = (sVmPolicyMask & PENALTY_LOG) != 0;
-        final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicyMask);
+        final boolean penaltyDropbox = (sVmPolicy.mask & PENALTY_DROPBOX) != 0;
+        final boolean penaltyDeath = ((sVmPolicy.mask & PENALTY_DEATH) != 0) || forceDeath;
+        final boolean penaltyLog = (sVmPolicy.mask & PENALTY_LOG) != 0;
+        final ViolationInfo info = new ViolationInfo(message, originStack, sVmPolicy.mask);
 
         // Erase stuff not relevant for process-wide violations
         info.numAnimationsRunning = 0;
@@ -1929,7 +1932,7 @@
             Log.e(TAG, message, originStack);
         }
 
-        int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicyMask);
+        int violationMaskSubset = PENALTY_DROPBOX | (ALL_VM_DETECT_BITS & sVmPolicy.mask);
 
         if (penaltyDropbox && !penaltyDeath) {
             // Common case for userdebug/eng builds.  If no death and
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 040a1d8..8a374406 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1689,6 +1689,10 @@
         } else {
             layout.draw(canvas, highlight, highlightPaint, cursorOffsetVertical);
         }
+
+        if (mSelectionActionModeHelper != null) {
+            mSelectionActionModeHelper.onDraw(canvas);
+        }
     }
 
     private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highlight,
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index f1b36274..57a3468 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -21,6 +21,7 @@
 import android.annotation.UiThread;
 import android.annotation.WorkerThread;
 import android.content.Context;
+import android.graphics.Canvas;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.os.AsyncTask;
@@ -73,6 +74,9 @@
     private AsyncTask mTextClassificationAsyncTask;
 
     private final SelectionTracker mSelectionTracker;
+
+    // TODO remove nullable marker once the switch gating the feature gets removed
+    @Nullable
     private final SmartSelectSprite mSmartSelectSprite;
 
     SelectionActionModeHelper(@NonNull Editor editor) {
@@ -85,7 +89,8 @@
                 new SelectionTracker(mTextView.getContext(), mTextView.isTextEditable());
 
         if (SMART_SELECT_ANIMATION_ENABLED) {
-            mSmartSelectSprite = new SmartSelectSprite(mTextView);
+            mSmartSelectSprite = new SmartSelectSprite(mTextView.getContext(),
+                    mTextView::invalidate);
         } else {
             mSmartSelectSprite = null;
         }
@@ -167,6 +172,12 @@
         cancelAsyncTask();
     }
 
+    public void onDraw(final Canvas canvas) {
+        if (mSmartSelectSprite != null) {
+            mSmartSelectSprite.draw(canvas);
+        }
+    }
+
     private void cancelAsyncTask() {
         if (mTextClassificationAsyncTask != null) {
             mTextClassificationAsyncTask.cancel(true);
@@ -235,19 +246,6 @@
             return;
         }
 
-        /*
-         * TODO Figure out a more robust approach for this
-         * We have to translate all the generated rectangles by the top-left padding of the
-         * TextView because the padding influences the rendering of the ViewOverlay, but is not
-         * taken into account when generating the selection path rectangles.
-         */
-        for (RectF rectangle : selectionRectangles) {
-            rectangle.left += mTextView.getPaddingLeft();
-            rectangle.right += mTextView.getPaddingLeft();
-            rectangle.top += mTextView.getPaddingTop();
-            rectangle.bottom += mTextView.getPaddingTop();
-        }
-
         final PointF touchPoint = new PointF(
                 mEditor.getLastUpPositionX(),
                 mEditor.getLastUpPositionY());
diff --git a/core/java/android/widget/SmartSelectSprite.java b/core/java/android/widget/SmartSelectSprite.java
index 8d06f5f..27b93bc 100644
--- a/core/java/android/widget/SmartSelectSprite.java
+++ b/core/java/android/widget/SmartSelectSprite.java
@@ -36,11 +36,11 @@
 import android.graphics.drawable.ShapeDrawable;
 import android.graphics.drawable.shapes.Shape;
 import android.util.TypedValue;
-import android.view.View;
-import android.view.ViewOverlay;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 
+import com.android.internal.util.Preconditions;
+
 import java.lang.annotation.Retention;
 import java.util.Collections;
 import java.util.Comparator;
@@ -50,7 +50,6 @@
 /**
  * A utility class for creating and animating the Smart Select animation.
  */
-// TODO Do not rely on ViewOverlays for drawing the Smart Select sprite
 final class SmartSelectSprite {
 
     private static final int EXPAND_DURATION = 300;
@@ -65,8 +64,8 @@
     private final Interpolator mCornerInterpolator;
     private final float mStrokeWidth;
 
-    private final View mView;
     private Animator mActiveAnimator = null;
+    private final Runnable mInvalidator;
     @ColorInt
     private final int mStrokeColor;
 
@@ -331,8 +330,12 @@
 
     }
 
-    SmartSelectSprite(final View view) {
-        final Context context = view.getContext();
+    /**
+     * @param context     The {@link Context} in which the animation will run
+     * @param invalidator A {@link Runnable} which will be called every time the animation updates,
+     *                    indicating that the view drawing the animation should invalidate itself
+     */
+    SmartSelectSprite(final Context context, final Runnable invalidator) {
         mExpandInterpolator = AnimationUtils.loadInterpolator(
                 context,
                 android.R.interpolator.fast_out_slow_in);
@@ -341,7 +344,7 @@
                 android.R.interpolator.fast_out_linear_in);
         mStrokeWidth = dpToPixel(context, STROKE_WIDTH_DP);
         mStrokeColor = getStrokeColor(context);
-        mView = view;
+        mInvalidator = Preconditions.checkNotNull(invalidator);
     }
 
     /**
@@ -366,7 +369,7 @@
         cancelAnimation();
 
         final ValueAnimator.AnimatorUpdateListener updateListener =
-                valueAnimator -> mView.invalidate();
+                valueAnimator -> mInvalidator.run();
 
         final List<RoundedRectangleShape> shapes = new LinkedList<>();
         final List<Animator> cornerAnimators = new LinkedList<>();
@@ -421,7 +424,6 @@
 
         mExistingRectangleList = rectangleList;
         mExistingDrawable = shapeDrawable;
-        mView.getOverlay().add(shapeDrawable);
 
         mActiveAnimator = createAnimator(rectangleList, startingOffsetLeft, startingOffsetRight,
                 cornerAnimators, updateListener,
@@ -480,7 +482,7 @@
             @Override
             public void onAnimationEnd(Animator animator) {
                 mExistingRectangleList.setDisplayType(RectangleList.DisplayType.POLYGON);
-                mExistingDrawable.invalidateSelf();
+                mInvalidator.run();
 
                 onAnimationEnd.run();
             }
@@ -581,11 +583,9 @@
     }
 
     private void removeExistingDrawables() {
-        final ViewOverlay overlay = mView.getOverlay();
-        overlay.remove(mExistingDrawable);
-
         mExistingDrawable = null;
         mExistingRectangleList = null;
+        mInvalidator.run();
     }
 
     /**
@@ -599,4 +599,10 @@
         }
     }
 
+    public void draw(Canvas canvas) {
+        if (mExistingDrawable != null) {
+            mExistingDrawable.draw(canvas);
+        }
+    }
+
 }
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 54afc95..2cab009 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1470,10 +1470,8 @@
             }
 
             final int oldHeight = holder.row.getLayoutParams().height;
-            int measuredRowHeight = holder.measuredRowHeight + holder.row.getPaddingTop()
-                    + holder.row.getPaddingBottom();
             holder.row.getLayoutParams().height = Math.max(1,
-                    (int) (measuredRowHeight * getRowScale(rowPosition)));
+                    (int) (holder.measuredRowHeight * getRowScale(rowPosition)));
             if (holder.row.getLayoutParams().height != oldHeight) {
                 holder.row.requestLayout();
             }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 8ea0242..a413283 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -18,6 +18,9 @@
 
 import android.app.WindowConfiguration;
 import android.graphics.Outline;
+import android.graphics.drawable.InsetDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.util.Pair;
 import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityNodeInfo;
 import com.android.internal.R;
@@ -1097,8 +1100,8 @@
             boolean navBarToLeftEdge = isNavBarToLeftEdge(mLastBottomInset, mLastLeftInset);
             int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset, mLastLeftInset);
             updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
-                    mWindow.mNavigationBarColor, navBarSize, navBarToRightEdge || navBarToLeftEdge,
-                    navBarToLeftEdge,
+                    mWindow.mNavigationBarColor, mWindow.mNavigationBarDividerColor, navBarSize,
+                    navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
                     0 /* sideInset */, animate && !disallowAnimate, false /* force */);
 
             boolean statusBarNeedsRightInset = navBarToRightEdge
@@ -1108,7 +1111,7 @@
             int statusBarSideInset = statusBarNeedsRightInset ? mLastRightInset
                     : statusBarNeedsLeftInset ? mLastLeftInset : 0;
             updateColorViewInt(mStatusColorViewState, sysUiVisibility,
-                    calculateStatusBarColor(), mLastTopInset,
+                    calculateStatusBarColor(), 0, mLastTopInset,
                     false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
                     animate && !disallowAnimate,
                     mForceWindowDrawsStatusBarBackground);
@@ -1195,6 +1198,7 @@
      * @param state the color view to update.
      * @param sysUiVis the current systemUiVisibility to apply.
      * @param color the current color to apply.
+     * @param dividerColor the current divider color to apply.
      * @param size the current size in the non-parent-matching dimension.
      * @param verticalBar if true the view is attached to a vertical edge, otherwise to a
      *                    horizontal edge,
@@ -1202,7 +1206,7 @@
      * @param animate if true, the change will be animated.
      */
     private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
-            int size, boolean verticalBar, boolean seascape, int sideMargin,
+            int dividerColor, int size, boolean verticalBar, boolean seascape, int sideMargin,
             boolean animate, boolean force) {
         state.present = state.attributes.isPresent(sysUiVis, mWindow.getAttributes().flags, force);
         boolean show = state.attributes.isVisible(state.present, color,
@@ -1221,7 +1225,7 @@
         if (view == null) {
             if (showView) {
                 state.view = view = new View(mContext);
-                view.setBackgroundColor(color);
+                setColor(view, color, dividerColor, verticalBar, seascape);
                 view.setTransitionName(state.attributes.transitionName);
                 view.setId(state.attributes.id);
                 visibilityChanged = true;
@@ -1256,7 +1260,7 @@
                 view.setLayoutParams(lp);
             }
             if (showView) {
-                view.setBackgroundColor(color);
+                setColor(view, color, dividerColor, verticalBar, seascape);
             }
         }
         if (visibilityChanged) {
@@ -1289,6 +1293,33 @@
         state.color = color;
     }
 
+    private static void setColor(View v, int color, int dividerColor, boolean verticalBar,
+            boolean seascape) {
+        if (dividerColor != 0) {
+            final Pair<Boolean, Boolean> dir = (Pair<Boolean, Boolean>) v.getTag();
+            if (dir == null || dir.first != verticalBar || dir.second != seascape) {
+                final int size = Math.round(
+                        TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
+                                v.getContext().getResources().getDisplayMetrics()));
+                // Use an inset to make the divider line on the side that faces the app.
+                final InsetDrawable d = new InsetDrawable(new ColorDrawable(color),
+                        verticalBar && !seascape ? size : 0,
+                        !verticalBar ? size : 0,
+                        verticalBar && seascape ? size : 0, 0);
+                v.setBackground(new LayerDrawable(new Drawable[] {
+                        new ColorDrawable(dividerColor), d }));
+                v.setTag(new Pair<>(verticalBar, seascape));
+            } else {
+                final LayerDrawable d = (LayerDrawable) v.getBackground();
+                final InsetDrawable inset = ((InsetDrawable) d.getDrawable(0));
+                ((ColorDrawable) inset.getDrawable()).setColor(dividerColor);
+                ((ColorDrawable) d.getDrawable(1)).setColor(color);
+            }
+        } else {
+            v.setBackgroundColor(color);
+        }
+    }
+
     private void updateColorViewTranslations() {
         // Put the color views back in place when they get moved off the screen
         // due to the the ViewRootImpl panning.
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 0d66376..2de9537 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -233,6 +233,7 @@
     private int mTextColor = 0;
     int mStatusBarColor = 0;
     int mNavigationBarColor = 0;
+    int mNavigationBarDividerColor = 0;
     private boolean mForcedStatusBarColor = false;
     private boolean mForcedNavigationBarColor = false;
 
@@ -2432,6 +2433,8 @@
         }
         if (!mForcedNavigationBarColor) {
             mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
+            mNavigationBarDividerColor = a.getColor(R.styleable.Window_navigationBarDividerColor,
+                    0x00000000);
         }
 
         WindowManager.LayoutParams params = getAttributes();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 0d15758..f85333eb 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -803,12 +803,14 @@
                         + "of length " + MIN_LOCK_PASSWORD_SIZE);
             }
 
-            final int computedQuality = PasswordMetrics.computeForPassword(password).quality;
-            setLong(PASSWORD_TYPE_KEY, Math.max(requestedQuality, computedQuality), userHandle);
+            setLong(PASSWORD_TYPE_KEY,
+                    computePasswordQuality(CREDENTIAL_TYPE_PASSWORD, password, requestedQuality),
+                    userHandle);
             getLockSettings().setLockCredential(password, CREDENTIAL_TYPE_PASSWORD, savedPassword,
                     requestedQuality, userHandle);
 
-            updateEncryptionPasswordIfNeeded(password, computedQuality, userHandle);
+            updateEncryptionPasswordIfNeeded(password,
+                    PasswordMetrics.computeForPassword(password).quality, userHandle);
             updatePasswordHistory(password, userHandle);
         } catch (RemoteException re) {
             // Cant do much
@@ -898,6 +900,24 @@
     }
 
     /**
+     * Returns the password quality of the given credential, promoting it to a higher level
+     * if DevicePolicyManager has a stronger quality requirement. This value will be written
+     * to PASSWORD_TYPE_KEY.
+     */
+    private int computePasswordQuality(int type, String credential, int requestedQuality) {
+        final int quality;
+        if (type == CREDENTIAL_TYPE_PASSWORD) {
+            int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
+            quality = Math.max(requestedQuality, computedQuality);
+        } else if (type == CREDENTIAL_TYPE_PATTERN)  {
+            quality = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+        } else /* if (type == CREDENTIAL_TYPE_NONE) */ {
+            quality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+        }
+        return quality;
+    }
+
+    /**
      * Enables/disables the Separate Profile Challenge for this {@param userHandle}. This is a no-op
      * for user handles that do not belong to a managed profile.
      *
@@ -1505,25 +1525,34 @@
         }
     }
 
-    public boolean setLockCredentialWithToken(String credential, int type, long tokenHandle,
-            byte[] token, int userId) {
+    /**
+     * Change a user's lock credential with a pre-configured escrow token.
+     *
+     * @param credential The new credential to be set
+     * @param type Credential type: password / pattern / none.
+     * @param requestedQuality the requested password quality by DevicePolicyManager.
+     *        See {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
+     * @param tokenHandle Handle of the escrow token
+     * @param token Escrow token
+     * @param userId The user who's lock credential to be changed
+     * @return {@code true} if the operation is successful.
+     */
+    public boolean setLockCredentialWithToken(String credential, int type, int requestedQuality,
+            long tokenHandle, byte[] token, int userId) {
         try {
             if (type != CREDENTIAL_TYPE_NONE) {
                 if (TextUtils.isEmpty(credential) || credential.length() < MIN_LOCK_PASSWORD_SIZE) {
                     throw new IllegalArgumentException("password must not be null and at least "
                             + "of length " + MIN_LOCK_PASSWORD_SIZE);
                 }
-
-                final int computedQuality = PasswordMetrics.computeForPassword(credential).quality;
-                int quality = Math.max(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
-                        computedQuality);
+                final int quality = computePasswordQuality(type, credential, requestedQuality);
                 if (!getLockSettings().setLockCredentialWithToken(credential, type, tokenHandle,
                         token, quality, userId)) {
                     return false;
                 }
                 setLong(PASSWORD_TYPE_KEY, quality, userId);
 
-                updateEncryptionPasswordIfNeeded(credential, computedQuality, userId);
+                updateEncryptionPasswordIfNeeded(credential, quality, userId);
                 updatePasswordHistory(credential, userId);
             } else {
                 if (!TextUtils.isEmpty(credential)) {
diff --git a/core/jni/android_os_VintfObject.cpp b/core/jni/android_os_VintfObject.cpp
index 7ec4b8e..5ef2a9e 100644
--- a/core/jni/android_os_VintfObject.cpp
+++ b/core/jni/android_os_VintfObject.cpp
@@ -56,7 +56,7 @@
 }
 
 template<typename T>
-static void tryAddSchema(const T* object, const XmlConverter<T>& converter,
+static void tryAddSchema(const std::shared_ptr<const T>& object, const XmlConverter<T>& converter,
         const std::string& description,
         std::vector<std::string>* cStrings) {
     if (object == nullptr) {
@@ -66,7 +66,7 @@
     }
 }
 
-static void tryAddHalNamesAndVersions(const HalManifest *manifest,
+static void tryAddHalNamesAndVersions(const std::shared_ptr<const HalManifest>& manifest,
         const std::string& description,
         std::set<std::string> *output) {
     if (manifest == nullptr) {
@@ -119,7 +119,7 @@
 }
 
 static jstring android_os_VintfObject_getSepolicyVersion(JNIEnv* env, jclass) {
-    const HalManifest *manifest = VintfObject::GetDeviceHalManifest();
+    std::shared_ptr<const HalManifest> manifest = VintfObject::GetDeviceHalManifest();
     if (manifest == nullptr || manifest->type() != SchemaType::DEVICE) {
         LOG(WARNING) << __FUNCTION__ << "Cannot get device manifest";
         return nullptr;
@@ -129,7 +129,7 @@
 }
 
 static jobject android_os_VintfObject_getVndkSnapshots(JNIEnv* env, jclass) {
-    const HalManifest *manifest = VintfObject::GetFrameworkHalManifest();
+    std::shared_ptr<const HalManifest> manifest = VintfObject::GetFrameworkHalManifest();
     if (manifest == nullptr || manifest->type() != SchemaType::FRAMEWORK) {
         LOG(WARNING) << __FUNCTION__ << "Cannot get framework manifest";
         return nullptr;
diff --git a/core/jni/android_os_VintfRuntimeInfo.cpp b/core/jni/android_os_VintfRuntimeInfo.cpp
index 19220cf0..315eac1 100644
--- a/core/jni/android_os_VintfRuntimeInfo.cpp
+++ b/core/jni/android_os_VintfRuntimeInfo.cpp
@@ -32,7 +32,7 @@
 #define MAP_STRING_METHOD(javaMethod, cppString)                                       \
     static jstring android_os_VintfRuntimeInfo_##javaMethod(JNIEnv* env, jclass clazz) \
     {                                                                                  \
-        const RuntimeInfo *info = VintfObject::GetRuntimeInfo();                       \
+        std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo();       \
         if (info == nullptr) return nullptr;                                           \
         return env->NewStringUTF((cppString).c_str());                                 \
     }                                                                                  \
@@ -50,7 +50,7 @@
 
 static jlong android_os_VintfRuntimeInfo_getKernelSepolicyVersion(JNIEnv *env, jclass clazz)
 {
-    const RuntimeInfo *info = VintfObject::GetRuntimeInfo();
+    std::shared_ptr<const RuntimeInfo> info = VintfObject::GetRuntimeInfo();
     if (info == nullptr) return 0;
     return static_cast<jlong>(info->kernelSepolicyVersion());
 }
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 2f5b2e2..57263b1 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -889,7 +889,7 @@
     // Render into the surface
     {
         ContextFactory factory;
-        RenderProxy proxy{false, renderNode, &factory};
+        RenderProxy proxy{true, renderNode, &factory};
         proxy.loadSystemProperties();
         proxy.setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
         proxy.initialize(surface);
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 598b586..81c6c1d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2055,6 +2055,14 @@
              Corresponds to {@link android.view.Window#setNavigationBarColor(int)}. -->
         <attr name="navigationBarColor" format="color" />
 
+        <!-- @hide
+             Shows 1dp line of the specified color between the navigation bar and the app content.
+             <p>For this to take effect, the window must be drawing the system bar backgrounds with
+             {@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not
+               have been requested to be translucent with
+             {@link android.R.attr#windowTranslucentNavigation}. -->
+        <attr name="navigationBarDividerColor" format="color" />
+
         <!-- The duration, in milliseconds, of the window background fade duration
              when transitioning into or away from an Activity when called with an
              Activity Transition. Corresponds to
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 8755e37..bf0c906 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -745,6 +745,11 @@
         <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
         <item name="colorAccent">@color/accent_device_default_light</item>
         <item name="colorEdgeEffect">@android:color/black</item>
+
+        <!-- Add white nav bar with divider that matches material -->
+        <item name="navigationBarDividerColor">#1f000000</item>
+        <item name="navigationBarColor">@android:color/white</item>
+        <item name="windowLightNavigationBar">true</item>
     </style>
 
     <!-- @hide DeviceDefault theme for a window that should use Settings theme colors
diff --git a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
index 2470e87..d289f1f 100644
--- a/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
+++ b/core/tests/coretests/src/android/app/admin/PasswordMetricsTest.java
@@ -17,6 +17,7 @@
 package android.app.admin;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
@@ -119,4 +120,48 @@
         // ordered, but not composed of alphas or digits
         assertEquals(1, PasswordMetrics.maxLengthSequence(":;<=>"));
     }
+
+    @Test
+    public void testEquals() {
+        PasswordMetrics metrics0 = new PasswordMetrics();
+        PasswordMetrics metrics1 = new PasswordMetrics();
+        assertNotEquals(metrics0, null);
+        assertNotEquals(metrics0, new Object());
+        assertEquals(metrics0, metrics0);
+        assertEquals(metrics0, metrics1);
+
+        assertEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
+                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4));
+
+        assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
+                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 5));
+
+        assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
+                new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 4));
+
+        metrics0 = PasswordMetrics.computeForPassword("1234abcd,./");
+        metrics1 = PasswordMetrics.computeForPassword("1234abcd,./");
+        assertEquals(metrics0, metrics1);
+        metrics1.letters++;
+        assertNotEquals(metrics0, metrics1);
+        metrics1.letters--;
+        metrics1.upperCase++;
+        assertNotEquals(metrics0, metrics1);
+        metrics1.upperCase--;
+        metrics1.lowerCase++;
+        assertNotEquals(metrics0, metrics1);
+        metrics1.lowerCase--;
+        metrics1.numeric++;
+        assertNotEquals(metrics0, metrics1);
+        metrics1.numeric--;
+        metrics1.symbols++;
+        assertNotEquals(metrics0, metrics1);
+        metrics1.symbols--;
+        metrics1.nonLetter++;
+        assertNotEquals(metrics0, metrics1);
+        metrics1.nonLetter--;
+        assertEquals(metrics0, metrics1);
+
+
+    }
 }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 1f55232..7a2df85 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -280,6 +280,7 @@
         <permission name="android.permission.MOUNT_FORMAT_FILESYSTEMS"/>
         <permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
         <permission name="android.permission.MOVE_PACKAGE"/>
+        <permission name="android.permission.PACKAGE_USAGE_STATS" />
         <permission name="android.permission.READ_FRAME_BUFFER"/>
         <permission name="android.permission.REAL_GET_TASKS"/>
         <permission name="android.permission.REGISTER_CALL_PROVIDER"/>
diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk
index ef2950b..0e6b31e 100644
--- a/legacy-test/Android.mk
+++ b/legacy-test/Android.mk
@@ -94,11 +94,10 @@
 
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(legacy_test_api_gen_stamp)
-$(full_classes_jack) : $(legacy_test_api_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(legacy_test_api_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):legacy.test.stubs.jar)
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 742f14d..a967d2a 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -83,7 +83,8 @@
 
 void SkiaPipeline::renderLayersImpl(const LayerUpdateQueue& layers,
         bool opaque, bool wideColorGamut) {
-    // TODO: Handle wide color gamut
+    sk_sp<GrContext> cachedContext;
+
     // Render all layers that need to be updated, in order.
     for (size_t i = 0; i < layers.entries().size(); i++) {
         RenderNode* layerNode = layers.entries()[i].renderNode.get();
@@ -126,10 +127,23 @@
             RenderNodeDrawable root(layerNode, layerCanvas, false);
             root.forceDraw(layerCanvas);
             layerCanvas->restoreToCount(saveCount);
-            layerCanvas->flush();
             mLightCenter = savedLightCenter;
+
+            // cache the current context so that we can defer flushing it until
+            // either all the layers have been rendered or the context changes
+            GrContext* currentContext = layerCanvas->getGrContext();
+            if (cachedContext.get() != currentContext) {
+                if (cachedContext.get()) {
+                    cachedContext->flush();
+                }
+                cachedContext.reset(SkSafeRef(currentContext));
+            }
         }
     }
+
+    if (cachedContext.get()) {
+        cachedContext->flush();
+    }
 }
 
 bool SkiaPipeline::createOrUpdateLayer(RenderNode* node,
diff --git a/packages/MtpDocumentsProvider/tests/AndroidTest.xml b/packages/MtpDocumentsProvider/tests/AndroidTest.xml
index d0b4c6e..940d364 100644
--- a/packages/MtpDocumentsProvider/tests/AndroidTest.xml
+++ b/packages/MtpDocumentsProvider/tests/AndroidTest.xml
@@ -21,7 +21,7 @@
     <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="MtpDocumentsProviderTests" />
     <test class="com.android.tradefed.testtype.InstrumentationTest" >
-        <option name="package" value="com.android.mtp" />
-        <option name="runner" value="android.test.InstrumentationTestRunner" />
+        <option name="package" value="com.android.mtp.tests" />
+        <option name="runner" value="com.android.mtp.TestResultInstrumentation" />
     </test>
 </configuration>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 37969e0..dd629c4 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -494,23 +494,6 @@
         int oldSpeed = mSpeed;
         mSpeed = generateAverageSpeedForSsid();
 
-        // set speed to the connected ScanResult if the AccessPoint is the active network
-        if (isActive() && mInfo != null) {
-            TimestampedScoredNetwork timedScore = mScoredNetworkCache.get(mInfo.getBSSID());
-            if (timedScore != null) {
-                if (Log.isLoggable(TAG, Log.DEBUG)) {
-                    Log.d(TAG, "Set score using specific access point curve for connected AP: "
-                            + getSsidStr());
-                }
-                // TODO(b/63073866): Map using getLevel rather than specific rssi value so score
-                // doesn't change without a visible wifi bar change.
-                int speed = timedScore.getScore().calculateBadge(mInfo.getRssi());
-                if (speed != Speed.NONE) {
-                    mSpeed = speed;
-                }
-            }
-        }
-
         boolean changed = oldSpeed != mSpeed;
         if(WifiTracker.sVerboseLogging && changed) {
             Log.i(TAG, String.format("%s: Set speed to %d", ssid, mSpeed));
@@ -529,6 +512,10 @@
                     getSsidStr(), mScoredNetworkCache));
         }
 
+        // TODO(b/63073866): If flickering issues persist, consider mapping using getLevel rather
+        // than specific rssi value so score doesn't change without a visible wifi bar change. This
+        // issue is likely to be more evident for the active AP whose RSSI value is not half-lifed.
+
         int count = 0;
         int totalSpeed = 0;
         for (TimestampedScoredNetwork timedScore : mScoredNetworkCache.values()) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index 2f0b51b..fdbbf14 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -155,7 +155,7 @@
             drawable.setLevel(mLevel);
         }
 
-        mTitleView = (TextView) view.findViewById(com.android.internal.R.id.title);
+        mTitleView = (TextView) view.findViewById(android.R.id.title);
         if (mTitleView != null) {
             // Attach to the end of the title view
             mTitleView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, mBadge, null);
@@ -224,12 +224,7 @@
      * Updates the title and summary; may indirectly call notifyChanged().
      */
     public void refresh() {
-        if (mForSavedNetworks) {
-            setTitle(mAccessPoint.getConfigName());
-        } else {
-            setTitle(mAccessPoint.getSsid());
-        }
-
+        setTitle(this, mAccessPoint, mForSavedNetworks);
         final Context context = getContext();
         int level = mAccessPoint.getLevel();
         int wifiSpeed = mAccessPoint.getSpeed();
@@ -258,6 +253,15 @@
         }
     }
 
+    @VisibleForTesting
+    static void setTitle(AccessPointPreference preference, AccessPoint ap, boolean savedNetworks) {
+        if (savedNetworks) {
+            preference.setTitle(ap.getConfigName());
+        } else {
+            preference.setTitle(ap.getSsidStr());
+        }
+    }
+
     /**
      * Helper method to generate content description string.
      */
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 6f1b25f..b678b3a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -417,56 +417,6 @@
     }
 
     @Test
-    public void testSpeedLabel_isDerivedFromConnectedBssidWhenScoreAvailable() {
-        int rssi = -55;
-        String bssid = "00:00:00:00:00:00";
-        int networkId = 123;
-
-        WifiInfo info = new WifiInfo();
-        info.setRssi(rssi);
-        info.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
-        info.setBSSID(bssid);
-        info.setNetworkId(networkId);
-
-        ArrayList<ScanResult> scanResults = new ArrayList<>();
-        ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi);
-        scanResults.add(scanResultUnconnected);
-
-        ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi);
-        scanResults.add(scanResultConnected);
-
-        AccessPoint ap =
-                new TestAccessPointBuilder(mContext)
-                        .setActive(true)
-                        .setNetworkId(networkId)
-                        .setSsid(TEST_SSID)
-                        .setScanResultCache(scanResults)
-                        .setWifiInfo(info)
-                        .build();
-
-        when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultUnconnected))
-                .thenReturn(buildScoredNetworkWithMockBadgeCurve());
-        when(mockBadgeCurve.lookupScore(anyInt())).thenReturn((byte) Speed.SLOW);
-
-        int connectedSpeed = Speed.VERY_FAST;
-        RssiCurve connectedBadgeCurve = mock(RssiCurve.class);
-        Bundle attr1 = new Bundle();
-        attr1.putParcelable(ScoredNetwork.ATTRIBUTES_KEY_BADGING_CURVE, connectedBadgeCurve);
-        ScoredNetwork connectedScore = new ScoredNetwork(
-                NetworkKey.createFromScanResult(scanResultConnected),
-                connectedBadgeCurve,
-                false /* meteredHint */,
-                attr1);
-        when(mockWifiNetworkScoreCache.getScoredNetwork(scanResultConnected))
-                .thenReturn(connectedScore);
-        when(connectedBadgeCurve.lookupScore(anyInt())).thenReturn((byte) connectedSpeed);
-
-        ap.update(mockWifiNetworkScoreCache, true /* scoringUiEnabled */);
-
-        assertThat(ap.getSpeed()).isEqualTo(connectedSpeed);
-    }
-
-    @Test
     public void testSummaryString_showsSpeedLabel() {
         AccessPoint ap = createAccessPointWithScanResultCache();
 
@@ -940,7 +890,7 @@
     }
 
     @Test
-    public void testSpeedLabelUsesFallbackScoreWhenConnectedAccessPointScoreUnavailable() {
+    public void testSpeedLabelFallbackScoreIgnoresNullCurves() {
         int rssi = -55;
         String bssid = "00:00:00:00:00:00";
         int networkId = 123;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
index 5c99194..a4c821f 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/AccessPointPreferenceTest.java
@@ -18,13 +18,12 @@
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
-
 import android.graphics.drawable.ColorDrawable;
+
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 import com.android.settingslib.TestConfig;
 
@@ -42,9 +41,12 @@
 
     private Context mContext = RuntimeEnvironment.application;
 
-    @Mock private AccessPoint mockAccessPoint;
-    @Mock private AccessPointPreference.UserBadgeCache mockUserBadgeCache;
-    @Mock private AccessPointPreference.IconInjector mockIconInjector;
+    @Mock
+    private AccessPoint mockAccessPoint;
+    @Mock
+    private AccessPointPreference.UserBadgeCache mockUserBadgeCache;
+    @Mock
+    private AccessPointPreference.IconInjector mockIconInjector;
 
     private AccessPointPreference createWithAccessPoint(AccessPoint accessPoint) {
         return new AccessPointPreference(accessPoint, mContext, mockUserBadgeCache,
@@ -115,4 +117,19 @@
 
         verify(mockIconInjector).getIcon(level);
     }
+
+    @Test
+    public void refresh_setTitle_shouldUseSsidString() {
+        final String ssid = "ssid";
+        final String summary = "connected";
+        final int security = AccessPoint.SECURITY_WEP;
+        final AccessPoint ap = new TestAccessPointBuilder(mContext)
+                .setSsid(ssid)
+                .setSecurity(security)
+                .build();
+        final AccessPointPreference preference = mock(AccessPointPreference.class);
+
+        AccessPointPreference.setTitle(preference, ap, false /* savedNetwork */);
+        verify(preference).setTitle(ssid);
+    }
 }
diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml
index 95cb73a..7e72dfb 100644
--- a/packages/SettingsProvider/res/values-bn/strings.xml
+++ b/packages/SettingsProvider/res/values-bn/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4567566098528588863">"সেটিংস সঞ্চয়স্থান"</string>
+    <string name="app_label" msgid="4567566098528588863">"সেটিংস স্টোরেজ"</string>
 </resources>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index bd1ebb9..b758e7f5 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -62,6 +62,7 @@
     <!-- Internal permissions granted to the shell. -->
     <uses-permission android:name="android.permission.FORCE_BACK" />
     <uses-permission android:name="android.permission.BATTERY_STATS" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
     <uses-permission android:name="android.permission.INJECT_EVENTS" />
     <uses-permission android:name="android.permission.RETRIEVE_WINDOW_CONTENT" />
diff --git a/packages/SystemUI/res/color/qs_background_dark.xml b/packages/SystemUI/res/color/qs_background_dark.xml
index 62e4959..c19fa08 100644
--- a/packages/SystemUI/res/color/qs_background_dark.xml
+++ b/packages/SystemUI/res/color/qs_background_dark.xml
@@ -15,6 +15,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.93"
+    <item android:alpha="0.87"
           android:color="?android:attr/colorBackgroundFloating"/>
 </selector>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index bb6213b..c596398 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -38,6 +38,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
@@ -52,6 +53,7 @@
 import android.os.IRemoteCallback;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -157,6 +159,21 @@
     private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
             "com.android.settings", "com.android.settings.FallbackHome");
 
+
+    /**
+     * If true, the system is in the half-boot-to-decryption-screen state.
+     * Prudently disable lockscreen.
+     */
+    public static final boolean CORE_APPS_ONLY;
+    static {
+        try {
+            CORE_APPS_ONLY = IPackageManager.Stub.asInterface(
+                    ServiceManager.getService("package")).isOnlyCoreApps();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     private static KeyguardUpdateMonitor sInstance;
 
     private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 4733008..3eb68f5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1228,6 +1228,12 @@
      * Enable the keyguard if the settings are appropriate.
      */
     private void doKeyguardLocked(Bundle options) {
+        if (KeyguardUpdateMonitor.CORE_APPS_ONLY) {
+            // Don't show keyguard during half-booted cryptkeeper stage.
+            if (DEBUG) Log.d(TAG, "doKeyguard: not showing because booting to cryptkeeper");
+            return;
+        }
+
         // if another app is disabling us, don't show
         if (!mExternallyEnabled) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled");
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 901b0b0..90f7b8d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -55,6 +55,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.View.OnTouchListener;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager.LayoutParams;
@@ -119,6 +120,7 @@
                 }
             };
 
+    private PipTouchState mTouchState;
     private PointF mDownPosition = new PointF();
     private PointF mDownDelta = new PointF();
     private ViewConfiguration mViewConfig;
@@ -175,6 +177,13 @@
         // Set the flags to allow us to watch for outside touches and also hide the menu and start
         // manipulating the PIP in the same touch gesture
         mViewConfig = ViewConfiguration.get(this);
+        mTouchState = new PipTouchState(mViewConfig, mHandler, () -> {
+            if (mMenuState == MENU_STATE_CLOSE) {
+                showPipMenu();
+            } else {
+                expandPip();
+            }
+        });
         getWindow().addFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | LayoutParams.FLAG_SLIPPERY);
 
         super.onCreate(savedInstanceState);
@@ -186,12 +195,28 @@
         mViewRoot.setBackground(mBackgroundDrawable);
         mMenuContainer = findViewById(R.id.menu_container);
         mMenuContainer.setAlpha(0);
-        mMenuContainer.setOnClickListener((v) -> {
-            if (mMenuState == MENU_STATE_CLOSE) {
-                showPipMenu();
-            } else {
-                expandPip();
+        mMenuContainer.setOnTouchListener((v, event) -> {
+            mTouchState.onTouchEvent(event);
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_UP:
+                    if (mTouchState.isDoubleTap() || mMenuState == MENU_STATE_FULL) {
+                        // Expand to fullscreen if this is a double tap or we are already expanded
+                        expandPip();
+                    } else if (!mTouchState.isWaitingForDoubleTap()) {
+                        // User has stalled long enough for this not to be a drag or a double tap,
+                        // just expand the menu if necessary
+                        if (mMenuState == MENU_STATE_CLOSE) {
+                            showPipMenu();
+                        }
+                    } else {
+                        // Next touch event _may_ be the second tap for the double-tap, schedule a
+                        // fallback runnable to trigger the menu if no touch event occurs before the
+                        // next tap
+                        mTouchState.scheduleDoubleTapTimeoutCallback();
+                    }
+                    break;
             }
+            return true;
         });
         mDismissButton = findViewById(R.id.dismiss);
         mDismissButton.setAlpha(0);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index e898a51..34666fb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -211,6 +211,10 @@
         EventBus.getDefault().register(this);
     }
 
+    public boolean isMenuActivityVisible() {
+        return mToActivityMessenger != null;
+    }
+
     public void onActivityPinned() {
         if (mMenuState == MENU_STATE_NONE) {
             // If the menu is not visible, then re-register the input consumer if it is not already
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 3181481..2b48e0f 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -187,13 +187,15 @@
         mMenuController.addListener(mMenuListener);
         mDismissViewController = new PipDismissViewController(context);
         mSnapAlgorithm = new PipSnapAlgorithm(mContext);
-        mTouchState = new PipTouchState(mViewConfig);
         mFlingAnimationUtils = new FlingAnimationUtils(context, 2.5f);
         mGestures = new PipTouchGesture[] {
                 mDefaultMovementGesture
         };
         mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mMenuController,
                 mSnapAlgorithm, mFlingAnimationUtils);
+        mTouchState = new PipTouchState(mViewConfig, mHandler,
+                () -> mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
+                        mMovementBounds, true /* allowMenuTimeout */, willResizeMenu()));
 
         Resources res = context.getResources();
         mExpandedShortestEdgeSize = res.getDimensionPixelSize(
@@ -429,7 +431,7 @@
                 final float distance = bounds.bottom - target;
                 fraction = Math.min(distance / bounds.height(), 1f);
             }
-            if (Float.compare(fraction, 0f) != 0 || mMenuState != MENU_STATE_NONE) {
+            if (Float.compare(fraction, 0f) != 0 || mMenuController.isMenuActivityVisible()) {
                 // Update if the fraction > 0, or if fraction == 0 and the menu was already visible
                 mMenuController.setDismissFraction(fraction);
             }
@@ -730,8 +732,20 @@
                         null /* animatorListener */);
                 setMinimizedStateInternal(false);
             } else if (mMenuState != MENU_STATE_FULL) {
-                mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
-                        mMovementBounds, true /* allowMenuTimeout */, willResizeMenu());
+                if (mTouchState.isDoubleTap()) {
+                    // Expand to fullscreen if this is a double tap
+                    mMotionHelper.expandPip();
+                } else if (!mTouchState.isWaitingForDoubleTap()) {
+                    // User has stalled long enough for this not to be a drag or a double tap, just
+                    // expand the menu
+                    mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
+                            mMovementBounds, true /* allowMenuTimeout */, willResizeMenu());
+                } else {
+                    // Next touch event _may_ be the second tap for the double-tap, schedule a
+                    // fallback runnable to trigger the menu if no touch event occurs before the
+                    // next tap
+                    mTouchState.scheduleDoubleTapTimeoutCallback();
+                }
             } else {
                 mMenuController.hideMenu();
                 mMotionHelper.expandPip();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index 686b3bb..b9369d3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -17,11 +17,15 @@
 package com.android.systemui.pip.phone;
 
 import android.graphics.PointF;
+import android.os.Handler;
+import android.os.SystemClock;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.ViewConfiguration;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.PrintWriter;
 
 /**
@@ -31,9 +35,17 @@
     private static final String TAG = "PipTouchHandler";
     private static final boolean DEBUG = false;
 
-    private ViewConfiguration mViewConfig;
+    @VisibleForTesting
+    static final long DOUBLE_TAP_TIMEOUT = 200;
+
+    private final Handler mHandler;
+    private final ViewConfiguration mViewConfig;
+    private final Runnable mDoubleTapTimeoutCallback;
 
     private VelocityTracker mVelocityTracker;
+    private long mDownTouchTime = 0;
+    private long mLastDownTouchTime = 0;
+    private long mUpTouchTime = 0;
     private final PointF mDownTouch = new PointF();
     private final PointF mDownDelta = new PointF();
     private final PointF mLastTouch = new PointF();
@@ -41,13 +53,22 @@
     private final PointF mVelocity = new PointF();
     private boolean mAllowTouches = true;
     private boolean mIsUserInteracting = false;
+    // Set to true only if the multiple taps occur within the double tap timeout
+    private boolean mIsDoubleTap = false;
+    // Set to true only if a gesture
+    private boolean mIsWaitingForDoubleTap = false;
     private boolean mIsDragging = false;
+    // The previous gesture was a drag
+    private boolean mPreviouslyDragging = false;
     private boolean mStartedDragging = false;
     private boolean mAllowDraggingOffscreen = false;
     private int mActivePointerId;
 
-    public PipTouchState(ViewConfiguration viewConfig) {
+    public PipTouchState(ViewConfiguration viewConfig, Handler handler,
+            Runnable doubleTapTimeoutCallback) {
         mViewConfig = viewConfig;
+        mHandler = handler;
+        mDoubleTapTimeoutCallback = doubleTapTimeoutCallback;
     }
 
     /**
@@ -81,6 +102,14 @@
                 mDownTouch.set(mLastTouch);
                 mAllowDraggingOffscreen = true;
                 mIsUserInteracting = true;
+                mDownTouchTime = ev.getEventTime();
+                mIsDoubleTap = !mPreviouslyDragging &&
+                        (mDownTouchTime - mLastDownTouchTime) < DOUBLE_TAP_TIMEOUT;
+                mIsWaitingForDoubleTap = false;
+                mLastDownTouchTime = mDownTouchTime;
+                if (mDoubleTapTimeoutCallback != null) {
+                    mHandler.removeCallbacks(mDoubleTapTimeoutCallback);
+                }
                 break;
             }
             case MotionEvent.ACTION_MOVE: {
@@ -155,7 +184,11 @@
                     break;
                 }
 
+                mUpTouchTime = ev.getEventTime();
                 mLastTouch.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
+                mPreviouslyDragging = mIsDragging;
+                mIsWaitingForDoubleTap = !mIsDoubleTap && !mIsDragging &&
+                        (mUpTouchTime - mDownTouchTime) < DOUBLE_TAP_TIMEOUT;
 
                 // Fall through to clean up
             }
@@ -251,6 +284,39 @@
         return mAllowDraggingOffscreen;
     }
 
+    /**
+     * @return whether this gesture is a double-tap.
+     */
+    public boolean isDoubleTap() {
+        return mIsDoubleTap;
+    }
+
+    /**
+     * @return whether this gesture will potentially lead to a following double-tap.
+     */
+    public boolean isWaitingForDoubleTap() {
+        return mIsWaitingForDoubleTap;
+    }
+
+    /**
+     * Schedules the callback to run if the next double tap does not occur.  Only runs if
+     * isWaitingForDoubleTap() is true.
+     */
+    public void scheduleDoubleTapTimeoutCallback() {
+        if (mIsWaitingForDoubleTap) {
+            long delay = getDoubleTapTimeoutCallbackDelay();
+            mHandler.removeCallbacks(mDoubleTapTimeoutCallback);
+            mHandler.postDelayed(mDoubleTapTimeoutCallback, delay);
+        }
+    }
+
+    @VisibleForTesting long getDoubleTapTimeoutCallbackDelay() {
+        if (mIsWaitingForDoubleTap) {
+            return Math.max(0, DOUBLE_TAP_TIMEOUT - (mUpTouchTime - mDownTouchTime));
+        }
+        return -1;
+    }
+
     private void initOrResetVelocityTracker() {
         if (mVelocityTracker == null) {
             mVelocityTracker = VelocityTracker.obtain();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7aebfdc5..0575e21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4787,7 +4787,7 @@
             animateCollapsePanels();
             return true;
         }
-        if (mKeyguardUserSwitcher.hideIfNotSimple(true)) {
+        if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) {
             return true;
         }
         return false;
diff --git a/packages/SystemUI/tests/AndroidTest.xml b/packages/SystemUI/tests/AndroidTest.xml
index 6ca42e8..53839a9b 100644
--- a/packages/SystemUI/tests/AndroidTest.xml
+++ b/packages/SystemUI/tests/AndroidTest.xml
@@ -23,6 +23,6 @@
     <option name="test-tag" value="SystemUITests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.systemui.tests" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="android.testing.TestableInstrumentation" />
     </test>
 </configuration>
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java
new file mode 100644
index 0000000..b8c946d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017 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.pip.phone;
+
+import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.pip.phone.PipTouchState;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class PipTouchStateTest extends SysuiTestCase {
+
+    private Handler mHandler;
+    private HandlerThread mHandlerThread;
+    private PipTouchState mTouchState;
+    private CountDownLatch mDoubleTapCallbackTriggeredLatch;
+
+    @Before
+    public void setUp() throws Exception {
+        mHandlerThread = new HandlerThread("PipTouchStateTestThread");
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+
+        mDoubleTapCallbackTriggeredLatch = new CountDownLatch(1);
+        mTouchState = new PipTouchState(ViewConfiguration.get(getContext()),
+                mHandler, () -> {
+            mDoubleTapCallbackTriggeredLatch.countDown();
+        });
+        assertFalse(mTouchState.isDoubleTap());
+        assertFalse(mTouchState.isWaitingForDoubleTap());
+    }
+
+    @Test
+    public void testDoubleTapLongSingleTap_notDoubleTapAndNotWaiting() {
+        final long currentTime = SystemClock.uptimeMillis();
+
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_DOWN, currentTime, 0, 0));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_UP,
+                currentTime + PipTouchState.DOUBLE_TAP_TIMEOUT + 10, 0, 0));
+        assertFalse(mTouchState.isDoubleTap());
+        assertFalse(mTouchState.isWaitingForDoubleTap());
+        assertTrue(mTouchState.getDoubleTapTimeoutCallbackDelay() == -1);
+    }
+
+    @Test
+    public void testDoubleTapTimeout_timeoutCallbackCalled() throws Exception {
+        final long currentTime = SystemClock.uptimeMillis();
+
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_DOWN, currentTime, 0, 0));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_UP,
+                currentTime + PipTouchState.DOUBLE_TAP_TIMEOUT - 10, 0, 0));
+        assertFalse(mTouchState.isDoubleTap());
+        assertTrue(mTouchState.isWaitingForDoubleTap());
+
+        assertTrue(mTouchState.getDoubleTapTimeoutCallbackDelay() == 10);
+        mTouchState.scheduleDoubleTapTimeoutCallback();
+        mDoubleTapCallbackTriggeredLatch.await(1, TimeUnit.SECONDS);
+        assertTrue(mDoubleTapCallbackTriggeredLatch.getCount() == 0);
+    }
+
+    @Test
+    public void testDoubleTapDrag_doubleTapCanceled() {
+        final long currentTime = SystemClock.uptimeMillis();
+
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_DOWN, currentTime, 0, 0));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_MOVE, currentTime + 10, 500, 500));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_UP, currentTime + 20, 500, 500));
+        assertTrue(mTouchState.isDragging());
+        assertFalse(mTouchState.isDoubleTap());
+        assertFalse(mTouchState.isWaitingForDoubleTap());
+        assertTrue(mTouchState.getDoubleTapTimeoutCallbackDelay() == -1);
+    }
+
+    @Test
+    public void testDoubleTap_doubleTapRegistered() {
+        final long currentTime = SystemClock.uptimeMillis();
+
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_DOWN, currentTime, 0, 0));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_UP, currentTime + 10, 0, 0));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_DOWN,
+                currentTime + PipTouchState.DOUBLE_TAP_TIMEOUT - 20, 0, 0));
+        mTouchState.onTouchEvent(createMotionEvent(ACTION_UP,
+                currentTime + PipTouchState.DOUBLE_TAP_TIMEOUT - 10, 0, 0));
+        assertTrue(mTouchState.isDoubleTap());
+        assertFalse(mTouchState.isWaitingForDoubleTap());
+        assertTrue(mTouchState.getDoubleTapTimeoutCallbackDelay() == -1);
+    }
+
+    private MotionEvent createMotionEvent(int action, long eventTime, float x, float y) {
+        return MotionEvent.obtain(0, eventTime, action, x, y, 0);
+    }
+}
\ No newline at end of file
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
index 0c1b0ef..ddac106 100644
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
@@ -6,6 +6,6 @@
         <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
         <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
         <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
-        <item name="android:colorBackgroundFloating">#000</item>
+        <item name="android:colorBackgroundFloating">@*android:color/material_grey_900</item>
     </style>
 </resources>
\ No newline at end of file
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 8e782c0..9fa384a 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -4287,6 +4287,11 @@
     // OS: O MR
     APPLICATIONS_STORAGE_PHOTOS = 1092;
 
+    // ACTION: Logged when user tries to pair a Bluetooth device without name from Settings app
+    // CATEGORY: SETTINGS
+    // OS: O MR
+    ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES = 1093;
+
     // ---- End O-MR1 Constants, all O-MR1 constants go above this line ----
 
     // OPEN: Settings > Network & Internet > Mobile network
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 7ade0eb..cc45e02 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -70,6 +70,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.am.ActivityStackSupervisor.FindTaskResult;
@@ -2061,10 +2062,15 @@
         try {
             final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
                     "makeInvisible", true /* beforeStopping */);
-            // Defer telling the client it is hidden if it can enter Pip and isn't current stopped
-            // or stopping. This gives it a chance to enter Pip in onPause().
+            // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
+            // stopped or stopping. This gives it a chance to enter Pip in onPause().
+            // TODO: There is still a question surrounding activities in multi-window mode that want
+            // to enter Pip after they are paused, but are still visible. I they should be okay to
+            // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
+            // the current contract for "auto-Pip" is that the app should enter it before onPause
+            // returns. Just need to confirm this reasoning makes sense.
             final boolean deferHidingClient = canEnterPictureInPicture
-                    && r.state != STOPPING && r.state != STOPPED;
+                    && r.state != STOPPING && r.state != STOPPED && r.state != PAUSED;
             r.setDeferHidingClient(deferHidingClient);
             r.setVisible(false);
 
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 3e5eed3..27e4d14 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -228,6 +228,7 @@
                         "releasing player piid:" + piid));
                 mPlayers.remove(new Integer(piid));
                 mDuckingManager.removeReleased(apc);
+                apc.handleStateEvent(AudioPlaybackConfiguration.PLAYER_STATE_RELEASED);
             }
         }
     }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index a1b8456..018b5fa4 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -154,7 +154,8 @@
 
     private final Injector mInjector;
     private final Context mContext;
-    private final Handler mHandler;
+    @VisibleForTesting
+    protected final Handler mHandler;
     @VisibleForTesting
     protected final LockSettingsStorage mStorage;
     private final LockSettingsStrongAuth mStrongAuth;
@@ -1736,6 +1737,10 @@
         return response;
     }
 
+    /**
+     * Call this method to notify DPMS regarding the latest password metric. This should be called
+     * when the user is authenticating or when a new password is being set.
+     */
     private void notifyActivePasswordMetricsAvailable(String password, @UserIdInt int userId) {
         final PasswordMetrics metrics;
         if (password == null) {
@@ -2197,6 +2202,8 @@
         }
         setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
         synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
+
+        notifyActivePasswordMetricsAvailable(credential, userId);
         return newHandle;
     }
 
@@ -2246,13 +2253,13 @@
                     userId);
             synchronizeUnifiedWorkChallengeForProfiles(userId, null);
             mSpManager.destroyPasswordBasedSyntheticPassword(handle, userId);
+
+            notifyActivePasswordMetricsAvailable(credential, userId);
         } else /* response == null || responseCode == VerifyCredentialResponse.RESPONSE_RETRY */ {
             Slog.w(TAG, "spBasedSetLockCredentialInternalLocked: " +
                     (response != null ? "rate limit exceeded" : "failed"));
             return;
         }
-        notifyActivePasswordMetricsAvailable(credential, userId);
-
     }
 
     @Override
@@ -2358,6 +2365,10 @@
                 Slog.w(TAG, "Invalid escrow token supplied");
                 return false;
             }
+            // Update PASSWORD_TYPE_KEY since it's needed by notifyActivePasswordMetricsAvailable()
+            // called by setLockCredentialWithAuthTokenLocked().
+            // TODO: refactor usage of PASSWORD_TYPE_KEY b/65239740
+            setLong(LockPatternUtils.PASSWORD_TYPE_KEY, requestedQuality, userId);
             long oldHandle = getSyntheticPasswordHandleLocked(userId);
             setLockCredentialWithAuthTokenLocked(credential, type, result.authToken,
                     requestedQuality, userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 69db49b..054ffd4 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -813,13 +813,6 @@
             throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, "Session not sealed");
         }
 
-        try {
-            resolveStageDirLocked();
-        } catch (IOException e) {
-            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
-                    "Failed to resolve stage location", e);
-        }
-
         Preconditions.checkNotNull(mPackageName);
         Preconditions.checkNotNull(mSignatures);
         Preconditions.checkNotNull(mResolvedBaseFile);
@@ -940,6 +933,13 @@
         mResolvedStagedFiles.clear();
         mResolvedInheritedFiles.clear();
 
+        try {
+            resolveStageDirLocked();
+        } catch (IOException e) {
+            throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
+                    "Failed to resolve stage location", e);
+        }
+
         final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter);
         final List<String> removeSplitList = new ArrayList<>();
         if (!ArrayUtils.isEmpty(removedFiles)) {
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 66e0a15..a3af68d 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -651,7 +651,7 @@
 
             // Use the same thread to remove the window as we used to add it, as otherwise we end up
             // with things in the view hierarchy being called from different threads.
-            mHandler.post(() -> {
+            mService.mAnimationHandler.post(() -> {
                 if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
                 try {
                     surface.remove();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d6b5567..8752932 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4101,6 +4101,7 @@
             return true;
         }
         enforceFullCrossUsersPermission(userHandle);
+        enforceUserUnlocked(userHandle, parent);
 
         synchronized (this) {
             // This API can only be called by an active device admin,
@@ -4120,7 +4121,8 @@
         enforceManagedProfile(userHandle, "call APIs refering to the parent profile");
 
         synchronized (this) {
-            int targetUser = getProfileParentId(userHandle);
+            final int targetUser = getProfileParentId(userHandle);
+            enforceUserUnlocked(targetUser, false);
             DevicePolicyData policy = getUserDataUnchecked(getCredentialOwner(userHandle, false));
             return isActivePasswordSufficientForUserLocked(policy, targetUser, false);
         }
@@ -4128,8 +4130,6 @@
 
     private boolean isActivePasswordSufficientForUserLocked(
             DevicePolicyData policy, int userHandle, boolean parent) {
-        enforceUserUnlocked(userHandle, parent);
-
         if (!mInjector.storageManagerIsFileBasedEncryptionEnabled()
                 && !policy.mPasswordStateHasBeenSetSinceBoot) {
             // Before user enters their password for the first time after a reboot, return the
@@ -4462,7 +4462,7 @@
                 result = mLockPatternUtils.setLockCredentialWithToken(password,
                         TextUtils.isEmpty(password) ? LockPatternUtils.CREDENTIAL_TYPE_NONE
                                 : LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                        tokenHandle, token, userHandle);
+                                quality, tokenHandle, token, userHandle);
             }
             boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
             if (requireEntry) {
@@ -5466,6 +5466,11 @@
         }
     }
 
+    /**
+     * Notify DPMS regarding the metric of the current password. This happens when the user changes
+     * the password, but also when the user just unlocks the keyguard. In comparison,
+     * reportPasswordChanged() is only called when the user changes the password.
+     */
     @Override
     public void setActivePasswordState(PasswordMetrics metrics, int userHandle) {
         if (!mHasFeature) {
diff --git a/services/tests/notification/AndroidTest.xml b/services/tests/notification/AndroidTest.xml
index fa77407..448bc3d 100644
--- a/services/tests/notification/AndroidTest.xml
+++ b/services/tests/notification/AndroidTest.xml
@@ -23,6 +23,6 @@
     <option name="test-tag" value="FrameworksNotificationTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.tests.notification" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="runner" value="android.testing.TestableInstrumentation" />
     </test>
 </configuration>
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index e8a1811..87b0db8 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -3658,7 +3658,8 @@
 
         // test reset password with token
         when(getServices().lockPatternUtils.setLockCredentialWithToken(eq(password),
-                eq(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD), eq(handle), eq(token),
+                eq(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD),
+                eq(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED), eq(handle), eq(token),
                 eq(UserHandle.USER_SYSTEM)))
                 .thenReturn(true);
         assertTrue(dpm.resetPasswordWithToken(admin1, password, token, 0));
diff --git a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
index 70d2274..a1d8198 100644
--- a/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BackgroundRestrictionsTest.java
@@ -32,7 +32,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.os.IDeviceIdleController;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -182,7 +181,7 @@
         }
     }
 
-    private void setAppOpsModeAllowed(boolean allow) throws PackageManager.NameNotFoundException {
+    private void setAppOpsModeAllowed(boolean allow) {
         mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, mTestPackageUid,
                 TEST_APP_PACKAGE, allow ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED);
     }
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 0df834f..0916a33 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -21,6 +21,7 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.storage.IStorageManager;
@@ -56,7 +57,7 @@
 
         @Override
         public Handler getHandler() {
-            return mock(Handler.class);
+            return new Handler(Looper.getMainLooper());
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index fd77de3..2c9aa9d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -23,8 +23,9 @@
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
+import static org.mockito.Mockito.verify;
 
-import android.app.admin.DevicePolicyManager;
+import android.app.admin.PasswordMetrics;
 import android.os.RemoteException;
 import android.os.UserHandle;
 
@@ -272,14 +273,22 @@
         long handle = mService.addEscrowToken(TOKEN.getBytes(), PRIMARY_USER_ID);
         assertFalse(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
-        mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID).getResponseCode();
+        mService.verifyCredential(PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0,
+                PRIMARY_USER_ID).getResponseCode();
         assertTrue(mService.isEscrowTokenActive(handle, PRIMARY_USER_ID));
 
         mService.setLockCredentialWithToken(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN,
                 handle, TOKEN.getBytes(), PASSWORD_QUALITY_SOMETHING, PRIMARY_USER_ID);
 
+        // Verify DPM gets notified about new device lock
+        mService.mHandler.runWithScissors(() -> {}, 0 /*now*/); // Flush runnables on handler
+        PasswordMetrics metric = PasswordMetrics.computeForPassword(PATTERN);
+        metric.quality = PASSWORD_QUALITY_SOMETHING;
+        verify(mDevicePolicyManager).setActivePasswordState(metric, PRIMARY_USER_ID);
+
         assertEquals(VerifyCredentialResponse.RESPONSE_OK,
-                mService.verifyCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0, PRIMARY_USER_ID).getResponseCode());
+                mService.verifyCredential(PATTERN, LockPatternUtils.CREDENTIAL_TYPE_PATTERN, 0,
+                        PRIMARY_USER_ID).getResponseCode());
         assertArrayEquals(storageKey, mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
     }
 
diff --git a/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java b/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java
index 94a85ee..011817e 100644
--- a/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java
+++ b/services/tests/servicestests/test-apps/JobTestApp/src/com/android/servicestests/apps/jobtestapp/TestJobActivity.java
@@ -30,9 +30,9 @@
     public static final String EXTRA_JOB_ID_KEY =
             "com.android.servicestests.apps.jobtestapp.extra.JOB_ID";
     public static final String ACTION_START_JOB =
-            "com.android.servicestests.apps.jobtestapp.extra.START_JOB";
+            "com.android.servicestests.apps.jobtestapp.action.START_JOB";
     public static final String ACTION_CANCEL_JOBS =
-            "com.android.servicestests.apps.jobtestapp.extra.CANCEL_JOBS";
+            "com.android.servicestests.apps.jobtestapp.action.CANCEL_JOBS";
     public static final int JOB_INITIAL_BACKOFF = 10_000;
     public static final int JOB_MINIMUM_LATENCY = 5_000;
 
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index ce0dcc3..c657a1b 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -22,8 +22,10 @@
 import android.hardware.usb.UsbConfiguration;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbEndpoint;
 import android.hardware.usb.UsbInterface;
+import android.hardware.usb.UsbManager;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.text.TextUtils;
@@ -32,8 +34,11 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.usb.descriptors.UsbDescriptorParser;
+import com.android.server.usb.descriptors.report.TextReportCanvas;
+import com.android.server.usb.descriptors.tree.UsbDescriptorsTree;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 
 /**
@@ -43,6 +48,8 @@
     private static final String TAG = UsbHostManager.class.getSimpleName();
     private static final boolean DEBUG = false;
 
+    private final Context mContext;
+
     // contains all connected USB devices
     private final HashMap<String, UsbDevice> mDevices = new HashMap<>();
 
@@ -69,6 +76,8 @@
 
     public UsbHostManager(Context context, UsbAlsaManager alsaManager,
             UsbSettingsManager settingsManager) {
+        mContext = context;
+
         mHostBlacklist = context.getResources().getStringArray(
                 com.android.internal.R.array.config_usbHostBlacklist);
         mUsbAlsaManager = alsaManager;
@@ -265,8 +274,8 @@
                 if (parser.parseDevice(mNewDevice.getDeviceName())) {
                     isInputHeadset = parser.isInputHeadset();
                     isOutputHeadset = parser.isOutputHeadset();
-                    Slog.i(TAG, "---- isHeadset[in:" + isInputHeadset
-                            + " , out:" + isOutputHeadset + "]");
+                    Slog.i(TAG, "---- isHeadset[in: " + isInputHeadset
+                            + " , out: " + isOutputHeadset + "]");
                 }
                 mUsbAlsaManager.usbDeviceAdded(mNewDevice,
                         isInputHeadset, isOutputHeadset);
@@ -339,6 +348,33 @@
             if (mUsbDeviceConnectionHandler != null) {
                 pw.println("Default USB Host Connection handler: " + mUsbDeviceConnectionHandler);
             }
+
+            Collection<UsbDevice> devices = mDevices.values();
+            if (devices.size() != 0) {
+                pw.println("USB Peripheral Descriptors");
+                for (UsbDevice device : devices) {
+                    StringBuilder stringBuilder = new StringBuilder();
+
+                    UsbDescriptorParser parser = new UsbDescriptorParser();
+                    if (parser.parseDevice(device.getDeviceName())) {
+                        UsbDescriptorsTree descriptorTree = new UsbDescriptorsTree();
+                        descriptorTree.parse(parser);
+
+                        UsbManager usbManager =
+                                (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
+                        UsbDeviceConnection connection = usbManager.openDevice(device);
+
+                        descriptorTree.report(new TextReportCanvas(connection, stringBuilder));
+                        connection.close();
+
+                        stringBuilder.append("isHeadset[in: " + parser.isInputHeadset()
+                                + " , out: " + parser.isOutputHeadset() + "]");
+                    } else {
+                        stringBuilder.append("Error Parsing USB Descriptors");
+                    }
+                    pw.println(stringBuilder.toString());
+                }
+            }
         }
     }
 
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java b/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java
index 305ae2f..7a92f9e 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbASFormat.java
@@ -102,6 +102,6 @@
     public void report(ReportCanvas canvas) {
         super.report(canvas);
 
-        canvas.write(UsbStrings.getFormatName(getFormatType()));
+        canvas.writeParagraph(UsbStrings.getFormatName(getFormatType()), /*emphasis*/false);
     }
 }
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
index c8fa694..d5cb89e 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDeviceDescriptor.java
@@ -130,8 +130,8 @@
         String subClasStr = UsbStrings.getClassName(devSubClass);
         canvas.writeListItem("Class " + devClass + ": " + classStr + " Subclass"
                 + devSubClass + ": " + subClasStr);
-        canvas.writeListItem("Vendor ID: " + getVendorID()
-                + " Product ID: " + getProductID()
+        canvas.writeListItem("Vendor ID: " + ReportCanvas.getHexString(getVendorID())
+                + " Product ID: " + ReportCanvas.getHexString(getProductID())
                 + " Product Release: " + ReportCanvas.getBCDString(getDeviceRelease()));
 
         byte mfgIndex = getMfgIndex();
diff --git a/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java b/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java
index 33746ba..a43569d 100644
--- a/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java
+++ b/services/usb/java/com/android/server/usb/descriptors/report/TextReportCanvas.java
@@ -40,6 +40,12 @@
         mStringBuilder = stringBuilder;
     }
 
+    private void writeListIndent() {
+        for (int space = 0; space < mListIndent; space++) {
+            mStringBuilder.append(" ");
+        }
+    }
+
     @Override
     public void write(String text) {
         mStringBuilder.append(text);
@@ -47,7 +53,8 @@
 
     @Override
     public void openHeader(int level) {
-        mStringBuilder.append("[" + level + " - ");
+        writeListIndent();
+        mStringBuilder.append("[");
     }
 
     @Override
@@ -56,7 +63,8 @@
     }
 
     @Override
-    public void openParagraph(boolean inRed) {
+    public void openParagraph(boolean emphasis) {
+        writeListIndent();
     }
 
     @Override
@@ -75,30 +83,20 @@
         closeParagraph();
     }
 
-    private void writeListIndent() {
-        for (int space = 0; space < mListIndent; space++) {
-            mStringBuilder.append(" ");
-        }
-    }
-
     @Override
     public void openList() {
         mListIndent += LIST_INDENT_AMNT;
-        writeListIndent();
-        mStringBuilder.append("---->\n");
     }
 
     @Override
     public void closeList() {
-        writeListIndent();
         mListIndent -= LIST_INDENT_AMNT;
-        mStringBuilder.append("<----\n");
     }
 
     @Override
     public void openListItem() {
         writeListIndent();
-        mStringBuilder.append(" - ");
+        mStringBuilder.append("- ");
     }
 
     @Override
diff --git a/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java b/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java
index ff58a26..64ecebc 100644
--- a/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java
+++ b/services/usb/java/com/android/server/usb/descriptors/report/UsbStrings.java
@@ -38,6 +38,10 @@
     private static HashMap<Integer, String> sTerminalNames;
     private static HashMap<Integer, String> sFormatNames;
 
+    static {
+        allocUsbStrings();
+    }
+
     private static void initDescriptorNames() {
         sDescriptorNames = new HashMap<Byte, String>();
         sDescriptorNames.put(UsbDescriptor.DESCRIPTORTYPE_DEVICE, "Device");
@@ -246,7 +250,7 @@
     /**
      * Initializes string tables.
      */
-    public static void allocUsbStrings() {
+    private static void allocUsbStrings() {
         initDescriptorNames();
         initACControlInterfaceNames();
         initACStreamingInterfaceNames();
@@ -258,19 +262,6 @@
     }
 
     /**
-     * Deinitializes string tables.
-     */
-    public static void releaseUsbStrings() {
-        sDescriptorNames = null;
-        sACControlInterfaceNames = null;
-        sACStreamingInterfaceNames = null;
-        sClassNames = null;
-        sAudioSubclassNames = null;
-        sAudioEncodingNames = null;
-        sTerminalNames = null;
-    }
-
-    /**
      * Retrieves the name for the specified descriptor ID.
      */
     public static String getDescriptorName(byte descriptorID) {
diff --git a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java
index 49caca5..6dbf415 100644
--- a/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java
+++ b/services/usb/java/com/android/server/usb/descriptors/tree/UsbDescriptorsACInterfaceNode.java
@@ -37,10 +37,10 @@
 
     @Override
     public void report(ReportCanvas canvas) {
-        canvas.openListItem();
-        canvas.writeParagraph("AC Interface type:0x"
-                + Integer.toHexString(mACInterface.getSubtype()), false);
+        canvas.writeListItem("AC Interface type: 0x"
+                + Integer.toHexString(mACInterface.getSubtype()));
+        canvas.openList();
         mACInterface.report(canvas);
-        canvas.closeListItem();
+        canvas.closeList();
     }
 }
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index cd65232..2a707c9 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -170,7 +170,7 @@
 
         final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
         dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
-        return filterByIntent(context, packageNames, dialIntentWithTelScheme);
+        return filterByIntent(context, packageNames, dialIntentWithTelScheme, userId);
     }
 
     public static List<String> getInstalledDialerApplications(Context context) {
@@ -204,17 +204,18 @@
      *
      * @param context A valid context
      * @param packageNames List of package names to filter.
+     * @param userId The UserId
      * @return The filtered list.
      */
     private static List<String> filterByIntent(Context context, List<String> packageNames,
-            Intent intent) {
+            Intent intent, int userId) {
         if (packageNames == null || packageNames.isEmpty()) {
             return new ArrayList<>();
         }
 
         final List<String> result = new ArrayList<>();
         final List<ResolveInfo> resolveInfoList = context.getPackageManager()
-                .queryIntentActivities(intent, 0);
+                .queryIntentActivitiesAsUser(intent, 0, userId);
         final int length = resolveInfoList.size();
         for (int i = 0; i < length; i++) {
             final ActivityInfo info = resolveInfoList.get(i).activityInfo;
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index acbcc3c..0572b49 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1760,13 +1760,7 @@
 
         // Carrier Signalling Receivers
         sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
-        sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
-                new String[]{
-                        "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:"
-                                + "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED,"
-                                + "com.android.internal.telephony.CARRIER_SIGNAL_RESET,"
-                                + "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE"
-                });
+        sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
 
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 98cb1f9..cc469b5 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5159,7 +5159,12 @@
         }
     }
 
-    /** @hide */
+    /**
+     * @deprecated Use  {@link android.telecom.TelecomManager#placeCall(Uri address,
+     * Bundle extras)} instead.
+     * @hide
+     */
+    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public void call(String callingPackage, String number) {
@@ -5172,7 +5177,11 @@
         }
     }
 
-    /** @hide */
+    /**
+     * @deprecated Use {@link android.telecom.TelecomManager#endCall()} instead.
+     * @hide
+     */
+    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public boolean endCall() {
@@ -5186,7 +5195,11 @@
         return false;
     }
 
-    /** @hide */
+    /**
+     * @deprecated Use {@link android.telecom.TelecomManager#acceptRingingCall} instead
+     * @hide
+     */
+    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void answerRingingCall() {
@@ -5199,7 +5212,11 @@
         }
     }
 
-    /** @hide */
+    /**
+     * @deprecated Use {@link android.telecom.TelecomManager#silenceRinger} instead
+     * @hide
+     */
+    @Deprecated
     @SystemApi
     @SuppressLint("Doclava125")
     public void silenceRinger() {
@@ -5754,10 +5771,13 @@
     }
 
     /**
+     * @deprecated Use {@link android.telecom.TelecomManager#silenceRinger} instead
      * Whether the phone supports TTY mode.
      *
      * @return {@code true} if the device supports TTY mode, and {@code false} otherwise.
+     *
      */
+    @Deprecated
     public boolean isTtyModeSupported() {
         try {
             ITelephony telephony = getITelephony();
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 256e13b..91032f3 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -107,6 +107,7 @@
     public static final int EVENT_PCO_DATA_RECEIVED = BASE + 45;
     public static final int EVENT_SET_CARRIER_DATA_ENABLED = BASE + 46;
     public static final int EVENT_DATA_RECONNECT = BASE + 47;
+    public static final int EVENT_ROAMING_SETTING_CHANGE = BASE + 48;
 
     /***** Constants *****/
 
diff --git a/test-runner/Android.mk b/test-runner/Android.mk
index 3c3718a..060a518 100644
--- a/test-runner/Android.mk
+++ b/test-runner/Android.mk
@@ -107,11 +107,10 @@
 
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(android_test_runner_api_gen_stamp)
-$(full_classes_jack) : $(android_test_runner_api_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_runner_api_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.runner.stubs.jar)
@@ -202,11 +201,10 @@
 
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
 
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(android_test_mock_gen_stamp)
-$(full_classes_jack) : $(android_test_mock_gen_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(android_test_mock_gen_stamp)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 # Archive a copy of the classes.jar in SDK build.
 $(call dist-for-goals,sdk win_sdk,$(full_classes_jar):android.test.mock.stubs.jar)
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index e76fef5..23aafb2 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -88,7 +88,7 @@
     }
 }
 
-static const char* replaceAll(const string& field_name, const char oldC, const string& newS) {
+static const std::string replaceAll(const string& field_name, const char oldC, const string& newS) {
     if (field_name.find_first_of(oldC) == field_name.npos) return field_name.c_str();
     size_t pos = 0, idx = 0;
     char* res = new char[field_name.size() * newS.size() + 1]; // assign a larger buffer
@@ -104,7 +104,9 @@
         }
     }
     res[idx] = '\0';
-    return res;
+    std::string result(res);
+    delete [] res;
+    return result;
 }
 
 static inline bool isDefaultDest(const FieldDescriptor* field) {
@@ -118,7 +120,8 @@
     for (int i=0; i<descriptor->field_count(); i++) {
         hasDefaultFlags[i] = true; // set default to true
         const FieldDescriptor* field = descriptor->field(i);
-        const char* field_name = replaceAll(field->full_name(), '.', "__");
+        const std::string field_name_str = replaceAll(field->full_name(), '.', "__");
+        const char* field_name = field_name_str.c_str();
         // check if the same name is already defined
         if (msgNames.find(field_name) != msgNames.end()) {
             hasDefaultFlags[i] = msgNames[field_name];
@@ -142,7 +145,7 @@
                 printf("static const char* %s_patterns[] = {\n", field_name);
                 for (int i=0; i<p.patterns_size(); i++) {
                     // the generated string need to escape backslash as well, need to dup it here
-                    printf("    \"%s\",\n", replaceAll(p.patterns(i), '\\', "\\\\"));
+                    printf("    \"%s\",\n", replaceAll(p.patterns(i), '\\', "\\\\").c_str());
                 }
                 printf("    NULL };\n");
                 printf("static Privacy %s = { %d, %d, %d, %s_patterns };\n", field_name, field->number(),
@@ -170,7 +173,7 @@
     for (int i=0; i<descriptor->field_count(); i++) {
         const FieldDescriptor* field = descriptor->field(i);
         if (hasDefaultFlags[i]) continue;
-        printf("    &%s,\n", replaceAll(field->full_name(), '.', "__"));
+        printf("    &%s,\n", replaceAll(field->full_name(), '.', "__").c_str());
     }
     printf("    NULL };\n");
     emptyline();