Merge "Remove mIsConnectingErrorPossible because no one uses"
diff --git a/api/current.txt b/api/current.txt
index e31f8a0..b9e00f6 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -42654,6 +42654,7 @@
     method public static int[] getSubscriptionIds(int);
     method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
     method public boolean isNetworkRoaming(int);
+    method public static boolean isValidSubscriptionId(int);
     method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method public void setSubscriptionOverrideCongested(int, boolean, long);
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 1ee3c93..cb33659 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -58,7 +58,7 @@
  * execute in parallel with any {@link Surface} initialization, such as waiting for a
  * {@link android.view.SurfaceView} to be ready as part of the UI initialization.</li>
  *
- * <li>The third and most complex usage pattern inlvolves surface sharing. Once instantiated an
+ * <li>The third and most complex usage pattern involves surface sharing. Once instantiated an
  * OutputConfiguration can be enabled for surface sharing via {@link #enableSurfaceSharing}. This
  * must be done before creating a new capture session and enables calls to
  * {@link CameraCaptureSession#updateOutputConfiguration}. An OutputConfiguration with enabled
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 6d9ba77..7e52ca3 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -141,13 +141,6 @@
         private String mDescription;
 
         /**
-         * STOPSHIP remove when app has stopped using this.
-         * @hide
-         */
-        public Builder() {
-        }
-
-        /**
          * Constructs the builder with the control points for the brightness curve.
          *
          * Brightness curves must have strictly increasing ambient brightness values in lux and
@@ -159,24 +152,6 @@
          * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
          */
         public Builder(float[] lux, float[] nits) {
-            setCurve(lux, nits);
-        }
-
-        /**
-         * Sets the control points for the brightness curve.
-         *
-         * Brightness curves must have strictly increasing ambient brightness values in lux and
-         * monotonically increasing display brightness values in nits. In addition, the initial
-         * control point must be 0 lux.
-         *
-         * @throws IllegalArgumentException if the initial control point is not at 0 lux.
-         * @throws IllegalArgumentException if the lux levels are not strictly increasing.
-         * @throws IllegalArgumentException if the nit levels are not monotonically increasing.
-         *
-         * STOPSHIP remove when app has stopped using this.
-         * @hide
-         */
-        public Builder setCurve(float[] lux, float[] nits) {
             Preconditions.checkNotNull(lux);
             Preconditions.checkNotNull(nits);
             if (lux.length == 0 || nits.length == 0) {
@@ -190,11 +165,10 @@
             }
             Preconditions.checkArrayElementsInRange(lux, 0, Float.MAX_VALUE, "lux");
             Preconditions.checkArrayElementsInRange(nits, 0, Float.MAX_VALUE, "nits");
-            checkMonotonic(lux, true/*strictly increasing*/, "lux");
+            checkMonotonic(lux, true /*strictly increasing*/, "lux");
             checkMonotonic(nits, false /*strictly increasing*/, "nits");
             mCurveLux = lux;
             mCurveNits = nits;
-            return this;
         }
 
         /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0645a16..d913273 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -313,6 +313,7 @@
  * @attr ref android.R.styleable#TextView_fallbackLineSpacing
  * @attr ref android.R.styleable#TextView_letterSpacing
  * @attr ref android.R.styleable#TextView_fontFeatureSettings
+ * @attr ref android.R.styleable#TextView_fontVariationSettings
  * @attr ref android.R.styleable#TextView_breakStrategy
  * @attr ref android.R.styleable#TextView_hyphenationFrequency
  * @attr ref android.R.styleable#TextView_autoSizeTextType
@@ -4382,6 +4383,8 @@
      *
      * @see #getFontVariationSettings()
      * @see FontVariationAxis
+     *
+     * @attr ref android.R.styleable#TextView_fontVariationSettings
      */
     public boolean setFontVariationSettings(@Nullable String fontVariationSettings) {
         final String existingSettings = mTextPaint.getFontVariationSettings();
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 9065bac..9ab55d6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3352,7 +3352,7 @@
           @hide
           @removed -->
     <permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|privileged" />
 
     <!-- @SystemApi Allows an application to know what content is playing and control its playback.
          <p>Not for use by third-party applications due to privacy of media consumption</p>  -->
@@ -4120,11 +4120,6 @@
     <permission android:name="android.permission.DISABLE_HIDDEN_API_CHECKS"
                 android:protectionLevel="signature" />
 
-    <!-- Allows an application to read emergency info name.
-         @hide <p>Not for use by third-party applications. -->
-    <permission android:name="com.android.emergency.permission.READ_EMERGENCY_INFO_NAME"
-                android:protectionLevel="signature" />
-
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/values-night/themes_device_defaults.xml b/core/res/res/values-night/themes_device_defaults.xml
index 5e3675a..c8d4d05 100644
--- a/core/res/res/values-night/themes_device_defaults.xml
+++ b/core/res/res/values-night/themes_device_defaults.xml
@@ -51,4 +51,7 @@
           -->
     <!-- DeviceDefault theme for a window that should look like the Settings app.  -->
     <style name="Theme.DeviceDefault.Settings" parent="Theme.DeviceDefault"/>
+
+    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert" />
 </resources>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index 377982a..0712cbc 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -15,7 +15,7 @@
 -->
 <resources>
     <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
-    <style name="Theme.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
diff --git a/core/res/res/values-watch/themes.xml b/core/res/res/values-watch/themes.xml
index 04df180..1be47ba 100644
--- a/core/res/res/values-watch/themes.xml
+++ b/core/res/res/values-watch/themes.xml
@@ -15,7 +15,7 @@
 -->
 <resources>
     <!-- Theme for the dialog shown when an app crashes or ANRs. Override to make it dark. -->
-    <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Dialog.Alert">
         <item name="windowContentTransitions">false</item>
         <item name="windowActivityTransitions">false</item>
         <item name="windowCloseOnTouchOutside">false</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 92cca72..389278f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2099,7 +2099,7 @@
   <java-symbol type="string" name="vpn_lockdown_error" />
   <java-symbol type="string" name="vpn_lockdown_config" />
   <java-symbol type="string" name="wallpaper_binding_label" />
-  <java-symbol type="style" name="Theme.Dialog.AppError" />
+  <java-symbol type="style" name="Theme.DeviceDefault.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Leanback.Dialog.Alert" />
   <java-symbol type="style" name="Theme.Toast" />
   <java-symbol type="xml" name="storage_list" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 3937af5..a7530ce 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -869,13 +869,6 @@
     <!-- System themes -->
     <eat-comment />
 
-    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
-    <style name="Theme.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
-        <item name="windowContentTransitions">false</item>
-        <item name="windowActivityTransitions">false</item>
-        <item name="windowCloseOnTouchOutside">false</item>
-    </style>
-
     <!-- Special theme for the recent apps dialog, to allow customization
          with overlays. -->
     <style name="Theme.Dialog.RecentApplications" parent="Theme.DeviceDefault.Light.Dialog">
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 14e5082..92096ab 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -719,6 +719,13 @@
         <item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
     </style>
 
+    <!-- Theme for the dialog shown when an app crashes or ANRs. -->
+    <style name="Theme.DeviceDefault.Dialog.AppError" parent="Theme.DeviceDefault.Light.Dialog.Alert">
+        <item name="windowContentTransitions">false</item>
+        <item name="windowActivityTransitions">false</item>
+        <item name="windowCloseOnTouchOutside">false</item>
+    </style>
+
     <style name="Theme.DeviceDefault.SearchBar" parent="Theme.Material.SearchBar">
         <!-- Color palette -->
         <item name="colorPrimary">@color/primary_device_default_dark</item>
diff --git a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
index 5ef30a8..dcc51e1 100644
--- a/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
+++ b/core/tests/coretests/src/android/hardware/display/BrightnessConfigurationTest.java
@@ -48,8 +48,8 @@
 
     @Test
     public void testSetCurveIsUnmodified() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration config = builder.build();
         Pair<float[], float[]> curve = config.getCurve();
         assertArrayEquals(LUX_LEVELS, curve.first, "lux");
@@ -58,45 +58,33 @@
 
     @Test(expected = IllegalArgumentException.class)
     public void testCurveMustHaveZeroLuxPoint() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[0] = 1f;
-        builder.setCurve(lux, NITS_LEVELS);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testCurveMustBeSet() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.build();
+        new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
     }
 
     @Test(expected = NullPointerException.class)
     public void testCurveMustNotHaveNullArrays() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(null, null);
+        new BrightnessConfiguration.Builder(null, null);
     }
 
     @Test(expected = IllegalArgumentException.class)
     public void testCurveMustNotHaveEmptyArrays() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(new float[0], new float[0]);
+        new BrightnessConfiguration.Builder(new float[0], new float[0]);
     }
 
     @Test
     public void testCurveMustNotHaveArraysOfDifferentLengths() {
         assertThrows(IllegalArgumentException.class, () -> {
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
             float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length + 1);
             lux[lux.length - 1] = lux[lux.length - 2] + 1;
-            boolean exceptionThrown = false;
-            builder.setCurve(lux, NITS_LEVELS);
+            new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
             float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length + 1);
             nits[nits.length - 1] = nits[nits.length - 2] + 1;
-            builder.setCurve(LUX_LEVELS, nits);
+            new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         });
     }
 
