Merge "Add more trace categories." into pi-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index db9d923..97c9fa5 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -377,6 +377,11 @@
     public abstract boolean isRecentsComponentHomeActivity(int userId);
 
     /**
+     * Cancels any currently running recents animation.
+     */
+    public abstract void cancelRecentsAnimation(boolean restoreHomeStackPosition);
+
+    /**
      * Whether an UID is active or idle.
      */
     public abstract boolean isUidActive(int uid);
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 7ae4cb7..3a05e70 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -57,13 +57,35 @@
         if (o instanceof BluetoothCodecStatus) {
             BluetoothCodecStatus other = (BluetoothCodecStatus) o;
             return (Objects.equals(other.mCodecConfig, mCodecConfig)
-                    && Objects.equals(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities)
-                    && Objects.equals(other.mCodecsSelectableCapabilities,
+                    && sameCapabilities(other.mCodecsLocalCapabilities, mCodecsLocalCapabilities)
+                    && sameCapabilities(other.mCodecsSelectableCapabilities,
                     mCodecsSelectableCapabilities));
         }
         return false;
     }
 
+    /**
+     * Checks whether two arrays of capabilities contain same capabilities.
+     * The order of the capabilities in each array is ignored.
+     *
+     * @param c1 the first array of capabilities to compare
+     * @param c2 the second array of capabilities to compare
+     * @return true if both arrays contain same capabilities
+     */
+    private static boolean sameCapabilities(BluetoothCodecConfig[] c1,
+                                            BluetoothCodecConfig[] c2) {
+        if (c1 == null) {
+            return (c2 == null);
+        }
+        if (c2 == null) {
+            return false;
+        }
+        if (c1.length != c2.length) {
+            return false;
+        }
+        return Arrays.asList(c1).containsAll(Arrays.asList(c2));
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mCodecConfig, mCodecsLocalCapabilities,
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
new file mode 100644
index 0000000..59b4665
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2018 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.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test cases for {@link BluetoothCodecConfig}.
+ * <p>
+ * To run this test, use:
+ * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecConfigTest.java
+ */
+public class BluetoothCodecConfigTest extends TestCase {
+    private static final int[] kCodecTypeArray = new int[] {
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX,
+        BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID,
+    };
+    private static final int[] kCodecPriorityArray = new int[] {
+        BluetoothCodecConfig.CODEC_PRIORITY_DISABLED,
+        BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+        BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
+    };
+    private static final int[] kSampleRateArray = new int[] {
+        BluetoothCodecConfig.SAMPLE_RATE_NONE,
+        BluetoothCodecConfig.SAMPLE_RATE_44100,
+        BluetoothCodecConfig.SAMPLE_RATE_48000,
+        BluetoothCodecConfig.SAMPLE_RATE_88200,
+        BluetoothCodecConfig.SAMPLE_RATE_96000,
+        BluetoothCodecConfig.SAMPLE_RATE_176400,
+        BluetoothCodecConfig.SAMPLE_RATE_192000,
+    };
+    private static final int[] kBitsPerSampleArray = new int[] {
+        BluetoothCodecConfig.BITS_PER_SAMPLE_NONE,
+        BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+        BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+        BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+    };
+    private static final int[] kChannelModeArray = new int[] {
+        BluetoothCodecConfig.CHANNEL_MODE_NONE,
+        BluetoothCodecConfig.CHANNEL_MODE_MONO,
+        BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+    };
+    private static final long[] kCodecSpecific1Array = new long[] { 1000, 1001, 1002, 1003, };
+    private static final long[] kCodecSpecific2Array = new long[] { 2000, 2001, 2002, 2003, };
+    private static final long[] kCodecSpecific3Array = new long[] { 3000, 3001, 3002, 3003, };
+    private static final long[] kCodecSpecific4Array = new long[] { 4000, 4001, 4002, 4003, };
+
+    private static final int kTotalConfigs = kCodecTypeArray.length * kCodecPriorityArray.length *
+        kSampleRateArray.length * kBitsPerSampleArray.length * kChannelModeArray.length *
+        kCodecSpecific1Array.length * kCodecSpecific2Array.length * kCodecSpecific3Array.length *
+        kCodecSpecific4Array.length;
+
+    private int selectCodecType(int configId) {
+        int left = kCodecTypeArray.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kCodecTypeArray.length;
+        return kCodecTypeArray[index];
+    }
+
+    private int selectCodecPriority(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kCodecPriorityArray.length;
+        return kCodecPriorityArray[index];
+    }
+
+    private int selectSampleRate(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kSampleRateArray.length;
+        return kSampleRateArray[index];
+    }
+
+    private int selectBitsPerSample(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
+            kBitsPerSampleArray.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kBitsPerSampleArray.length;
+        return kBitsPerSampleArray[index];
+    }
+
+    private int selectChannelMode(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
+            kBitsPerSampleArray.length * kChannelModeArray.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kChannelModeArray.length;
+        return kChannelModeArray[index];
+    }
+
+    private long selectCodecSpecific1(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
+            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kCodecSpecific1Array.length;
+        return kCodecSpecific1Array[index];
+    }
+
+    private long selectCodecSpecific2(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
+            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
+            kCodecSpecific2Array.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kCodecSpecific2Array.length;
+        return kCodecSpecific2Array[index];
+    }
+
+    private long selectCodecSpecific3(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
+            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
+            kCodecSpecific2Array.length * kCodecSpecific3Array.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kCodecSpecific3Array.length;
+        return kCodecSpecific3Array[index];
+    }
+
+    private long selectCodecSpecific4(int configId) {
+        int left = kCodecTypeArray.length * kCodecPriorityArray.length * kSampleRateArray.length *
+            kBitsPerSampleArray.length * kChannelModeArray.length * kCodecSpecific1Array.length *
+            kCodecSpecific2Array.length * kCodecSpecific3Array.length *
+            kCodecSpecific4Array.length;
+        int right = kTotalConfigs / left;
+        int index = configId / right;
+        index = index % kCodecSpecific4Array.length;
+        return kCodecSpecific4Array[index];
+    }
+
+    @SmallTest
+    public void testBluetoothCodecConfig_valid_get_methods() {
+
+        for (int config_id = 0; config_id < kTotalConfigs; config_id++) {
+            int codec_type = selectCodecType(config_id);
+            int codec_priority = selectCodecPriority(config_id);
+            int sample_rate = selectSampleRate(config_id);
+            int bits_per_sample = selectBitsPerSample(config_id);
+            int channel_mode = selectChannelMode(config_id);
+            long codec_specific1 = selectCodecSpecific1(config_id);
+            long codec_specific2 = selectCodecSpecific2(config_id);
+            long codec_specific3 = selectCodecSpecific3(config_id);
+            long codec_specific4 = selectCodecSpecific4(config_id);
+
+            BluetoothCodecConfig bcc = new BluetoothCodecConfig(codec_type, codec_priority,
+                                                                sample_rate, bits_per_sample,
+                                                                channel_mode, codec_specific1,
+                                                                codec_specific2, codec_specific3,
+                                                                codec_specific4);
+            if (sample_rate == BluetoothCodecConfig.SAMPLE_RATE_NONE) {
+                assertFalse(bcc.isValid());
+            } else if (bits_per_sample == BluetoothCodecConfig.BITS_PER_SAMPLE_NONE) {
+                assertFalse(bcc.isValid());
+            } else if (channel_mode == BluetoothCodecConfig.CHANNEL_MODE_NONE) {
+                assertFalse(bcc.isValid());
+            } else {
+                assertTrue(bcc.isValid());
+            }
+
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
+                assertTrue(bcc.isMandatoryCodec());
+            } else {
+                assertFalse(bcc.isMandatoryCodec());
+            }
+
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC) {
+                assertEquals("SBC", bcc.getCodecName());
+            }
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC) {
+                assertEquals("AAC", bcc.getCodecName());
+            }
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX) {
+                assertEquals("aptX", bcc.getCodecName());
+            }
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD) {
+                assertEquals("aptX HD", bcc.getCodecName());
+            }
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC) {
+                assertEquals("LDAC", bcc.getCodecName());
+            }
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX) {
+                assertEquals("UNKNOWN CODEC(" + BluetoothCodecConfig.SOURCE_CODEC_TYPE_MAX + ")",
+                             bcc.getCodecName());
+            }
+            if (codec_type == BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID) {
+                assertEquals("INVALID CODEC", bcc.getCodecName());
+            }
+
+            assertEquals(codec_type, bcc.getCodecType());
+            assertEquals(codec_priority, bcc.getCodecPriority());
+            assertEquals(sample_rate, bcc.getSampleRate());
+            assertEquals(bits_per_sample, bcc.getBitsPerSample());
+            assertEquals(channel_mode, bcc.getChannelMode());
+            assertEquals(codec_specific1, bcc.getCodecSpecific1());
+            assertEquals(codec_specific2, bcc.getCodecSpecific2());
+            assertEquals(codec_specific3, bcc.getCodecSpecific3());
+            assertEquals(codec_specific4, bcc.getCodecSpecific4());
+        }
+    }
+
+    @SmallTest
+    public void testBluetoothCodecConfig_equals() {
+        BluetoothCodecConfig bcc1 =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4000);
+
+        BluetoothCodecConfig bcc2_same =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4000);
+        assertTrue(bcc1.equals(bcc2_same));
+
+        BluetoothCodecConfig bcc3_codec_type =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4000);
+        assertFalse(bcc1.equals(bcc3_codec_type));
+
+        BluetoothCodecConfig bcc4_codec_priority =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4000);
+        assertFalse(bcc1.equals(bcc4_codec_priority));
+
+        BluetoothCodecConfig bcc5_sample_rate =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4000);
+        assertFalse(bcc1.equals(bcc5_sample_rate));
+
+        BluetoothCodecConfig bcc6_bits_per_sample =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4000);
+        assertFalse(bcc1.equals(bcc6_bits_per_sample));
+
+        BluetoothCodecConfig bcc7_channel_mode =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                     1000, 2000, 3000, 4000);
+        assertFalse(bcc1.equals(bcc7_channel_mode));
+
+        BluetoothCodecConfig bcc8_codec_specific1 =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1001, 2000, 3000, 4000);
+        assertFalse(bcc1.equals(bcc8_codec_specific1));
+
+        BluetoothCodecConfig bcc9_codec_specific2 =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2002, 3000, 4000);
+        assertFalse(bcc1.equals(bcc9_codec_specific2));
+
+        BluetoothCodecConfig bcc10_codec_specific3 =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3003, 4000);
+        assertFalse(bcc1.equals(bcc10_codec_specific3));
+
+        BluetoothCodecConfig bcc11_codec_specific4 =
+            new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                     BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                     BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                     BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                     BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                     1000, 2000, 3000, 4004);
+        assertFalse(bcc1.equals(bcc11_codec_specific4));
+    }
+}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
new file mode 100644
index 0000000..83bf2ed
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright 2018 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.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit test cases for {@link BluetoothCodecStatus}.
+ * <p>
+ * To run this test, use:
+ * runtest --path core/tests/bluetoothtests/src/android/bluetooth/BluetoothCodecStatusTest.java
+ */
+public class BluetoothCodecStatusTest extends TestCase {
+
+    // Codec configs: A and B are same; C is different
+    private static final BluetoothCodecConfig config_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig config_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig config_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    // Local capabilities: A and B are same; C is different
+    private static final BluetoothCodecConfig local_capability1_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability1_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability1_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+
+    private static final BluetoothCodecConfig local_capability2_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability2_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability2_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability3_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability3_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability3_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability4_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability4_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability4_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability5_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability5_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig local_capability5_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+
+    // Selectable capabilities: A and B are same; C is different
+    private static final BluetoothCodecConfig selectable_capability1_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability1_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability1_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability2_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability2_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability2_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability3_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability3_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability3_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability4_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability4_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability4_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability5_A =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability5_B =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO |
+                                 BluetoothCodecConfig.CHANNEL_MODE_MONO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig selectable_capability5_C =
+        new BluetoothCodecConfig(BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC,
+                                 BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT,
+                                 BluetoothCodecConfig.SAMPLE_RATE_44100 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_48000 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_88200 |
+                                 BluetoothCodecConfig.SAMPLE_RATE_96000,
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_16 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_24 |
+                                 BluetoothCodecConfig.BITS_PER_SAMPLE_32,
+                                 BluetoothCodecConfig.CHANNEL_MODE_STEREO,
+                                 1000, 2000, 3000, 4000);
+
+    private static final BluetoothCodecConfig[] local_capability_A = {
+        local_capability1_A,
+        local_capability2_A,
+        local_capability3_A,
+        local_capability4_A,
+        local_capability5_A,
+    };
+
+    private static final BluetoothCodecConfig[] local_capability_B = {
+        local_capability1_B,
+        local_capability2_B,
+        local_capability3_B,
+        local_capability4_B,
+        local_capability5_B,
+    };
+
+    private static final BluetoothCodecConfig[] local_capability_B_reordered = {
+        local_capability5_B,
+        local_capability4_B,
+        local_capability2_B,
+        local_capability3_B,
+        local_capability1_B,
+    };
+
+    private static final BluetoothCodecConfig[] local_capability_C = {
+        local_capability1_C,
+        local_capability2_C,
+        local_capability3_C,
+        local_capability4_C,
+        local_capability5_C,
+    };
+
+    private static final BluetoothCodecConfig[] selectable_capability_A = {
+        selectable_capability1_A,
+        selectable_capability2_A,
+        selectable_capability3_A,
+        selectable_capability4_A,
+        selectable_capability5_A,
+    };
+
+    private static final BluetoothCodecConfig[] selectable_capability_B = {
+        selectable_capability1_B,
+        selectable_capability2_B,
+        selectable_capability3_B,
+        selectable_capability4_B,
+        selectable_capability5_B,
+    };
+
+    private static final BluetoothCodecConfig[] selectable_capability_B_reordered = {
+        selectable_capability5_B,
+        selectable_capability4_B,
+        selectable_capability2_B,
+        selectable_capability3_B,
+        selectable_capability1_B,
+    };
+
+    private static final BluetoothCodecConfig[] selectable_capability_C = {
+        selectable_capability1_C,
+        selectable_capability2_C,
+        selectable_capability3_C,
+        selectable_capability4_C,
+        selectable_capability5_C,
+    };
+
+    private static final BluetoothCodecStatus bcs_A =
+        new BluetoothCodecStatus(config_A, local_capability_A, selectable_capability_A);
+    private static final BluetoothCodecStatus bcs_B =
+        new BluetoothCodecStatus(config_B, local_capability_B, selectable_capability_B);
+    private static final BluetoothCodecStatus bcs_B_reordered =
+        new BluetoothCodecStatus(config_B, local_capability_B_reordered,
+                                 selectable_capability_B_reordered);
+    private static final BluetoothCodecStatus bcs_C =
+        new BluetoothCodecStatus(config_C, local_capability_C, selectable_capability_C);
+
+    @SmallTest
+    public void testBluetoothCodecStatus_get_methods() {
+
+        assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_A));
+        assertTrue(Objects.equals(bcs_A.getCodecConfig(), config_B));
+        assertFalse(Objects.equals(bcs_A.getCodecConfig(), config_C));
+
+        assertTrue(Arrays.equals(bcs_A.getCodecsLocalCapabilities(), local_capability_A));
+        assertTrue(Arrays.equals(bcs_A.getCodecsLocalCapabilities(), local_capability_B));
+        assertFalse(Arrays.equals(bcs_A.getCodecsLocalCapabilities(), local_capability_C));
+
+        assertTrue(Arrays.equals(bcs_A.getCodecsSelectableCapabilities(),
+                                 selectable_capability_A));
+        assertTrue(Arrays.equals(bcs_A.getCodecsSelectableCapabilities(),
+                                  selectable_capability_B));
+        assertFalse(Arrays.equals(bcs_A.getCodecsSelectableCapabilities(),
+                                  selectable_capability_C));
+    }
+
+    @SmallTest
+    public void testBluetoothCodecStatus_equals() {
+        assertTrue(bcs_A.equals(bcs_B));
+        assertTrue(bcs_B.equals(bcs_A));
+        assertTrue(bcs_A.equals(bcs_B_reordered));
+        assertTrue(bcs_B_reordered.equals(bcs_A));
+        assertFalse(bcs_A.equals(bcs_C));
+        assertFalse(bcs_C.equals(bcs_A));
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
index e7c8c94..8160f90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButtonController.java
@@ -75,7 +75,8 @@
         int displayId = getDisplayId();
         for (ActivityManager.StackInfo stackInfo :stackInfoList) {
             // if the display id is known and does not match the stack we skip
-            if (displayId != -1 && displayId != stackInfo.displayId) {
+            if (displayId != -1 && displayId != stackInfo.displayId ||
+                    stackInfo.topActivity == null) {
                 continue;
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index 7d283d9..81d6191 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -28,8 +28,10 @@
 import android.os.IBinder;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
@@ -46,7 +48,7 @@
     private Handler mHandler;
     private Car mCar;
     private CarHvacManager mHvacManager;
-    private HashMap<HvacKey, TemperatureView> mTempComponents = new HashMap<>();
+    private HashMap<HvacKey, List<TemperatureView>> mTempComponents = new HashMap<>();
 
     public HvacController(Context context) {
         mContext = context;
@@ -114,18 +116,24 @@
      * @param temperatureView
      */
     public void addHvacTextView(TemperatureView temperatureView) {
-        mTempComponents.put(
-                new HvacKey(temperatureView.getPropertyId(), temperatureView.getAreaId()),
-                temperatureView);
+
+        HvacKey hvacKey = new HvacKey(temperatureView.getPropertyId(), temperatureView.getAreaId());
+        if (!mTempComponents.containsKey(hvacKey)) {
+            mTempComponents.put(hvacKey, new ArrayList<>());
+        }
+        mTempComponents.get(hvacKey).add(temperatureView);
         initComponent(temperatureView);
     }
 
     private void initComponents() {
-        Iterator<Map.Entry<HvacKey, TemperatureView>> iterator =
+        Iterator<Map.Entry<HvacKey, List<TemperatureView>>> iterator =
                 mTempComponents.entrySet().iterator();
         while (iterator.hasNext()) {
-            Map.Entry<HvacKey, TemperatureView> next = iterator.next();
-            initComponent(next.getValue());
+            Map.Entry<HvacKey, List<TemperatureView>> next = iterator.next();
+            List<TemperatureView> temperatureViews = next.getValue();
+            for (TemperatureView view : temperatureViews) {
+                initComponent(view);
+            }
         }
     }
 
@@ -155,11 +163,13 @@
             try {
                 int areaId = val.getAreaId();
                 int propertyId = val.getPropertyId();
-                TemperatureView temperatureView = mTempComponents.get(
+                List<TemperatureView> temperatureViews = mTempComponents.get(
                         new HvacKey(propertyId, areaId));
-                if (temperatureView != null) {
+                if (temperatureViews != null && !temperatureViews.isEmpty()) {
                     float value = (float) val.getValue();
-                    temperatureView.setTemp(value);
+                    for (TemperatureView tempView : temperatureViews) {
+                        tempView.setTemp(value);
+                    }
                 } // else the data is not of interest
             } catch (Exception e) {
                 // catch all so we don't take down the sysui if a new data type is
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 1b02e15..22a48f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -269,13 +269,6 @@
                 }
                 if (mCode != 0) {
                     if (doIt) {
-                        // If there was a pending remote recents animation, then we need to
-                        // cancel the animation now before we handle the button itself. In the case
-                        // where we are going home and the recents animation has already started,
-                        // just cancel the recents animation, leaving the home stack in place
-                        boolean isHomeKey = mCode == KEYCODE_HOME;
-                        ActivityManagerWrapper.getInstance().cancelRecentsAnimation(!isHomeKey);
-
                         sendEvent(KeyEvent.ACTION_UP, 0);
                         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
                     } else {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6951c50..6718d95 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -26633,6 +26633,11 @@
         }
 
         @Override
+        public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
+            ActivityManagerService.this.cancelRecentsAnimation(restoreHomeStackPosition);
+        }
+
+        @Override
         public boolean isUidActive(int uid) {
             synchronized (ActivityManagerService.this) {
                 final UidRecord uidRec = mActiveUids.get(uid);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 920e77f..bd4210c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -6091,6 +6091,14 @@
                 && (!isNavBarVirtKey || mNavBarVirtualKeyHapticFeedbackEnabled)
                 && event.getRepeatCount() == 0;
 
+        // Cancel any pending remote recents animations before handling the button itself. In the
+        // case where we are going home and the recents animation has already started, just cancel
+        // the recents animation, leaving the home stack in place for the pending start activity
+        if (isNavBarVirtKey && !down) {
+            boolean isHomeKey = keyCode == KeyEvent.KEYCODE_HOME;
+            mActivityManagerInternal.cancelRecentsAnimation(!isHomeKey);
+        }
+
         // Handle special keys.
         switch (keyCode) {
             case KeyEvent.KEYCODE_BACK: {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 08fa153..79b230d 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -369,7 +369,7 @@
     }
 
     void cancelAnimation(@ReorderMode int reorderMode, String reason) {
-        if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation()");
+        if (DEBUG_RECENTS_ANIMATIONS) Slog.d(TAG, "cancelAnimation(): reason=" + reason);
         synchronized (mService.getWindowManagerLock()) {
             if (mCanceled) {
                 // We've already canceled the animation
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 1b06b2f..67ef471 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -83,7 +83,8 @@
      */
     AnimationAdapter createAnimationAdapter(AppWindowToken appWindowToken, Point position,
             Rect stackBounds) {
-        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "createAnimationAdapter(): token=" + appWindowToken);
+        if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "createAnimationAdapter(): token="
+                + appWindowToken);
         final RemoteAnimationAdapterWrapper adapter = new RemoteAnimationAdapterWrapper(
                 appWindowToken, position, stackBounds);
         mPendingAnimations.add(adapter);
@@ -96,8 +97,9 @@
     void goodToGo() {
         if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo()");
         if (mPendingAnimations.isEmpty() || mCanceled) {
-            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo(): Animation finished before good to go, canceled="
-                    + mCanceled + " mPendingAnimations=" + mPendingAnimations.size());
+            if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "goodToGo(): Animation finished already,"
+                    + " canceled=" + mCanceled
+                    + " mPendingAnimations=" + mPendingAnimations.size());
             onAnimationFinished();
             return;
         }
@@ -123,10 +125,6 @@
             }
             if (DEBUG_REMOTE_ANIMATIONS) {
                 Slog.d(TAG, "startAnimation(): Notify animation start:");
-                for (int i = 0; i < mPendingAnimations.size(); i++) {
-                    Slog.d(TAG, "\t" + mPendingAnimations.get(i).mAppWindowToken);
-                }
-            } else if (DEBUG_APP_TRANSITIONS) {
                 writeStartDebugStatement();
             }
         });
@@ -166,7 +164,8 @@
                 if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tAdd token=" + wrapper.mAppWindowToken);
                 targets.add(target);
             } else {
-                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tRemove token=" + wrapper.mAppWindowToken);
+                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "\tRemove token="
+                        + wrapper.mAppWindowToken);
 
                 // We can't really start an animation but we still need to make sure to finish the
                 // pending animation that was started by SurfaceAnimator
@@ -188,7 +187,8 @@
             releaseFinishedCallback();
             mService.openSurfaceTransaction();
             try {
-                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG, "onAnimationFinished(): Notify animation finished:");
+                if (DEBUG_REMOTE_ANIMATIONS) Slog.d(TAG,
+                        "onAnimationFinished(): Notify animation finished:");
                 for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
                     final RemoteAnimationAdapterWrapper adapter = mPendingAnimations.get(i);
                     adapter.mCapturedFinishCallback.onAnimationFinished(adapter);
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 87249df..9fdb31e 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -16,6 +16,7 @@
 
 package android.net.ip;
 
+import com.android.internal.util.HexDump;
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.WakeupMessage;
 
@@ -142,6 +143,12 @@
         // Install an APF program to filter incoming packets.
         public void installPacketFilter(byte[] filter) {}
 
+        // Asynchronously read back the APF program & data buffer from the wifi driver.
+        // Due to Wifi HAL limitations, the current implementation only supports dumping the entire
+        // buffer. In response to this request, the driver returns the data buffer asynchronously
+        // by sending an IpClient#EVENT_READ_PACKET_FILTER_COMPLETE message.
+        public void startReadPacketFilter() {}
+
         // If multicast filtering cannot be accomplished with APF, this function will be called to
         // actuate multicast filtering using another means.
         public void setFallbackMulticastFilter(boolean enabled) {}
@@ -248,6 +255,11 @@
             log("installPacketFilter(byte[" + filter.length + "])");
         }
         @Override
+        public void startReadPacketFilter() {
+            mCallback.startReadPacketFilter();
+            log("startReadPacketFilter()");
+        }
+        @Override
         public void setFallbackMulticastFilter(boolean enabled) {
             mCallback.setFallbackMulticastFilter(enabled);
             log("setFallbackMulticastFilter(" + enabled + ")");
@@ -559,6 +571,7 @@
     private static final int CMD_SET_MULTICAST_FILTER             = 9;
     private static final int EVENT_PROVISIONING_TIMEOUT           = 10;
     private static final int EVENT_DHCPACTION_TIMEOUT             = 11;
+    private static final int EVENT_READ_PACKET_FILTER_COMPLETE    = 12;
 
     private static final int MAX_LOG_RECORDS = 500;
     private static final int MAX_PACKET_RECORDS = 100;
@@ -611,6 +624,7 @@
     private ApfFilter mApfFilter;
     private boolean mMulticastFiltering;
     private long mStartTimeMillis;
+    private byte[] mApfDataSnapshot;
 
     public static class Dependencies {
         public INetworkManagementService getNMS() {
@@ -823,6 +837,10 @@
         sendMessage(EVENT_PRE_DHCP_ACTION_COMPLETE);
     }
 
+    public void readPacketFilterComplete(byte[] data) {
+        sendMessage(EVENT_READ_PACKET_FILTER_COMPLETE, data);
+    }
+
     /**
      * Set the TCP buffer sizes to use.
      *
@@ -863,6 +881,7 @@
         final ProvisioningConfiguration provisioningConfig = mConfiguration;
         final ApfCapabilities apfCapabilities = (provisioningConfig != null)
                 ? provisioningConfig.mApfCapabilities : null;
+        final byte[] apfDataSnapshot = mApfDataSnapshot;
 
         IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         pw.println(mTag + " APF dump:");
@@ -880,6 +899,14 @@
             }
         }
         pw.decreaseIndent();
+        pw.println(mTag + " latest APF data snapshot: ");
+        pw.increaseIndent();
+        if (apfDataSnapshot != null) {
+            pw.println(HexDump.dumpHexString(apfDataSnapshot));
+        } else {
+            pw.println("No last snapshot.");
+        }
+        pw.decreaseIndent();
 
         pw.println();
         pw.println(mTag + " current ProvisioningConfiguration:");
@@ -1676,6 +1703,11 @@
                     break;
                 }
 
+                case EVENT_READ_PACKET_FILTER_COMPLETE: {
+                    mApfDataSnapshot = (byte[]) msg.obj;
+                    break;
+                }
+
                 case EVENT_DHCPACTION_TIMEOUT:
                     stopDhcpAction();
                     break;