Merge "Post runnables instead of sending messages."
diff --git a/compiled-classes-phone b/compiled-classes-phone
index ec3371e..2cbfc22 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -633,6 +633,7 @@
 android.bluetooth.BluetoothClass
 android.bluetooth.BluetoothClass$1
 android.bluetooth.BluetoothCodecConfig
+android.bluetooth.BluetoothCodecStatus
 android.bluetooth.BluetoothDevice
 android.bluetooth.BluetoothDevice$1
 android.bluetooth.BluetoothDevice$2
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 1165fce..4960159 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -105,10 +105,9 @@
      * Intent used to broadcast the change in the Audio Codec state of the
      * A2DP Source profile.
      *
-     * <p>This intent will have 3 extras:
+     * <p>This intent will have 2 extras:
      * <ul>
-     *   <li> {@link #EXTRA_CODEC_CONFIG} - The current codec configuration. </li>
-     *   <li> {@link #EXTRA_PREVIOUS_CODEC_CONFIG} - The previous codec configuration. </li>
+     *   <li> {@link BluetoothCodecStatus#EXTRA_CODEC_STATUS} - The codec status. </li>
      *   <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device if the device is currently
      *   connected, otherwise it is not included.</li>
      * </ul>
@@ -564,24 +563,24 @@
     }
 
     /**
-     * Gets the current codec configuration.
+     * Gets the current codec status (configuration and capability).
      *
-     * @return the current codec configuration
+     * @return the current codec status
      * @hide
      */
-    public BluetoothCodecConfig getCodecConfig() {
-        if (DBG) Log.d(TAG, "getCodecConfig");
+    public BluetoothCodecStatus getCodecStatus() {
+        if (DBG) Log.d(TAG, "getCodecStatus");
         try {
             mServiceLock.readLock().lock();
             if (mService != null && isEnabled()) {
-                return mService.getCodecConfig();
+                return mService.getCodecStatus();
             }
             if (mService == null) {
                 Log.w(TAG, "Proxy not attached to service");
             }
             return null;
         } catch (RemoteException e) {
-            Log.e(TAG, "Error talking to BT service in getCodecConfig()", e);
+            Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
             return null;
         } finally {
             mServiceLock.readLock().unlock();
diff --git a/core/java/android/bluetooth/BluetoothCodecConfig.java b/core/java/android/bluetooth/BluetoothCodecConfig.java
index a37a0b3..a482103 100644
--- a/core/java/android/bluetooth/BluetoothCodecConfig.java
+++ b/core/java/android/bluetooth/BluetoothCodecConfig.java
@@ -29,24 +29,6 @@
  * {@hide}
  */
 public final class BluetoothCodecConfig implements Parcelable {
-
-    /**
-     * Extra for the codec configuration intents of the individual profiles.
-     *
-     * This extra represents the current codec configuration of the A2DP
-     * profile.
-     */
-    public static final String EXTRA_CODEC_CONFIG = "android.bluetooth.codec.extra.CODEC_CONFIG";
-
-    /**
-     * Extra for the codec configuration intents of the individual profiles.
-     *
-     * This extra represents the previous codec configuration of the A2DP
-     * profile.
-     */
-    public static final String EXTRA_PREVIOUS_CODEC_CONFIG =
-        "android.bluetooth.codec.extra.PREVIOUS_CODEC_CONFIG";
-
     // Add an entry for each source codec here.
     // NOTE: The values should be same as those listed in the following file:
     //   hardware/libhardware/include/hardware/bt_av.h
@@ -128,13 +110,93 @@
                             mCodecSpecific2, mCodecSpecific3, mCodecSpecific4);
     }
 
+    /**
+     * Checks whether the object contains valid codec configuration.
+     *
+     * @return true if the object contains valid codec configuration,
+     * otherwise false.
+     */
+    public boolean isValid() {
+        return (mSampleRate != SAMPLE_RATE_NONE) &&
+            (mBitsPerSample != BITS_PER_SAMPLE_NONE) &&
+            (mChannelMode != CHANNEL_MODE_NONE);
+    }
+
+    /**
+     * Adds capability string to an existing string.
+     *
+     * @param prevStr the previous string with the capabilities. Can be
+     * a null pointer.
+     * @param capStr the capability string to append to prevStr argument.
+     * @return the result string in the form "prevStr|capStr".
+     */
+    private static String appendCapabilityToString(String prevStr,
+                                                   String capStr) {
+        if (prevStr == null) {
+            return capStr;
+        }
+        return prevStr + "|" + capStr;
+    }
+
     @Override
     public String toString() {
-        return "{mCodecType:" + mCodecType +
+        String sampleRateStr = null;
+        if (mSampleRate == SAMPLE_RATE_NONE) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "NONE");
+        }
+        if ((mSampleRate & SAMPLE_RATE_44100) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "44100");
+        }
+        if ((mSampleRate & SAMPLE_RATE_48000) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "48000");
+        }
+        if ((mSampleRate & SAMPLE_RATE_88200) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "88200");
+        }
+        if ((mSampleRate & SAMPLE_RATE_96000) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "96000");
+        }
+        if ((mSampleRate & SAMPLE_RATE_176400) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "176400");
+        }
+        if ((mSampleRate & SAMPLE_RATE_192000) != 0) {
+            sampleRateStr = appendCapabilityToString(sampleRateStr, "192000");
+        }
+
+        String bitsPerSampleStr = null;
+        if (mBitsPerSample == BITS_PER_SAMPLE_NONE) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "NONE");
+        }
+        if ((mBitsPerSample & BITS_PER_SAMPLE_16) != 0) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "16");
+        }
+        if ((mBitsPerSample & BITS_PER_SAMPLE_24) != 0) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "24");
+        }
+        if ((mBitsPerSample & BITS_PER_SAMPLE_32) != 0) {
+            bitsPerSampleStr = appendCapabilityToString(bitsPerSampleStr, "32");
+        }
+
+        String channelModeStr = null;
+        if (mChannelMode == CHANNEL_MODE_NONE) {
+            channelModeStr = appendCapabilityToString(channelModeStr, "NONE");
+        }
+        if ((mChannelMode & CHANNEL_MODE_MONO) != 0) {
+            channelModeStr = appendCapabilityToString(channelModeStr, "MONO");
+        }
+        if ((mChannelMode & CHANNEL_MODE_STEREO) != 0) {
+            channelModeStr = appendCapabilityToString(channelModeStr, "STEREO");
+        }
+
+        return "{codecName:" + getCodecName() +
+            ",mCodecType:" + mCodecType +
             ",mCodecPriority:" + mCodecPriority +
             ",mSampleRate:" + String.format("0x%x", mSampleRate) +