@@ -105,23 +93,21 @@
         assertThrows(IllegalArgumentException.class, () -> {
             float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
             lux[lux.length - 1] = Float.NaN;
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(lux, NITS_LEVELS);
+            new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         });
 
         assertThrows(IllegalArgumentException.class, () -> {
             float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
             nits[nits.length - 1] = Float.NaN;
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(LUX_LEVELS, nits);
+            new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         });
     }
 
 
     @Test
     public void testParceledConfigIsEquivalent() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration config = builder.build();
         Parcel p = Parcel.obtain();
         p.writeParcelable(config, 0 /*flags*/);
@@ -133,12 +119,11 @@
 
     @Test
     public void testEquals() {
-        BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        BrightnessConfiguration.Builder builder =
+                new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration baseConfig = builder.build();
 
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, NITS_LEVELS);
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, NITS_LEVELS);
         BrightnessConfiguration identicalConfig = builder.build();
         assertEquals(baseConfig, identicalConfig);
         assertEquals("hashCodes must be equal for identical configs",
@@ -146,15 +131,13 @@
 
         float[] lux = Arrays.copyOf(LUX_LEVELS, LUX_LEVELS.length);
         lux[lux.length - 1] = lux[lux.length - 1] * 2;
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(lux, NITS_LEVELS);
+        builder = new BrightnessConfiguration.Builder(lux, NITS_LEVELS);
         BrightnessConfiguration luxDifferConfig = builder.build();
         assertNotEquals(baseConfig, luxDifferConfig);
 
         float[] nits = Arrays.copyOf(NITS_LEVELS, NITS_LEVELS.length);
         nits[nits.length - 1] = nits[nits.length - 1] * 2;
-        builder = new BrightnessConfiguration.Builder();
-        builder.setCurve(LUX_LEVELS, nits);
+        builder = new BrightnessConfiguration.Builder(LUX_LEVELS, nits);
         BrightnessConfiguration nitsDifferConfig = builder.build();
         assertNotEquals(baseConfig, nitsDifferConfig);
     }
diff --git a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
index 920988b..9e44554 100644
--- a/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
+++ b/core/tests/coretests/src/android/os/SetPersistentVrThreadTest.java
@@ -24,7 +24,6 @@
 import android.provider.Settings;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
 /**
  * Tests ActivityManager#setPersistentVrThread and ActivityManager#setVrThread's
@@ -76,9 +75,11 @@
     }
 
     private void setPersistentVrModeEnabled(boolean enable) throws Throwable {
-        mVrManager.setPersistentVrModeEnabled(enable);
-        // Allow the system time to send out callbacks for persistent VR mode.
-        Thread.sleep(200);
+        if (mVrManager != null) {
+            mVrManager.setPersistentVrModeEnabled(enable);
+            // Allow the system time to send out callbacks for persistent VR mode.
+            Thread.sleep(200);
+        }
     }
 
     @SmallTest
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index 339a7ee..7681cc3 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -91,6 +91,7 @@
         "android_media_Media2HTTPConnection.cpp",
         "android_media_Media2HTTPService.cpp",
         "android_media_Media2DataSource.cpp",
+        "android_media_MediaMetricsJNI.cpp",
         "android_media_MediaPlayer2.cpp",
         "android_media_SyncParams.cpp",
     ],
@@ -98,7 +99,6 @@
     shared_libs: [
         "android.hardware.cas@1.0",  // for CasManager. VNDK???
         "android.hardware.cas.native@1.0",  // CasManager. VNDK???
-        "libandroid_runtime",  // ???
         "libaudioclient",  // for use of AudioTrack, AudioSystem. to be removed
         "libbinder",
         "libgui",  // for VideoFrameScheduler
@@ -120,13 +120,9 @@
     header_libs: ["libhardware_headers"],
 
     static_libs: [
-        "libbacktrace",
         "libbase",
-        "libc_malloc_debug_backtrace",
         "libcrypto",
         "libcutils",
-        "libdexfile",
-        "liblzma",
         "libmedia_helper",
         "libmedia_player2_util",
         "libmediadrm",
@@ -135,7 +131,7 @@
         "libmediaplayer2",
         "libmediaplayer2-protos",
         "libmediautils",
-        "libnetd_client",
+        "libnetd_client",  // for setNetworkForUser
         "libprotobuf-cpp-lite",
         "libstagefright_esds",
         "libstagefright_foundation",
@@ -146,9 +142,6 @@
         "libstagefright_player2",
         "libstagefright_rtsp",
         "libstagefright_timedtext2",
-        "libunwindstack",
-        "libutilscallstack",
-        "libziparchive",
     ],
 
     group_static_libs: true,
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
new file mode 100644
index 0000000..3ded8c2
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright 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.
+ */
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+
+#include "android_media_MediaMetricsJNI.h"
+#include <media/MediaAnalyticsItem.h>
+
+
+// Copeid from core/jni/ (libandroid_runtime.so)
+namespace android {
+
+// place the attributes into a java PersistableBundle object
+jobject MediaMetricsJNI::writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle) {
+
+    jclass clazzBundle = env->FindClass("android/os/PersistableBundle");
+    if (clazzBundle==NULL) {
+        ALOGD("can't find android/os/PersistableBundle");
+        return NULL;
+    }
+    // sometimes the caller provides one for us to fill
+    if (mybundle == NULL) {
+        // create the bundle
+        jmethodID constructID = env->GetMethodID(clazzBundle, "<init>", "()V");
+        mybundle = env->NewObject(clazzBundle, constructID);
+        if (mybundle == NULL) {
+            return NULL;
+        }
+    }
+
+    // grab methods that we can invoke
+    jmethodID setIntID = env->GetMethodID(clazzBundle, "putInt", "(Ljava/lang/String;I)V");
+    jmethodID setLongID = env->GetMethodID(clazzBundle, "putLong", "(Ljava/lang/String;J)V");
+    jmethodID setDoubleID = env->GetMethodID(clazzBundle, "putDouble", "(Ljava/lang/String;D)V");
+    jmethodID setStringID = env->GetMethodID(clazzBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V");
+
+    // env, class, method, {parms}
+    //env->CallVoidMethod(env, mybundle, setIntID, jstr, jint);
+
+    // iterate through my attributes
+    // -- get name, get type, get value
+    // -- insert appropriately into the bundle
+    for (size_t i = 0 ; i < item->mPropCount; i++ ) {
+            MediaAnalyticsItem::Prop *prop = &item->mProps[i];
+            // build the key parameter from prop->mName
+            jstring keyName = env->NewStringUTF(prop->mName);
+            // invoke the appropriate method to insert
+            switch (prop->mType) {
+                case MediaAnalyticsItem::kTypeInt32:
+                    env->CallVoidMethod(mybundle, setIntID,
+                                        keyName, (jint) prop->u.int32Value);
+                    break;
+                case MediaAnalyticsItem::kTypeInt64:
+                    env->CallVoidMethod(mybundle, setLongID,
+                                        keyName, (jlong) prop->u.int64Value);
+                    break;
+                case MediaAnalyticsItem::kTypeDouble:
+                    env->CallVoidMethod(mybundle, setDoubleID,
+                                        keyName, (jdouble) prop->u.doubleValue);
+                    break;
+                case MediaAnalyticsItem::kTypeCString:
+                    env->CallVoidMethod(mybundle, setStringID, keyName,
+                                        env->NewStringUTF(prop->u.CStringValue));
+                    break;
+                default:
+                        ALOGE("to_String bad item type: %d for %s",
+                              prop->mType, prop->mName);
+                        break;
+            }
+    }
+
+    return mybundle;
+}
+
+};  // namespace android
+
diff --git a/media/jni/android_media_MediaMetricsJNI.h b/media/jni/android_media_MediaMetricsJNI.h
new file mode 100644
index 0000000..fd621ea
--- /dev/null
+++ b/media/jni/android_media_MediaMetricsJNI.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+#define _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <media/MediaAnalyticsItem.h>
+
+// Copeid from core/jni/ (libandroid_runtime.so)
+namespace android {
+
+class MediaMetricsJNI {
+public:
+    static jobject writeMetricsToBundle(JNIEnv* env, MediaAnalyticsItem *item, jobject mybundle);
+};
+
+};  // namespace android
+
+#endif //  _ANDROID_MEDIA_MEDIAMETRICSJNI_H_
diff --git a/media/jni/android_media_MediaPlayer2.cpp b/media/jni/android_media_MediaPlayer2.cpp
index 801dade..a2bf549 100644
--- a/media/jni/android_media_MediaPlayer2.cpp
+++ b/media/jni/android_media_MediaPlayer2.cpp
@@ -909,7 +909,7 @@
 }
 
 static jboolean