+            "(" + sampleRateStr + ")" +
             ",mBitsPerSample:" + String.format("0x%x", mBitsPerSample) +
+            "(" + bitsPerSampleStr + ")" +
             ",mChannelMode:" + String.format("0x%x", mChannelMode) +
+            "(" + channelModeStr + ")" +
             ",mCodecSpecific1:" + mCodecSpecific1 +
             ",mCodecSpecific2:" + mCodecSpecific2 +
             ",mCodecSpecific3:" + mCodecSpecific3 +
@@ -181,7 +243,32 @@
     }
 
     /**
-     * Returns the codec type.
+     * Gets the codec name.
+     *
+     * @return the codec name
+     */
+    public String getCodecName() {
+        switch (mCodecType) {
+        case SOURCE_CODEC_TYPE_SBC:
+            return "SBC";
+        case SOURCE_CODEC_TYPE_AAC:
+            return "AAC";
+        case SOURCE_CODEC_TYPE_APTX:
+            return "aptX";
+        case SOURCE_CODEC_TYPE_APTX_HD:
+            return "aptX HD";
+        case SOURCE_CODEC_TYPE_LDAC:
+            return "LDAC";
+        case SOURCE_CODEC_TYPE_INVALID:
+            return "INVALID CODEC";
+        default:
+            break;
+        }
+        return "UNKNOWN CODEC(" + mCodecType + ")";
+    }
+
+    /**
+     * Gets the codec type.
      * See {@link android.bluetooth.BluetoothCodecConfig#SOURCE_CODEC_TYPE_SBC}.
      *
      * @return the codec type
@@ -191,7 +278,7 @@
     }
 
     /**
-     * Returns the codec selection priority.
+     * Gets the codec selection priority.
      * The codec selection priority is relative to other codecs: larger value
      * means higher priority. If 0, reset to default.
      *
@@ -202,7 +289,7 @@
     }
 
     /**
-     * Returns the codec sample rate. The value can be a bitmask with all
+     * Gets the codec sample rate. The value can be a bitmask with all
      * supported sample rates:
      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_NONE} or
      * {@link android.bluetooth.BluetoothCodecConfig#SAMPLE_RATE_44100} or
@@ -219,7 +306,7 @@
     }
 
     /**
-     * Returns the codec bits per sample. The value can be a bitmask with all
+     * Gets the codec bits per sample. The value can be a bitmask with all
      * bits per sample supported:
      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_NONE} or
      * {@link android.bluetooth.BluetoothCodecConfig#BITS_PER_SAMPLE_16} or
@@ -233,7 +320,7 @@
     }
 
     /**
-     * Returns the codec channel mode. The value can be a bitmask with all
+     * Gets the codec channel mode. The value can be a bitmask with all
      * supported channel modes:
      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_NONE} or
      * {@link android.bluetooth.BluetoothCodecConfig#CHANNEL_MODE_MONO} or
@@ -246,7 +333,7 @@
     }
 
     /**
-     * Returns a codec specific value1.
+     * Gets a codec specific value1.
      *
      * @return a codec specific value1.
      */
@@ -255,7 +342,7 @@
     }
 
     /**
-     * Returns a codec specific value2.
+     * Gets a codec specific value2.
      *
      * @return a codec specific value2
      */
@@ -264,7 +351,7 @@
     }
 
     /**
-     * Returns a codec specific value3.
+     * Gets a codec specific value3.
      *
      * @return a codec specific value3
      */
@@ -273,7 +360,7 @@
     }
 
     /**
-     * Returns a codec specific value4.
+     * Gets a codec specific value4.
      *
      * @return a codec specific value4
      */
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.aidl b/core/java/android/bluetooth/BluetoothCodecStatus.aidl
new file mode 100644
index 0000000..f9c3a3d
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.bluetooth;
+
+parcelable BluetoothCodecStatus;
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
new file mode 100644
index 0000000..c8cd8d1
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -0,0 +1,134 @@
+/*
+ * 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 android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Represents the codec status (configuration and capability) for a Bluetooth
+ * A2DP source device.
+ *
+ * {@see BluetoothA2dp}
+ *
+ * {@hide}
+ */
+public final class BluetoothCodecStatus implements Parcelable {
+    /**
+     * Extra for the codec configuration intents of the individual profiles.
+     *
+     * This extra represents the current codec status of the A2DP
+     * profile.
+     */
+    public static final String EXTRA_CODEC_STATUS =
+        "android.bluetooth.codec.extra.CODEC_STATUS";
+
+    private final BluetoothCodecConfig mCodecConfig;
+    private final BluetoothCodecConfig[] mCodecsLocalCapabilities;
+    private final BluetoothCodecConfig[] mCodecsSelectableCapabilities;
+
+    public BluetoothCodecStatus(BluetoothCodecConfig codecConfig,
+                                BluetoothCodecConfig[] codecsLocalCapabilities,
+                                BluetoothCodecConfig[] codecsSelectableCapabilities) {
+        mCodecConfig = codecConfig;
+        mCodecsLocalCapabilities = codecsLocalCapabilities;
+        mCodecsSelectableCapabilities = codecsSelectableCapabilities;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof BluetoothCodecStatus) {
+            BluetoothCodecStatus other = (BluetoothCodecStatus)o;
+            return (Objects.equals(other.mCodecConfig, mCodecConfig) &&
+                    Objects.equals(other.mCodecsLocalCapabilities,
+                                   mCodecsLocalCapabilities) &&
+                    Objects.equals(other.mCodecsSelectableCapabilities,
+                                   mCodecsSelectableCapabilities));
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
+                            mCodecsLocalCapabilities);
+    }
+
+    @Override
+    public String toString() {
+        return "{mCodecConfig:" + mCodecConfig +
+            ",mCodecsLocalCapabilities:" + Arrays.toString(mCodecsLocalCapabilities) +
+            ",mCodecsSelectableCapabilities:" + Arrays.toString(mCodecsSelectableCapabilities) +
+            "}";
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Parcelable.Creator<BluetoothCodecStatus> CREATOR =
+            new Parcelable.Creator<BluetoothCodecStatus>() {
+        public BluetoothCodecStatus createFromParcel(Parcel in) {
+            final BluetoothCodecConfig codecConfig = in.readTypedObject(BluetoothCodecConfig.CREATOR);
+            final BluetoothCodecConfig[] codecsLocalCapabilities = in.createTypedArray(BluetoothCodecConfig.CREATOR);
+            final BluetoothCodecConfig[] codecsSelectableCapabilities = in.createTypedArray(BluetoothCodecConfig.CREATOR);
+
+            return new BluetoothCodecStatus(codecConfig,
+                                            codecsLocalCapabilities,
+                                            codecsSelectableCapabilities);
+        }
+        public BluetoothCodecStatus[] newArray(int size) {
+            return new BluetoothCodecStatus[size];
+        }
+    };
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeTypedObject(mCodecConfig, 0);
+        out.writeTypedArray(mCodecsLocalCapabilities, 0);
+        out.writeTypedArray(mCodecsSelectableCapabilities, 0);
+    }
+
+    /**
+     * Gets the current codec configuration.
+     *
+     * @return the current codec configuration
+     */
+    public BluetoothCodecConfig getCodecConfig() {
+        return mCodecConfig;
+    }
+
+    /**
+     * Gets the codecs local capabilities.
+     *
+     * @return an array with the codecs local capabilities
+     */
+    public BluetoothCodecConfig[] getCodecsLocalCapabilities() {
+        return mCodecsLocalCapabilities;
+    }
+
+    /**
+     * Gets the codecs selectable capabilities.
+     *
+     * @return an array with the codecs selectable capabilities
+     */
+    public BluetoothCodecConfig[] getCodecsSelectableCapabilities() {
+        return mCodecsSelectableCapabilities;
+    }
+}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 5b524eb..dbb5b7d 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothCodecStatus;
 import android.bluetooth.BluetoothDevice;
 
 /**
@@ -37,6 +38,6 @@
     oneway void adjustAvrcpAbsoluteVolume(int direction);
     oneway void setAvrcpAbsoluteVolume(int volume);
     boolean isA2dpPlaying(in BluetoothDevice device);
-    BluetoothCodecConfig getCodecConfig();
+    BluetoothCodecStatus getCodecStatus();
     oneway void setCodecConfigPreference(in BluetoothCodecConfig codecConfig);
 }
diff --git a/core/res/res/values-mcc704-mnc01/config.xml b/core/res/res/values-mcc704-mnc01/config.xml
new file mode 100644
index 0000000..10b6470
--- /dev/null
+++ b/core/res/res/values-mcc704-mnc01/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, 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 my 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.
+*/
+-->
+
+<resources>
+    <!-- Do not translate. Defines the slots is Two Digit Number for dialing normally not USSD -->
+    <string-array name="config_twoDigitNumberPattern">
+        <item>"*1"</item>
+        <item>"*5"</item>
+        <item>"*9"</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc708-mnc001/config.xml b/core/res/res/values-mcc708-mnc001/config.xml
new file mode 100755
index 0000000..7b7c48d
--- /dev/null
+++ b/core/res/res/values-mcc708-mnc001/config.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2016, 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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <string-array translatable="false" name="config_twoDigitNumberPattern">
+        <item>"*1"</item>
+        <item>"*5"</item>
+    </string-array>
+</resources>
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index 83001df..0a90749 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -286,7 +286,8 @@
     }
 
     // Returns seconds since device boot.