-android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
+android_media_MediaPlayer2_setParameter(JNIEnv *env, jobject thiz, jint key, jobject)
 {
     ALOGV("setParameter: key %d", key);
     sp<MediaPlayer2> mp = getMediaPlayer(env, thiz);
@@ -918,9 +918,11 @@
         return false;
     }
 
-    // TODO: parcelForJavaObject() shouldn't be used since it's dependent on
-    //       framework's Parcel implementation. This setParameter() is used
-    //       only with AudioAttribute. Can this be used as jobject with JAudioTrack?
+    return false;
+    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
+    //       Once JAudioTrack migration is done, the AudioAttribute jobject
+    //       should be directly passed to AudioTrack without native parcel conversion.
+    /*
     Parcel *request = parcelForJavaObject(env, java_request);
     status_t err = mp->setParameter(key, *request);
     if (err == OK) {
@@ -928,6 +930,7 @@
     } else {
         return false;
     }
+    */
 }
 
 static jobject
@@ -940,6 +943,11 @@
         return NULL;
     }
 
+    return NULL;
+    // TODO: set/getParameter is temporarily disabled to remove android_runtime.so dependency.
+    //       Once JAudioTrack migration is done, the AudioAttribute jobject
+    //       should be directly passed to AudioTrack without native parcel conversion.
+    /*
     jobject jParcel = createJavaParcelObject(env);
     if (jParcel != NULL) {
         Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
@@ -950,6 +958,7 @@
         }
     }
     return jParcel;
+    */
 }
 
 static void
@@ -1019,55 +1028,6 @@
     return out;
 }
 
-// Sends the new filter to the client.
-static jint
-android_media_MediaPlayer2_setMetadataFilter(JNIEnv *env, jobject thiz, jobject request)
-{
-    sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return UNKNOWN_ERROR;
-    }
-
-    Parcel *filter = parcelForJavaObject(env, request);
-
-    if (filter == NULL ) {
-        jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
-        return UNKNOWN_ERROR;
-    }
-
-    return (jint) media_player->setMetadataFilter(*filter);
-}
-
-static jboolean
-android_media_MediaPlayer2_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
-                                      jboolean apply_filter, jobject reply)
-{
-    sp<MediaPlayer2> media_player = getMediaPlayer(env, thiz);
-    if (media_player == NULL ) {
-        jniThrowException(env, "java/lang/IllegalStateException", NULL);
-        return JNI_FALSE;
-    }
-
-    Parcel *metadata = parcelForJavaObject(env, reply);
-
-    if (metadata == NULL ) {
-        jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
-        return JNI_FALSE;
-    }
-
-    metadata->freeData();
-    // On return metadata is positioned at the beginning of the
-    // metadata. Note however that the parcel actually starts with the
-    // return code so you should not rewind the parcel using
-    // setDataPosition(0).
-    if (media_player->getMetadata(update_only, apply_filter, metadata) == OK) {
-        return JNI_TRUE;
-    } else {
-        return JNI_FALSE;
-    }
-}
-
 // This function gets some field IDs, which in turn causes class initialization.
 // It is called from a static block in MediaPlayer2, which won't run until the
 // first time an instance of this class is used.
@@ -1532,8 +1492,6 @@
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer2_isLooping},
     {"_setVolume",          "(FF)V",                            (void *)android_media_MediaPlayer2_setVolume},
     {"_invoke",             "([B)[B",                           (void *)android_media_MediaPlayer2_invoke},
-    {"native_setMetadataFilter", "(Landroid/os/Parcel;)I",      (void *)android_media_MediaPlayer2_setMetadataFilter},
-    {"native_getMetadata", "(ZZLandroid/os/Parcel;)Z",          (void *)android_media_MediaPlayer2_getMetadata},
     {"native_init",         "()V",                              (void *)android_media_MediaPlayer2_native_init},
     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer2_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer2_native_finalize},
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
index 0c4e02b..e13e566 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpSinkProfile.java
@@ -33,7 +33,6 @@
 
 final class A2dpSinkProfile implements LocalBluetoothProfile {
     private static final String TAG = "A2dpSinkProfile";
-    private static boolean V = true;
 
     private BluetoothA2dpSink mService;
     private boolean mIsProfileReady;
@@ -56,7 +55,7 @@
             implements BluetoothProfile.ServiceListener {
 
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothA2dpSink) proxy;
             // We just bound to the service, so refresh the UI for any connected A2DP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -75,7 +74,7 @@
         }
 
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mIsProfileReady=false;
         }
     }