-    private static long curTime() {
+    @VisibleForTesting
+    protected long currentTimeSeconds() {
         return SystemClock.elapsedRealtime() / DateUtils.SECOND_IN_MILLIS;
     }
 
@@ -450,7 +451,7 @@
             }
 
             mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length));
-            mLastSeen = curTime();
+            mLastSeen = currentTimeSeconds();
 
             // Sanity check packet in case a packet arrives before we attach RA filter
             // to our packet socket. b/29586253
@@ -580,7 +581,7 @@
         // How many seconds does this RA's have to live, taking into account the fact
         // that we might have seen it a while ago.
         long currentLifetime() {
-            return mMinLifetime - (curTime() - mLastSeen);
+            return mMinLifetime - (currentTimeSeconds() - mLastSeen);
         }
 
         boolean isExpired() {
@@ -946,7 +947,7 @@
             Log.e(TAG, "Failed to generate APF program.", e);
             return;
         }
-        mLastTimeInstalledProgram = curTime();
+        mLastTimeInstalledProgram = currentTimeSeconds();
         mLastInstalledProgramMinLifetime = programMinLifetime;
         mLastInstalledProgram = program;
         mNumProgramUpdates++;
@@ -965,7 +966,7 @@
      */
     private boolean shouldInstallnewProgram() {
         long expiry = mLastTimeInstalledProgram + mLastInstalledProgramMinLifetime;
-        return expiry < curTime() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING;
+        return expiry < currentTimeSeconds() + MAX_PROGRAM_LIFETIME_WORTH_REFRESHING;
     }
 
     private void hexDump(String msg, byte[] packet, int length) {
@@ -999,7 +1000,7 @@
             if (ra.matches(packet, length)) {
                 if (VDBG) log("matched RA " + ra);
                 // Update lifetimes.
-                ra.mLastSeen = curTime();
+                ra.mLastSeen = currentTimeSeconds();
                 ra.mMinLifetime = ra.minLifetime(packet, length);
                 ra.seenCount++;
 
@@ -1128,7 +1129,7 @@
         pw.println("Program updates: " + mNumProgramUpdates);
         pw.println(String.format(
                 "Last program length %d, installed %ds ago, lifetime %ds",
-                mLastInstalledProgram.length, curTime() - mLastTimeInstalledProgram,
+                mLastInstalledProgram.length, currentTimeSeconds() - mLastTimeInstalledProgram,
                 mLastInstalledProgramMinLifetime));
 
         pw.println("RA filters:");
@@ -1137,7 +1138,7 @@
             pw.println(ra);
             pw.increaseIndent();
             pw.println(String.format(
-                    "Seen: %d, last %ds ago", ra.seenCount, curTime() - ra.mLastSeen));
+                    "Seen: %d, last %ds ago", ra.seenCount, currentTimeSeconds() - ra.mLastSeen));
             if (DBG) {
                 pw.println("Last match:");
                 pw.increaseIndent();
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b3f5630..00c36f9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -150,6 +150,7 @@
     private UsbDebuggingManager mDebuggingManager;
     private final UsbAlsaManager mUsbAlsaManager;
     private Intent mBroadcastedIntent;
+    private boolean mPendingBootBroadcast;
 
     private class AdbSettingsObserver extends ContentObserver {
         public AdbSettingsObserver() {
@@ -740,13 +741,16 @@
                     if (UsbManager.containsFunction(mCurrentFunctions,
                             UsbManager.USB_FUNCTION_ACCESSORY)) {
                         updateCurrentAccessory();
-                    } else if (!mConnected) {
-                        // restore defaults when USB is disconnected
-                        setEnabledFunctions(null, false, false);
                     }
                     if (mBootCompleted) {
+                        if (!mConnected) {
+                            // restore defaults when USB is disconnected
+                            setEnabledFunctions(null, false, false);
+                        }
                         updateUsbStateBroadcastIfNeeded(false);
                         updateUsbFunctions();
+                    } else {
+                        mPendingBootBroadcast = true;
                     }
                     break;
                 case MSG_UPDATE_HOST_STATE:
@@ -758,6 +762,8 @@
                     updateUsbNotification();
                     if (mBootCompleted) {
                         updateUsbStateBroadcastIfNeeded(false);
+                    } else {
+                        mPendingBootBroadcast = true;
                     }
                     break;
                 case MSG_ENABLE_ADB:
@@ -777,6 +783,10 @@
                     break;
                 case MSG_BOOT_COMPLETED:
                     mBootCompleted = true;
+                    if (mPendingBootBroadcast) {
+                        updateUsbStateBroadcastIfNeeded(false);
+                        mPendingBootBroadcast = false;
+                    }
                     setEnabledFunctions(null, false, false);
                     if (mCurrentAccessory != null) {
                         getCurrentSettings().accessoryAttached(mCurrentAccessory);
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index ff61754..91d6c68 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -29,9 +29,11 @@
 import android.net.metrics.RaEvent;
 import android.os.ConditionVariable;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.test.AndroidTestCase;
+import android.text.format.DateUtils;
 import android.test.suitebuilder.annotation.SmallTest;
 import static android.system.OsConstants.*;
 
@@ -604,6 +606,8 @@
         public final static byte[] MOCK_MAC_ADDR = {1,2,3,4,5,6};
         private FileDescriptor mWriteSocket;
 
+        private final long mFixedTimeMs = SystemClock.elapsedRealtime();
+
         public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
                 IpConnectivityLog log) throws Exception {
             super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
@@ -617,6 +621,11 @@
         }
 
         @Override
+        protected long currentTimeSeconds() {
+            return mFixedTimeMs / DateUtils.SECOND_IN_MILLIS;
+        }
+
+        @Override
         void maybeStartFilter() {
             mHardwareAddress = MOCK_MAC_ADDR;
             installNewProgramLocked();
@@ -969,27 +978,30 @@
 
     // Verify that the last program pushed to the IpManager.Callback properly filters the
     // given packet for the given lifetime.
-    private void verifyRaLifetime(MockIpManagerCallback ipManagerCallback, ByteBuffer packet,
-            int lifetime) {
-        byte[] program = ipManagerCallback.getApfProgram();
+    private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
+        final int FRACTION_OF_LIFETIME = 6;
+        final int ageLimit = lifetime / FRACTION_OF_LIFETIME;
 
-        // Verify new program should drop RA for 1/6th its lifetime
+        // Verify new program should drop RA for 1/6th its lifetime and pass afterwards.
         assertDrop(program, packet.array());
-        assertDrop(program, packet.array(), lifetime/6);
-        assertPass(program, packet.array(), lifetime/6 + 1);
+        assertDrop(program, packet.array(), ageLimit);
+        assertPass(program, packet.array(), ageLimit + 1);
         assertPass(program, packet.array(), lifetime);
-
         // Verify RA checksum is ignored
+        final short originalChecksum = packet.getShort(ICMP6_RA_CHECKSUM_OFFSET);
         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)12345);
         assertDrop(program, packet.array());
         packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, (short)-12345);
         assertDrop(program, packet.array());
+        packet.putShort(ICMP6_RA_CHECKSUM_OFFSET, originalChecksum);
 
         // Verify other changes to RA make it not match filter
+        final byte originalFirstByte = packet.get(0);
         packet.put(0, (byte)-1);
         assertPass(program, packet.array());
         packet.put(0, (byte)0);
         assertDrop(program, packet.array());
+        packet.put(0, originalFirstByte);
     }
 
     // Test that when ApfFilter is shown the given packet, it generates a program to filter it
@@ -999,9 +1011,8 @@
         // Verify new program generated if ApfFilter witnesses RA
         ipManagerCallback.resetApfProgramWait();
         apfFilter.pretendPacketReceived(packet.array());
-        ipManagerCallback.getApfProgram();
-
-        verifyRaLifetime(ipManagerCallback, packet, lifetime);
+        byte[] program = ipManagerCallback.getApfProgram();
+        verifyRaLifetime(program, packet, lifetime);
     }
 
     private void verifyRaEvent(RaEvent expected) {
@@ -1046,18 +1057,26 @@
         TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
         byte[] program = ipManagerCallback.getApfProgram();
 
+        final int ROUTER_LIFETIME = 1000;
+        final int PREFIX_VALID_LIFETIME = 200;
+        final int PREFIX_PREFERRED_LIFETIME = 100;
+        final int RDNSS_LIFETIME  = 300;
+        final int ROUTE_LIFETIME  = 400;
+        // Note that lifetime of 2000 will be ignored in favor of shorter route lifetime of 1000.
+        final int DNSSL_LIFETIME  = 2000;
+
         // Verify RA is passed the first time
         ByteBuffer basePacket = ByteBuffer.wrap(new byte[ICMP6_RA_OPTION_OFFSET]);
         basePacket.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
         basePacket.put(IPV6_NEXT_HEADER_OFFSET, (byte)IPPROTO_ICMPV6);
         basePacket.put(ICMP6_TYPE_OFFSET, (byte)ICMP6_ROUTER_ADVERTISEMENT);
-        basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)1000);
+        basePacket.putShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET, (short)ROUTER_LIFETIME);
         basePacket.position(IPV6_DEST_ADDR_OFFSET);
         basePacket.put(IPV6_ALL_NODES_ADDRESS);
         assertPass(program, basePacket.array());
 
-        testRaLifetime(apfFilter, ipManagerCallback, basePacket, 1000);
-        verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, -1));
+        testRaLifetime(apfFilter, ipManagerCallback, basePacket, ROUTER_LIFETIME);
+        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, -1));
 
         // Ensure zero-length options cause the packet to be silently skipped.
         // Do this before we test other packets. http://b/29586253
@@ -1079,11 +1098,14 @@
         prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
         prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
         prefixOptionPacket.putInt(
-                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET, 100);
+                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
+                PREFIX_PREFERRED_LIFETIME);
         prefixOptionPacket.putInt(
-                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET, 200);
-        testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, 100);
-        verifyRaEvent(new RaEvent(1000, 200, 100, -1, -1, -1));
+                ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
+                PREFIX_VALID_LIFETIME);
+        testRaLifetime(apfFilter, ipManagerCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
+        verifyRaEvent(new RaEvent(
+                ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
 
         ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
@@ -1092,9 +1114,9 @@
         rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
         rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
         rdnssOptionPacket.putInt(
-                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 300);
-        testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, 300);
-        verifyRaEvent(new RaEvent(1000, -1, -1, -1, 300, -1));
+                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
+        testRaLifetime(apfFilter, ipManagerCallback, rdnssOptionPacket, RDNSS_LIFETIME);
+        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
 
         ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
@@ -1103,9 +1125,9 @@
         routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
         routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
         routeInfoOptionPacket.putInt(
-                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 400);
-        testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, 400);
-        verifyRaEvent(new RaEvent(1000, -1, -1, 400, -1, -1));
+                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
+        testRaLifetime(apfFilter, ipManagerCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
+        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
 
         ByteBuffer dnsslOptionPacket = ByteBuffer.wrap(
                 new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
@@ -1114,18 +1136,17 @@
         dnsslOptionPacket.put((byte)ICMP6_DNSSL_OPTION_TYPE);
         dnsslOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
         dnsslOptionPacket.putInt(
-                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, 2000);
-        // Note that lifetime of 2000 will be ignored in favor of shorter
-        // route lifetime of 1000.
-        testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, 1000);
-        verifyRaEvent(new RaEvent(1000, -1, -1, -1, -1, 2000));
+                ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, DNSSL_LIFETIME);
+        testRaLifetime(apfFilter, ipManagerCallback, dnsslOptionPacket, ROUTER_LIFETIME);
+        verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
 
         // Verify that current program filters all five RAs:
-        verifyRaLifetime(ipManagerCallback, basePacket, 1000);
-        verifyRaLifetime(ipManagerCallback, prefixOptionPacket, 100);
-        verifyRaLifetime(ipManagerCallback, rdnssOptionPacket, 300);
-        verifyRaLifetime(ipManagerCallback, routeInfoOptionPacket, 400);
-        verifyRaLifetime(ipManagerCallback, dnsslOptionPacket, 1000);
+        program = ipManagerCallback.getApfProgram();
+        verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
+        verifyRaLifetime(program, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
+        verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
+        verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
+        verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
 
         apfFilter.shutdown();
     }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 043925ed..a9e38ce 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -706,7 +706,11 @@
                             attachCallback.onAttachFailed();
                             break;
                         case CALLBACK_IDENTITY_CHANGED:
-                            identityChangedListener.onIdentityChanged((byte[]) msg.obj);
+                            if (identityChangedListener == null) {
+                                Log.e(TAG, "CALLBACK_IDENTITY_CHANGED: null listener.");
+                            } else {
+                                identityChangedListener.onIdentityChanged((byte[]) msg.obj);
+                            }
                             break;
                         case CALLBACK_RANGING_SUCCESS: {
                             RttManager.RttListener listener = getAndRemoveRangingListener(msg.arg1);
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index ca4d121..f1174b6 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -217,9 +217,9 @@
         return (homeSp == null ? that.homeSp == null : homeSp.equals(that.homeSp))
                 && (credential == null ? that.credential == null
                         : credential.equals(that.credential))
-                && (policy == null) ? that.policy == null : policy.equals(that.policy)
-                && (subscriptionUpdate == null) ? that.subscriptionUpdate == null
-                        : subscriptionUpdate.equals(that.subscriptionUpdate)
+                && (policy == null ? that.policy == null : policy.equals(that.policy))
+                && (subscriptionUpdate == null ? that.subscriptionUpdate == null
+                        : subscriptionUpdate.equals(that.subscriptionUpdate))
                 && isTrustRootCertListEquals(trustRootCertList, that.trustRootCertList)
                 && updateIdentifier == that.updateIdentifier
                 && credentialPriority == that.credentialPriority
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index b2583d3..bc29402 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -293,13 +293,13 @@
                 && minRoamingDownlinkBandwidth == that.minRoamingDownlinkBandwidth
                 && minRoamingUplinkBandwidth == that.minRoamingUplinkBandwidth
                 && Arrays.equals(excludedSsidList, that.excludedSsidList)
-                && (requiredProtoPortMap == null) ? that.requiredProtoPortMap == null
-                        : requiredProtoPortMap.equals(that.requiredProtoPortMap)
+                && (requiredProtoPortMap == null ? that.requiredProtoPortMap == null
+                        : requiredProtoPortMap.equals(that.requiredProtoPortMap))
                 && maximumBssLoadValue == that.maximumBssLoadValue
-                && (preferredRoamingPartnerList == null) ? that.preferredRoamingPartnerList == null
-                        : preferredRoamingPartnerList.equals(that.preferredRoamingPartnerList)
-                && (policyUpdate == null) ? that.policyUpdate == null
-                        : policyUpdate.equals(that.policyUpdate);
+                && (preferredRoamingPartnerList == null ? that.preferredRoamingPartnerList == null
+                        : preferredRoamingPartnerList.equals(that.preferredRoamingPartnerList))
+                && (policyUpdate == null ? that.policyUpdate == null
+                        : policyUpdate.equals(that.policyUpdate));
     }
 
     /**