@@ -106,7 +105,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -114,24 +115,18 @@
     }
 
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> srcs = getConnectedDevices();
-        if (srcs != null) {
-            for (BluetoothDevice src : srcs) {
-                if (src.equals(device)) {
-                    // Connect to same device, Ignore it
-                    Log.d(TAG,"Ignoring Connect");
-                    return true;
-                }
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting the headset.
-        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
+        if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
         }
         return mService.disconnect(device);
@@ -145,17 +140,23 @@
     }
 
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -166,7 +167,9 @@
     }
 
     boolean isA2dpPlaying() {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         List<BluetoothDevice> srcs = mService.getConnectedDevices();
         if (!srcs.isEmpty()) {
             if (mService.isA2dpPlaying(srcs.get(0))) {
@@ -208,7 +211,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.A2DP_SINK,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
index f9f6233..4b6a22c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HfpClientProfile.java
@@ -36,7 +36,6 @@
  */
 final class HfpClientProfile implements LocalBluetoothProfile {
     private static final String TAG = "HfpClientProfile";
-    private static boolean V = false;
 
     private BluetoothHeadsetClient mService;
     private boolean mIsProfileReady;
@@ -60,7 +59,7 @@
 
         @Override
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
-            if (V) Log.d(TAG,"Bluetooth service connected");
+            Log.d(TAG, "Bluetooth service connected");
             mService = (BluetoothHeadsetClient) proxy;
             // We just bound to the service, so refresh the UI for any connected HFP devices.
             List<BluetoothDevice> deviceList = mService.getConnectedDevices();
@@ -81,7 +80,7 @@
 
         @Override
         public void onServiceDisconnected(int profile) {
-            if (V) Log.d(TAG,"Bluetooth service disconnected");
+            Log.d(TAG, "Bluetooth service disconnected");
             mIsProfileReady=false;
         }
     }
@@ -115,7 +114,9 @@
     }
 
     public List<BluetoothDevice> getConnectedDevices() {
-        if (mService == null) return new ArrayList<BluetoothDevice>(0);
+        if (mService == null) {
+            return new ArrayList<BluetoothDevice>(0);
+        }
         return mService.getDevicesMatchingConnectionStates(
               new int[] {BluetoothProfile.STATE_CONNECTED,
                          BluetoothProfile.STATE_CONNECTING,
@@ -124,23 +125,17 @@
 
     @Override
     public boolean connect(BluetoothDevice device) {
-        if (mService == null) return false;
-        List<BluetoothDevice> srcs = getConnectedDevices();
-        if (srcs != null) {
-            for (BluetoothDevice src : srcs) {
-                if (src.equals(device)) {
-                    // Connect to same device, Ignore it
-                    Log.d(TAG,"Ignoring Connect");
-                    return true;
-                }
-            }
+        if (mService == null) {
+            return false;
         }
         return mService.connect(device);
     }
 
     @Override
     public boolean disconnect(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         // Downgrade priority as user is disconnecting the headset.
         if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON){
             mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -158,19 +153,25 @@
 
     @Override
     public boolean isPreferred(BluetoothDevice device) {
-        if (mService == null) return false;
+        if (mService == null) {
+            return false;
+        }
         return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
     }
 
     @Override
     public int getPreferred(BluetoothDevice device) {
-        if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+        if (mService == null) {
+            return BluetoothProfile.PRIORITY_OFF;
+        }
         return mService.getPriority(device);
     }
 
     @Override
     public void setPreferred(BluetoothDevice device, boolean preferred) {
-        if (mService == null) return;
+        if (mService == null) {
+            return;
+        }
         if (preferred) {
             if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
                 mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
@@ -216,7 +217,7 @@
     }
 
     protected void finalize() {
-        if (V) Log.d(TAG, "finalize()");
+        Log.d(TAG, "finalize()");
         if (mService != null) {
             try {
                 BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
new file mode 100644
index 0000000..274fff8
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpSinkProfileTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothA2dpSink;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class A2dpSinkProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothA2dpSink mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private A2dpSinkProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new A2dpSinkProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothA2dpSink() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothA2dpSink() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
\ No newline at end of file
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
new file mode 100644
index 0000000..187be0b
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HfpClientProfileTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 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 com.android.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadsetClient;
+import android.bluetooth.BluetoothProfile;
+
+import com.android.settingslib.SettingsLibRobolectricTestRunner;
+import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadow.api.Shadow;
+
+@RunWith(SettingsLibRobolectricTestRunner.class)
+@Config(shadows = {ShadowBluetoothAdapter.class})
+public class HfpClientProfileTest {
+
+    @Mock
+    private CachedBluetoothDeviceManager mDeviceManager;
+    @Mock
+    private LocalBluetoothProfileManager mProfileManager;
+    @Mock
+    private BluetoothHeadsetClient mService;
+    @Mock
+    private CachedBluetoothDevice mCachedBluetoothDevice;
+    @Mock
+    private BluetoothDevice mBluetoothDevice;
+    private BluetoothProfile.ServiceListener mServiceListener;
+    private HfpClientProfile mProfile;
+    private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mShadowBluetoothAdapter = Shadow.extract(BluetoothAdapter.getDefaultAdapter());
+        mProfile = new HfpClientProfile(RuntimeEnvironment.application,
+                mDeviceManager, mProfileManager);
+        mServiceListener = mShadowBluetoothAdapter.getServiceListener();
+        mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT, mService);
+    }
+
+    @Test
+    public void connect_shouldConnectBluetoothHeadsetClient() {
+        mProfile.connect(mBluetoothDevice);
+        verify(mService).connect(mBluetoothDevice);
+    }
+
+    @Test
+    public void disconnect_shouldDisconnectBluetoothHeadsetClient() {
+        mProfile.disconnect(mBluetoothDevice);
+        verify(mService).disconnect(mBluetoothDevice);
+    }
+
+    @Test
+    public void getConnectionStatus_shouldReturnConnectionState() {
+        when(mService.getConnectionState(mBluetoothDevice)).
+                thenReturn(BluetoothProfile.STATE_CONNECTED);
+        assertThat(mProfile.getConnectionStatus(mBluetoothDevice)).
+                isEqualTo(BluetoothProfile.STATE_CONNECTED);
+    }
+}
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 4fc190d..ec35b3d 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -16,6 +16,8 @@
 
 package com.android.shell;
 
+import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_TELEVISION;
 import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
 
 import static com.android.shell.BugreportPrefs.STATE_HIDE;
@@ -235,6 +237,7 @@
     private static final Bundle sNotificationBundle = new Bundle();
 
     private boolean mIsWatch;
+    private boolean mIsTv;
 
     private int mLastProgressPercent;
 
@@ -255,6 +258,9 @@
         final Configuration conf = mContext.getResources().getConfiguration();
         mIsWatch = (conf.uiMode & Configuration.UI_MODE_TYPE_MASK) ==
                 Configuration.UI_MODE_TYPE_WATCH;
+        PackageManager packageManager = getPackageManager();
+        mIsTv = packageManager.hasSystemFeature(FEATURE_LEANBACK)
+                || packageManager.hasSystemFeature(FEATURE_TELEVISION);
         NotificationManager nm = NotificationManager.from(mContext);
         nm.createNotificationChannel(
                 new NotificationChannel(NOTIFICATION_CHANNEL_ID,
@@ -500,8 +506,8 @@
                 .setProgress(info.max, info.progress, false)
                 .setOngoing(true);
 
-        // Wear bugreport doesn't need the bug info dialog, screenshot and cancel action.
-        if (!mIsWatch) {
+        // Wear and ATV bugreport doesn't need the bug info dialog, screenshot and cancel action.
+        if (!(mIsWatch || mIsTv)) {
             final Action cancelAction = new Action.Builder(null, mContext.getString(
                     com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
             final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 2cbb78a..3744105 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -356,10 +356,11 @@
     if (supplementalIconId != 0) {
       Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId);
       supplementalIcon.mutate().setTint(color);
-      listItem.setSupplementalIcon(supplementalIcon, true,
-          supplementalIconOnClickListener);
+      listItem.setSupplementalIcon(supplementalIcon, true);
+      listItem.setSupplementalIconListener(supplementalIconOnClickListener);
     } else {
       listItem.setSupplementalEmptyIcon(true);
+      listItem.setSupplementalIconListener(null);
     }
 
     mVolumeLineItems.add(listItem);
diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS
index 9c70a5e..7009282 100644
--- a/proto/src/metrics_constants/OWNERS
+++ b/proto/src/metrics_constants/OWNERS
@@ -1,3 +1,4 @@
+cwren@android.com
 yanglu@google.com
 yaochen@google.com
 yro@google.com
diff --git a/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java
new file mode 100644
index 0000000..1ae598e
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/encryption/chunk/ChunkHash.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 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 com.android.server.backup.encryption.chunk;
+
+import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+import java.util.Base64;
+
+/**
+ * Represents the SHA-256 hash of the plaintext of a chunk, which is frequently used as a key.
+ *
+ * <p>This class is {@link Comparable} and implements {@link #equals(Object)} and {@link
+ * #hashCode()}.
+ */
+public class ChunkHash implements Comparable<ChunkHash> {
+    /** The length of the hash in bytes. The hash is a SHA-256, so this is 256 bits. */
+    public static final int HASH_LENGTH_BYTES = 256 / 8;
+
+    private static final int UNSIGNED_MASK = 0xFF;
+
+    private final byte[] mHash;
+
+    /** Constructs a new instance which wraps the given SHA-256 hash bytes. */
+    public ChunkHash(byte[] hash) {
+        Preconditions.checkArgument(hash.length == HASH_LENGTH_BYTES, "Hash must have 256 bits");
+        mHash = hash;
+    }
+
+    public byte[] getHash() {
+        return mHash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof ChunkHash)) {
+            return false;
+        }
+
+        ChunkHash chunkHash = (ChunkHash) o;
+        return Arrays.equals(mHash, chunkHash.mHash);
+    }
+
+    @Override
+    public int hashCode() {
+        return Arrays.hashCode(mHash);
+    }
+
+    @Override
+    public int compareTo(ChunkHash other) {
+        return lexicographicalCompareUnsignedBytes(getHash(), other.getHash());
+    }
+
+    @Override
+    public String toString() {
+        return Base64.getEncoder().encodeToString(mHash);
+    }
+
+    private static int lexicographicalCompareUnsignedBytes(byte[] left, byte[] right) {
+        int minLength = Math.min(left.length, right.length);
+        for (int i = 0; i < minLength; i++) {
+            int result = toInt(left[i]) - toInt(right[i]);
+            if (result != 0) {
+                return result;
+            }
+        }
+        return left.length - right.length;
+    }
+
+    private static int toInt(byte value) {
+        return value & UNSIGNED_MASK;
+    }
+}
diff --git a/services/core/java/com/android/server/HardwarePropertiesManagerService.java b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
index 4016d29..e21a3d7 100644
--- a/services/core/java/com/android/server/HardwarePropertiesManagerService.java
+++ b/services/core/java/com/android/server/HardwarePropertiesManagerService.java
@@ -26,7 +26,6 @@
 import static android.os.HardwarePropertiesManager.TEMPERATURE_THROTTLING_BELOW_VR_MIN;
 
 import android.Manifest;
-import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
@@ -34,8 +33,8 @@
 import android.os.Binder;
 import android.os.CpuUsageInfo;
 import android.os.IHardwarePropertiesManager;
-import android.os.Process;
 import android.os.UserHandle;
+
 import com.android.internal.util.DumpUtils;
 import com.android.server.vr.VrManagerInternal;
 
@@ -166,11 +165,11 @@
         final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
         final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
         if (!dpm.isDeviceOwnerApp(callingPackage)
-                && !vrService.isCurrentVrListener(callingPackage, userId)
                 && mContext.checkCallingOrSelfPermission(Manifest.permission.DEVICE_POWER)
-                        != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("The caller is not a device owner, bound VrListenerService"
-                + ", or holding the DEVICE_POWER permission.");
+                        != PackageManager.PERMISSION_GRANTED
+                && (vrService == null || !vrService.isCurrentVrListener(callingPackage, userId))) {
+            throw new SecurityException("The caller is neither a device owner"
+                + ", nor holding the DEVICE_POWER permission, nor the current VrListener.");
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2ee598f..c721901 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2382,7 +2382,7 @@
                 }
             }
             int logSampleRate = Settings.Global.getInt(mContext.getContentResolver(),
-                    Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, -1);
+                    Settings.Global.HIDDEN_API_ACCESS_LOG_SAMPLING_RATE, 0x200);
             if (logSampleRate < 0 || logSampleRate > 0x10000) {
                 logSampleRate = -1;
             }
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 347a357..cd4d6a3 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -33,7 +33,7 @@
     private boolean mConsuming = true;
 
     public BaseErrorDialog(Context context) {
-        super(context, com.android.internal.R.style.Theme_Dialog_AppError);
+        super(context, com.android.internal.R.style.Theme_DeviceDefault_Dialog_AppError);
         context.assertRuntimeOverlayThemable();
 
         getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 1b688a6..76c191d 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -26,8 +26,8 @@
 import android.util.Slog;
 import android.util.Spline;
 
-import com.android.internal.util.Preconditions;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
 import com.android.server.display.utils.Plog;
 
 import java.io.PrintWriter;
@@ -77,8 +77,8 @@
                 Slog.w(TAG, "Screen brightness mapping does not cover whole range of available " +
                         "backlight values, autobrightness functionality may be impaired.");
             }
-            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder();
-            builder.setCurve(luxLevels, brightnessLevelsNits);
+            BrightnessConfiguration.Builder builder = new BrightnessConfiguration.Builder(
+                    luxLevels, brightnessLevelsNits);
             return new PhysicalMappingStrategy(builder.build(), nitsRange, backlightRange,
                     autoBrightnessAdjustmentMaxGamma);
         } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 340ae0a..7751f5f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -694,7 +694,8 @@
 
             for (int userId : userIds) {
                 if (enabled) {
-                    if (isPackageOrComponentAllowed(component.toString(), userId)) {
+                    if (isPackageOrComponentAllowed(component.toString(), userId)
+                            || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
                         registerServiceLocked(component, userId);
                     } else {
                         Slog.d(TAG, component + " no longer has permission to be bound");
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index ccc092d..0176dd4 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -228,6 +228,9 @@
     //       Encourages logging of any available arguments, and all call sites
     //       are necessarily logged identically.
     //
+    // NOTE: Log first because passed objects may or may not be thread-safe and
+    // once passed on to the callback they may be modified by another thread.
+    //
     // TODO: Find an lighter weight approach.
     private class LoggingCallbackWrapper extends Callback {
         private static final String PREFIX = "INVOKE ";
@@ -243,63 +246,63 @@
 
         @Override
         public void onPreDhcpAction() {
-            mCallback.onPreDhcpAction();
             log("onPreDhcpAction()");
+            mCallback.onPreDhcpAction();
         }
         @Override
         public void onPostDhcpAction() {
-            mCallback.onPostDhcpAction();
             log("onPostDhcpAction()");
+            mCallback.onPostDhcpAction();
         }
         @Override
         public void onNewDhcpResults(DhcpResults dhcpResults) {
-            mCallback.onNewDhcpResults(dhcpResults);
             log("onNewDhcpResults({" + dhcpResults + "})");
+            mCallback.onNewDhcpResults(dhcpResults);
         }
         @Override
         public void onProvisioningSuccess(LinkProperties newLp) {
-            mCallback.onProvisioningSuccess(newLp);
             log("onProvisioningSuccess({" + newLp + "})");
+            mCallback.onProvisioningSuccess(newLp);
         }
         @Override
         public void onProvisioningFailure(LinkProperties newLp) {
-            mCallback.onProvisioningFailure(newLp);
             log("onProvisioningFailure({" + newLp + "})");
+            mCallback.onProvisioningFailure(newLp);
         }
         @Override
         public void onLinkPropertiesChange(LinkProperties newLp) {
-            mCallback.onLinkPropertiesChange(newLp);
             log("onLinkPropertiesChange({" + newLp + "})");
+            mCallback.onLinkPropertiesChange(newLp);
         }
         @Override
         public void onReachabilityLost(String logMsg) {
-            mCallback.onReachabilityLost(logMsg);
             log("onReachabilityLost(" + logMsg + ")");
+            mCallback.onReachabilityLost(logMsg);
         }
         @Override
         public void onQuit() {
-            mCallback.onQuit();
             log("onQuit()");
+            mCallback.onQuit();
         }
         @Override
         public void installPacketFilter(byte[] filter) {
-            mCallback.installPacketFilter(filter);
             log("installPacketFilter(byte[" + filter.length + "])");
+            mCallback.installPacketFilter(filter);
         }
         @Override
         public void startReadPacketFilter() {
-            mCallback.startReadPacketFilter();
             log("startReadPacketFilter()");
+            mCallback.startReadPacketFilter();
         }
         @Override
         public void setFallbackMulticastFilter(boolean enabled) {
-            mCallback.setFallbackMulticastFilter(enabled);
             log("setFallbackMulticastFilter(" + enabled + ")");
+            mCallback.setFallbackMulticastFilter(enabled);
         }
         @Override
         public void setNeighborDiscoveryOffload(boolean enable) {
-            mCallback.setNeighborDiscoveryOffload(enable);
             log("setNeighborDiscoveryOffload(" + enable + ")");
+            mCallback.setNeighborDiscoveryOffload(enable);
         }
     }
 
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 2691701..8b59771 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -75,6 +75,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
     platform-robolectric-android-all-stubs \
     android-support-test \
+    guava \
     mockito-robolectric-prebuilt \
     platform-test-annotations \
     truth-prebuilt \
diff --git a/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
new file mode 100644
index 0000000..3b6e038
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/encryption/chunk/ChunkHashTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 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 com.android.server.backup.encryption.chunk;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+import com.google.common.primitives.Bytes;
+import java.util.Arrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class ChunkHashTest {
+    private static final int HASH_LENGTH_BYTES = 256 / 8;
+    private static final byte[] TEST_HASH_1 = Arrays.copyOf(new byte[] {1}, HASH_LENGTH_BYTES);
+    private static final byte[] TEST_HASH_2 = Arrays.copyOf(new byte[] {2}, HASH_LENGTH_BYTES);
+
+    @Test
+    public void testGetHash_returnsHash() {
+        ChunkHash chunkHash = new ChunkHash(TEST_HASH_1);
+
+        byte[] hash = chunkHash.getHash();
+
+        assertThat(hash).asList().containsExactlyElementsIn(Bytes.asList(TEST_HASH_1)).inOrder();
+    }
+
+    @Test
+    public void testEquals() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        assertThat(chunkHash1).isEqualTo(equalChunkHash1);
+        assertThat(chunkHash1).isNotEqualTo(chunkHash2);
+    }
+
+    @Test
+    public void testHashCode() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int hash1 = chunkHash1.hashCode();
+        int equalHash1 = equalChunkHash1.hashCode();
+        int hash2 = chunkHash2.hashCode();
+
+        assertThat(hash1).isEqualTo(equalHash1);
+        assertThat(hash1).isNotEqualTo(hash2);
+    }
+
+    @Test
+    public void testCompareTo_whenEqual_returnsZero() {
+        ChunkHash chunkHash = new ChunkHash(TEST_HASH_1);
+        ChunkHash equalChunkHash = new ChunkHash(TEST_HASH_1);
+
+        int result = chunkHash.compareTo(equalChunkHash);
+
+        assertThat(result).isEqualTo(0);
+    }
+
+    @Test
+    public void testCompareTo_whenArgumentGreater_returnsNegative() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int result = chunkHash1.compareTo(chunkHash2);
+
+        assertThat(result).isLessThan(0);
+    }
+
+    @Test
+    public void testCompareTo_whenArgumentSmaller_returnsPositive() {
+        ChunkHash chunkHash1 = new ChunkHash(TEST_HASH_1);
+        ChunkHash chunkHash2 = new ChunkHash(TEST_HASH_2);
+
+        int result = chunkHash2.compareTo(chunkHash1);
+
+        assertThat(result).isGreaterThan(0);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index e6ca03b..48dda01 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -152,8 +152,7 @@
         final float[] lux = { 0f, 1f };
         final float[] nits = { 0, PowerManager.BRIGHTNESS_ON };
 
-        BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
         assertNotEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
@@ -214,8 +213,7 @@
                 DISPLAY_RANGE_NITS[DISPLAY_RANGE_NITS.length - 1]
         };
 
-        BrightnessConfiguration config = new BrightnessConfiguration.Builder()
-                .setCurve(lux, nits)
+        BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
                 .build();
         strategy.setBrightnessConfiguration(config);
         assertEquals(1.0f, strategy.getBrightness(1f), 0.01 /*tolerance*/);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 1d9e605..8ebfec4 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1589,12 +1589,14 @@
     }
 
     /**
-     * @return true if a valid subId else false
-     * @hide
+     * Checks if the supplied subscription ID is valid.
+     * Note: a valid subscription ID does not necessarily correspond to an active subscription.
+     *
+     * @param subscriptionId The subscription ID.
+     * @return true if the supplied subscriptionId is valid; false otherwise.
      */
-    @UnsupportedAppUsage
-    public static boolean isValidSubscriptionId(int subId) {
-        return subId > INVALID_SUBSCRIPTION_ID ;
+    public static boolean isValidSubscriptionId(int subscriptionId) {
+        return subscriptionId > INVALID_SUBSCRIPTION_ID;
     }
 
     /**
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index 29bf74c..e50c70d 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -1,18 +1,24 @@
 #!/bin/bash
-LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
+LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
 
-if git branch -vv | grep "^*" | grep "\[aosp/master" > /dev/null; then
+if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; then
     # Change appears to be in AOSP
     exit 0
 else
     # Change appears to be non-AOSP; search for files
-    git show --name-only --pretty=format: $1 | grep $2 | while read file; do
-        echo
+    count=0
+    while read -r file ; do
+        if (( count == 0 )); then
+            echo
+        fi
         echo -e "\033[0;31mThe source of truth for '$file' is in AOSP.\033[0m"
+        (( count++ ))
+    done < <(git show --name-only --pretty=format: $1 | grep -- "$2")
+    if (( count != 0 )); then
         echo
-        echo "If your change contains no confidential details, please upload and merge"
-        echo "this change at https://android-review.googlesource.com/."
+        echo "If your change contains no confidential details (such as security fixes), please"
+        echo "upload and merge this change at https://android-review.googlesource.com/."
         echo
         exit 77
-    done
+    fi
 fi