Merge "Move appName inside Downloadrequest."
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk
index f932388..536cbef 100644
--- a/cmds/uiautomator/library/Android.mk
+++ b/cmds/uiautomator/library/Android.mk
@@ -64,10 +64,9 @@
 LOCAL_MODULE := android_uiautomator
 LOCAL_JAVA_LIBRARIES := $(uiautomator.core_java_libraries)
 LOCAL_SOURCE_FILES_ALL_GENERATED := true
-include $(BUILD_STATIC_JAVA_LIBRARY)
 # Make sure to run droiddoc first to generate the stub source files.
-$(full_classes_compiled_jar) : $(uiautomator_stubs_stamp)
-$(built_dex_intermediate) : $(uiautomator_stubs_stamp)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(uiautomator_stubs_stamp)
+include $(BUILD_STATIC_JAVA_LIBRARY)
 
 ###############################################
 # API check
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 2d25659..c31a9b2 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -767,6 +767,28 @@
     }
 
     /**
+     * Force SCO audio to be opened regardless any other restrictions
+     *
+     * @param forced Whether or not SCO audio connection should be forced:
+     *                 True to force SCO audio
+     *                 False to use SCO audio in normal manner
+     * @hide
+     */
+    public void setForceScoAudio(boolean forced) {
+        if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
+        if (mService != null && isEnabled()) {
+            try {
+                mService.setForceScoAudio(forced);
+            } catch (RemoteException e) {
+              Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
+    /**
      * Check if Bluetooth SCO audio is connected.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index 6ad442b..6bd0d7f 100755
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -52,6 +52,7 @@
     boolean disconnectAudio();
     void setAudioRouteAllowed(boolean allowed);
     boolean getAudioRouteAllowed();
+    void setForceScoAudio(boolean forced);
     boolean startScoUsingVirtualVoiceCall(in BluetoothDevice device);
     boolean stopScoUsingVirtualVoiceCall(in BluetoothDevice device);
     void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2c1796370..feb9cfe 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7498,6 +7498,15 @@
         */
        public static final String TETHER_DUN_APN = "tether_dun_apn";
 
+        /**
+         * Used to disable trying to talk to any available tethering offload HAL.
+         *
+         * Integer values are interpreted as boolean, and the absence of an explicit setting
+         * is interpreted as |false|.
+         * @hide
+         */
+        public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
+
        /**
         * List of carrier apps which are whitelisted to prompt the user for install when
         * a sim card with matching uicc carrier privilege rules is inserted.
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2b5c0d6..07f1b45 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -606,7 +606,6 @@
 {
     JavaVMInitArgs initArgs;
     char propBuf[PROPERTY_VALUE_MAX];
-    char stackTraceDirBuf[sizeof("-Xstacktracedir:")-1 + PROPERTY_VALUE_MAX];
     char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];
     char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
     char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
@@ -687,7 +686,10 @@
     // If dalvik.vm.stack-trace-dir is set, it enables the "new" stack trace
     // dump scheme and a new file is created for each stack dump. If it isn't set,
     // the old scheme is enabled.
-    if (!parseRuntimeOption("dalvik.vm.stack-trace-dir", stackTraceDirBuf, "-Xstacktracedir:")) {
+    property_get("dalvik.vm.stack-trace-dir", propBuf, "");
+    if (strlen(propBuf) > 0) {
+        addOption("-Xusetombstonedtraces");
+    } else {
         parseRuntimeOption("dalvik.vm.stack-trace-file", stackTraceFileBuf, "-Xstacktracefile:");
     }
 
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 68a08519..821d0e5 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -1035,7 +1035,7 @@
         return;
     }
 
-    dump_backtrace_to_file_timeout(pid, fd, timeoutSecs);
+    dump_backtrace_to_file_timeout(pid, kDebuggerdNativeBacktrace, timeoutSecs, fd);
 
     close(fd);
 }
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
index 14b032e..c66a10c 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk
@@ -18,7 +18,7 @@
 ## The application with a minimal main dex
 include $(CLEAR_VARS)
 
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex android-support-multidex-instrumentation android-support-test
 LOCAL_MODULE_TAGS := tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
@@ -35,16 +35,11 @@
     $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list
 
 LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex
-LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.preprocessor=true\
-    -D jack.preprocessor.file=$(LOCAL_PATH)/test.jpp -D jack.dex.output.multidex.legacy=true
 
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
+LOCAL_MIN_SDK_VERSION := 8
 
-ifdef LOCAL_JACK_ENABLED
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
-endif
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex \
+     -D jack.dex.output.multidex.legacy=true
 
 include $(BUILD_PACKAGE)
 
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml
index 7fff711..98d8f27 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/AndroidManifest.xml
@@ -22,7 +22,15 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation android:name="com.android.test.runner.MultiDexTestRunner"
+                     android:targetPackage="com.android.multidexlegacyandexception"
+                     android:label="Test for MultiDexLegacyAndException" />
+
+    <instrumentation android:name="com.android.multidexlegacyandexception.tests.MultiDexAndroidJUnitRunner"
+                     android:targetPackage="com.android.multidexlegacyandexception"
+                     android:label="Test for MultiDexLegacyAndException" />
+
+    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.android.multidexlegacyandexception"
                      android:label="Test for MultiDexLegacyAndException" />
 </manifest>
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/Test.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/ActivityTest.java
similarity index 62%
rename from core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/Test.java
rename to core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/ActivityTest.java
index 8d065a4..d6ac3e5 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/Test.java
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/ActivityTest.java
@@ -13,16 +13,31 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.android.multidexlegacyandexception;
+package com.android.multidexlegacyandexception.tests;
+
+import com.android.multidexlegacyandexception.CaughtOnlyByIntermediateException;
+import com.android.multidexlegacyandexception.CaughtOnlyException;
+import com.android.multidexlegacyandexception.ExceptionInMainDex;
+import com.android.multidexlegacyandexception.ExceptionInMainDex2;
+import com.android.multidexlegacyandexception.ExceptionInSecondaryDex;
+import com.android.multidexlegacyandexception.ExceptionInSecondaryDex2;
+import com.android.multidexlegacyandexception.ExceptionInSecondaryDexWithSuperInMain;
+import com.android.multidexlegacyandexception.IntermediateClass;
+import com.android.multidexlegacyandexception.MainActivity;
+import com.android.multidexlegacyandexception.MiniIntermediateClass;
+import com.android.multidexlegacyandexception.SuperExceptionInMainDex;
+import com.android.multidexlegacyandexception.SuperExceptionInSecondaryDex;
+import com.android.multidexlegacyandexception.TestApplication;
 
 /**
- * Run the tests with: <code>adb shell am instrument -w
- com.android.multidexlegacyandexception/android.test.InstrumentationTestRunner
+ * Run the tests with:
+ * <code>
+adb shell am instrument -w com.android.multidexlegacyandexception/com.android.multidexlegacyandexception.tests.MultiDexAndroidJUnitRunner
 </code>
  */
 @SuppressWarnings("deprecation")
-public class Test extends android.test.ActivityInstrumentationTestCase2<MainActivity> {
-    public Test() {
+public class ActivityTest extends android.test.ActivityInstrumentationTestCase2<MainActivity> {
+    public ActivityTest() {
         super(MainActivity.class);
     }
 
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java
new file mode 100644
index 0000000..758ac1d
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/MultiDexAndroidJUnitRunner.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You 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.multidexlegacyandexception.tests;
+
+import android.os.Bundle;
+import android.support.multidex.MultiDex;
+import android.support.test.runner.AndroidJUnitRunner;
+
+public class MultiDexAndroidJUnitRunner extends AndroidJUnitRunner {
+
+  @Override
+  public void onCreate(Bundle arguments) {
+      MultiDex.installInstrumentation(getContext(), getTargetContext());
+      super.onCreate(arguments);
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityIntermediate.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityIntermediate.java
new file mode 100644
index 0000000..3a8acc6
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityIntermediate.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You 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.multidexlegacyandexception.tests;
+
+public class NoActivityIntermediate {
+
+  public static int get() {
+    return NoActivitySubTest.get();
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityJUnit3Test.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityJUnit3Test.java
new file mode 100644
index 0000000..31cb939
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityJUnit3Test.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 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.multidexlegacyandexception.tests;
+
+import android.test.InstrumentationTestCase;
+import com.android.multidexlegacyandexception.CaughtOnlyByIntermediateException;
+import com.android.multidexlegacyandexception.CaughtOnlyException;
+import com.android.multidexlegacyandexception.ExceptionInMainDex;
+import com.android.multidexlegacyandexception.ExceptionInMainDex2;
+import com.android.multidexlegacyandexception.ExceptionInSecondaryDex;
+import com.android.multidexlegacyandexception.ExceptionInSecondaryDex2;
+import com.android.multidexlegacyandexception.ExceptionInSecondaryDexWithSuperInMain;
+import com.android.multidexlegacyandexception.IntermediateClass;
+import com.android.multidexlegacyandexception.MiniIntermediateClass;
+import com.android.multidexlegacyandexception.SuperExceptionInMainDex;
+import com.android.multidexlegacyandexception.SuperExceptionInSecondaryDex;
+import com.android.multidexlegacyandexception.TestApplication;
+import junit.framework.Assert;
+
+/**
+ * Run the tests with: <code>
+adb shell am instrument -w com.android.multidexlegacyandexception/com.android.test.runner.MultiDexTestRunner
+</code>
+ * or <code>
+adb shell am instrument -w com.android.multidexlegacyandexception/com.android.multidexlegacyandexception.tests.MultiDexAndroidJUnitRunner
+</code>
+ */
+@SuppressWarnings("deprecation")
+public class NoActivityJUnit3Test extends InstrumentationTestCase {
+
+    @org.junit.Test
+    public void testExceptionInMainDex() {
+        Assert.assertEquals(10, TestApplication.get(true));
+    }
+
+    @org.junit.Test
+    public void testExceptionInIntermediate() {
+        Assert.assertEquals(11, IntermediateClass.get3(true));
+        Assert.assertEquals(11, MiniIntermediateClass.get3(true));
+        Assert.assertEquals(11, IntermediateClass.get4(true));
+        Assert.assertEquals(1, IntermediateClass.get5(null));
+        Assert.assertEquals(10, IntermediateClass.get5(new ExceptionInMainDex()));
+        Assert.assertEquals(11, IntermediateClass.get5(new ExceptionInSecondaryDex()));
+        Assert.assertEquals(12, IntermediateClass.get5(new ExceptionInMainDex2()));
+        Assert.assertEquals(13, IntermediateClass.get5(new ExceptionInSecondaryDex2()));
+        Assert.assertEquals(14, IntermediateClass.get5(new OutOfMemoryError()));
+        Assert.assertEquals(17, IntermediateClass.get5(new CaughtOnlyException()));
+        Assert.assertEquals(39, IntermediateClass.get5(new ExceptionInSecondaryDexWithSuperInMain()));
+        Assert.assertEquals(23, IntermediateClass.get5(new SuperExceptionInSecondaryDex()));
+        Assert.assertEquals(23, IntermediateClass.get5(new SuperExceptionInMainDex()));
+        Assert.assertEquals(23, IntermediateClass.get5(new CaughtOnlyByIntermediateException()));
+        Assert.assertEquals(37, IntermediateClass.get5(new ArrayIndexOutOfBoundsException()));
+    }
+
+    @org.junit.Test
+    public void testMultidexedTest() {
+      Assert.assertEquals(7, NoActivityIntermediate.get());
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityJUnit4Test.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityJUnit4Test.java
new file mode 100644
index 0000000..94a5b7f
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivityJUnit4Test.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You 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.multidexlegacyandexception.tests;
+
+import android.support.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+
+/**
+ * Run the tests with: <code>
+adb shell am instrument -w com.android.multidexlegacyandexception/com.android.test.runner.MultiDexTestRunner
+</code>
+ * or <code>
+adb shell am instrument -w com.android.multidexlegacyandexception/com.android.multidexlegacyandexception.tests.MultiDexAndroidJUnitRunner
+</code>
+ */
+@RunWith(AndroidJUnit4.class)
+public class NoActivityJUnit4Test extends NoActivityJUnit3Test {
+
+  @org.junit.Test
+  public void multidexedTestJUnit4() {
+    super.testMultidexedTest();
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivitySubTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivitySubTest.java
new file mode 100644
index 0000000..4885c2e
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/src/com/android/multidexlegacyandexception/tests/NoActivitySubTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You 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.multidexlegacyandexception.tests;
+
+public class NoActivitySubTest {
+
+  public static int get() {
+    return 7;
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp
deleted file mode 100644
index 0d027ed..0000000
--- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/test.jpp
+++ /dev/null
@@ -1,3 +0,0 @@
-test:
-  @@com.android.jack.annotations.ForceInMainDex
-  class com.android.multidexlegacyandexception.Test
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
index 208eceb..2784193 100644
--- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk
@@ -44,6 +44,8 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
+LOCAL_MIN_SDK_VERSION := 8
+
 include $(BUILD_PACKAGE)
 
 ifndef LOCAL_JACK_ENABLED
@@ -85,6 +87,8 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp
 endif
 
+LOCAL_MIN_SDK_VERSION := 8
+
 include $(BUILD_PACKAGE)
 
 ifndef LOCAL_JACK_ENABLED
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.mk
new file mode 100644
index 0000000..69ec5ce
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+
+## The application with a minimal main dex
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex-instrumentation
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 8
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyTestAppTests
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_JAVACFLAGS := -nowarn
+
+LOCAL_MIN_SDK_VERSION := 8
+
+LOCAL_INSTRUMENTATION_FOR := MultiDexLegacyTestApp
+
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml
new file mode 100644
index 0000000..35369c7
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.multidexlegacytestapp.test"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="8" />
+    <instrumentation
+        android:name="com.android.test.runner.MultiDexTestRunner"
+        android:targetPackage="com.android.multidexlegacytestapp" />
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.multidexlegacytestapp" />
+
+    <application
+        android:label="multidexlegacytestapp.test" >
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/InstrumentationTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/InstrumentationTest.java
new file mode 100644
index 0000000..a0288f2
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/InstrumentationTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.multidexlegacytestapp.test;
+
+import android.test.InstrumentationTestCase;
+import com.android.multidexlegacytestapp.manymethods.Big001;
+import com.android.multidexlegacytestapp.manymethods.Big079;
+import junit.framework.Assert;
+
+/**
+ * Run the tests with: <code>
+adb shell am instrument -w com.android.multidexlegacytestapp.test/com.android.test.runner.MultiDexTestRunner
+</code>
+ */
+public class InstrumentationTest extends InstrumentationTestCase {
+
+    public void testExceptionInMainDex() {
+      Assert.assertEquals(0, new Big001().get0());
+      Assert.assertEquals(100, new Big079().get100());
+    }
+
+    public void testMultidexedTest() {
+      Assert.assertEquals(7, Intermediate.get());
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/Intermediate.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/Intermediate.java
new file mode 100644
index 0000000..9a79c7a
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/Intermediate.java
@@ -0,0 +1,9 @@
+package com.android.multidexlegacytestapp.test;
+
+public class Intermediate {
+
+  public static int get() {
+    return SubTest.get();
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/SubTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/SubTest.java
new file mode 100644
index 0000000..e28584b
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests/src/com/android/multidexlegacytestapp/test/SubTest.java
@@ -0,0 +1,11 @@
+package com.android.multidexlegacytestapp.test;
+
+import com.android.multidexlegacytestapp.manymethods.Big080;
+
+public class SubTest {
+
+  public static int get() {
+    return new Big080().get7();
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.mk
new file mode 100644
index 0000000..f2bd353
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/Android.mk
@@ -0,0 +1,63 @@
+# Copyright (C) 2014 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+
+## The tests with only one dex
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex-instrumentation android-support-test
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyTestAppTests2
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_JAVACFLAGS := -nowarn
+
+LOCAL_MIN_SDK_VERSION := 8
+
+LOCAL_INSTRUMENTATION_FOR := MultiDexLegacyTestApp
+
+include $(BUILD_PACKAGE)
+
+
+## The tests with a minimal main dex
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-multidex-instrumentation android-support-test
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 8
+
+LOCAL_PACKAGE_NAME := MultiDexLegacyTestAppTests2-multidex
+
+LOCAL_DEX_PREOPT := false
+
+LOCAL_JAVACFLAGS := -nowarn
+
+LOCAL_MIN_SDK_VERSION := 8
+
+LOCAL_INSTRUMENTATION_FOR := MultiDexLegacyTestApp
+
+LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml
new file mode 100644
index 0000000..1cadfcd
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.multidexlegacytestapp.test2"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="8" />
+    <instrumentation
+        android:name="com.android.multidexlegacytestapp.test2.MultiDexAndroidJUnitRunner"
+        android:targetPackage="com.android.multidexlegacytestapp" />
+
+    <application
+        android:label="multidexlegacytestapp.test" >
+        <uses-library android:name="android.test.runner" />
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/InstrumentationTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/InstrumentationTest.java
new file mode 100644
index 0000000..4e6ec14
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/InstrumentationTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2014 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.multidexlegacytestapp.test2;
+
+import android.support.test.runner.AndroidJUnit4;
+import com.android.multidexlegacytestapp.manymethods.Big001;
+import com.android.multidexlegacytestapp.manymethods.Big079;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Run the tests with: <code>adb shell am instrument -w
+ com.android.multidexlegacytestapp.test2/com.android.multidexlegacytestapp.test2.MultiDexAndroidJUnitRunner
+</code>
+ */
+@RunWith(AndroidJUnit4.class)
+public class InstrumentationTest {
+
+    @Test
+    public void exceptionInMainDex() {
+      Assert.assertEquals(0, new Big001().get0());
+      Assert.assertEquals(100, new Big079().get100());
+    }
+
+    @Test
+    public void multidexedTest() {
+      Assert.assertEquals(7, Intermediate.get());
+    }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/Intermediate.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/Intermediate.java
new file mode 100644
index 0000000..3e5e81e
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/Intermediate.java
@@ -0,0 +1,9 @@
+package com.android.multidexlegacytestapp.test2;
+
+public class Intermediate {
+
+  public static int get() {
+    return SubTest.get();
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java
new file mode 100644
index 0000000..963f904
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/MultiDexAndroidJUnitRunner.java
@@ -0,0 +1,15 @@
+package com.android.multidexlegacytestapp.test2;
+
+import android.os.Bundle;
+import android.support.multidex.MultiDex;
+import android.support.test.runner.AndroidJUnitRunner;
+
+public class MultiDexAndroidJUnitRunner extends AndroidJUnitRunner {
+
+  @Override
+  public void onCreate(Bundle arguments) {
+      MultiDex.installInstrumentation(getContext(), getTargetContext());
+      super.onCreate(arguments);
+  }
+
+}
diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/SubTest.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/SubTest.java
new file mode 100644
index 0000000..acff80f
--- /dev/null
+++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestAppTests2/src/com/android/multidexlegacytestapp/test2/SubTest.java
@@ -0,0 +1,11 @@
+package com.android.multidexlegacytestapp.test2;
+
+import com.android.multidexlegacytestapp.manymethods.Big080;
+
+public class SubTest {
+
+  public static int get() {
+    return new Big080().get7();
+  }
+
+}
diff --git a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
index 2f0a411..2324593 100644
--- a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
+++ b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
@@ -4,31 +4,35 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context="com.android.captiveportallogin.CaptivePortalLoginActivity"
-    tools:ignore="MergeRootFrame">
+    tools:ignore="MergeRootFrame" >
+
     <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
 
-    <TextView
-        android:id="@+id/url_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="20sp"
-        android:singleLine="true" />
+      <FrameLayout
+          android:layout_width="match_parent"
+          android:layout_height="4dp" >
 
-    <ProgressBar
-        android:id="@+id/progress_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="?android:attr/progressBarStyleHorizontal" />
+        <!-- Eliminates ProgressBar padding by boxing it into a 4dp high container -->
+        <ProgressBar
+            android:id="@+id/progress_bar"
+            style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
+            android:indeterminate="false"
+            android:max="100"
+            android:progress="0"
+            android:layout_gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+      </FrameLayout>
 
-    <WebView
-        android:id="@+id/webview"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentBottom="false"
-        android:layout_alignParentRight="false" />
+      <WebView
+          android:id="@+id/webview"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:layout_alignParentBottom="false"
+          android:layout_alignParentRight="false" />
 
-</LinearLayout>
+    </LinearLayout>
 </FrameLayout>
diff --git a/packages/CaptivePortalLogin/res/values/styles.xml b/packages/CaptivePortalLogin/res/values/styles.xml
index 4a99638..f6c2339 100644
--- a/packages/CaptivePortalLogin/res/values/styles.xml
+++ b/packages/CaptivePortalLogin/res/values/styles.xml
@@ -4,7 +4,7 @@
         Base application theme, dependent on API level. This theme is replaced
         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
     -->
-    <style name="AppBaseTheme" parent="@android:style/Theme.Material.Settings">
+    <style name="AppBaseTheme" parent="@android:style/Theme.DeviceDefault.Settings">
         <!--
             Theme customizations available in newer API levels can go in
             res/values-vXX/styles.xml, while customizations related to
@@ -15,8 +15,5 @@
     <!-- Application theme. -->
     <style name="AppTheme" parent="AppBaseTheme">
         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
-        <!-- Setting's theme's accent color makes ProgressBar useless, reset back. -->
-        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
     </style>
-
 </resources>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 34465e9..57e155a 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -37,6 +37,7 @@
 import android.util.TypedValue;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.View;
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
@@ -97,8 +98,6 @@
         // setContentView initializes the WebView logic which in turn reads the system properties.
         setContentView(R.layout.activity_captive_portal_login);
 
-        getActionBar().setDisplayShowHomeEnabled(false);
-
         // Exit app if Network disappears.
         final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
         if (networkCapabilities == null) {
@@ -117,9 +116,14 @@
         }
         mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
 
-        final WebView myWebView = (WebView) findViewById(R.id.webview);
-        myWebView.clearCache(true);
-        WebSettings webSettings = myWebView.getSettings();
+        getActionBar().setDisplayShowHomeEnabled(false);
+        getActionBar().setElevation(0); // remove shadow
+        getActionBar().setTitle(getHeaderTitle());
+        getActionBar().setSubtitle("");
+
+        final WebView webview = getWebview();
+        webview.clearCache(true);
+        WebSettings webSettings = webview.getSettings();
         webSettings.setJavaScriptEnabled(true);
         webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
         webSettings.setUseWideViewPort(true);
@@ -128,11 +132,11 @@
         webSettings.setBuiltInZoomControls(true);
         webSettings.setDisplayZoomControls(false);
         mWebViewClient = new MyWebViewClient();
-        myWebView.setWebViewClient(mWebViewClient);
-        myWebView.setWebChromeClient(new MyWebChromeClient());
+        webview.setWebViewClient(mWebViewClient);
+        webview.setWebChromeClient(new MyWebChromeClient());
         // Start initial page load so WebView finishes loading proxy settings.
         // Actual load of mUrl is initiated by MyWebViewClient.
-        myWebView.loadData("", "text/html", null);
+        webview.loadData("", "text/html", null);
     }
 
     // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
@@ -251,10 +255,14 @@
         if (url == null) {
             url = mCm.getCaptivePortalServerUrl();
         }
+        return makeURL(url);
+    }
+
+    private static URL makeURL(String url) {
         try {
             return new URL(url);
         } catch (MalformedURLException e) {
-            Log.e(TAG, "Invalid captive portal URL " + url);
+            Log.e(TAG, "Invalid URL " + url);
         }
         return null;
     }
@@ -331,15 +339,16 @@
             // For internally generated pages, leave URL bar listing prior URL as this is the URL
             // the page refers to.
             if (!url.startsWith(INTERNAL_ASSETS)) {
-                final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
-                myUrlBar.setText(url);
+                getActionBar().setSubtitle(getHeaderSubtitle(url));
             }
+            getProgressBar().setVisibility(View.VISIBLE);
             testForCaptivePortal();
         }
 
         @Override
         public void onPageFinished(WebView view, String url) {
             mPagesLoaded++;
+            getProgressBar().setVisibility(View.INVISIBLE);
             if (mPagesLoaded == 1) {
                 // Now that WebView has loaded at least one page we know it has read in the proxy
                 // settings.  Now prompt the WebView read the Network-specific proxy settings.
@@ -412,8 +421,31 @@
     private class MyWebChromeClient extends WebChromeClient {
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
-            final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
-            myProgressBar.setProgress(newProgress);
+            getProgressBar().setProgress(newProgress);
         }
     }
+
+    private ProgressBar getProgressBar() {
+        return (ProgressBar) findViewById(R.id.progress_bar);
+    }
+
+    private WebView getWebview() {
+        return (WebView) findViewById(R.id.webview);
+    }
+
+    private String getHeaderTitle() {
+        return getString(R.string.action_bar_label);
+    }
+
+    private String getHeaderSubtitle(String urlString) {
+        URL url = makeURL(urlString);
+        if (url == null) {
+            return urlString;
+        }
+        final String https = "https";
+        if (https.equals(url.getProtocol())) {
+            return https + "://" + url.getHost();
+        }
+        return url.getHost();
+    }
 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 4691e1a..abbdd54 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -1777,7 +1777,7 @@
         pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
                 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
                 pw.print(" isResizeable=" + isResizeable());
-                pw.print(" firstActiveTime=" + lastActiveTime);
+                pw.print(" firstActiveTime=" + firstActiveTime);
                 pw.print(" lastActiveTime=" + lastActiveTime);
                 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
     }
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 8088554..dffa670 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -199,6 +199,7 @@
         final Handler smHandler = mTetherMasterSM.getHandler();
         mOffloadController = new OffloadController(smHandler,
                 deps.getOffloadHardwareInterface(smHandler, mLog),
+                mContext.getContentResolver(),
                 mLog);
         mUpstreamNetworkMonitor = new UpstreamNetworkMonitor(
                 mContext, mTetherMasterSM, TetherMasterSM.EVENT_UPSTREAM_CALLBACK, mLog);
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 12899d8..c64e705 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -16,9 +16,13 @@
 
 package com.android.server.connectivity.tethering;
 
+import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+
+import android.content.ContentResolver;
 import android.net.LinkProperties;
-import android.os.Handler;
 import android.net.util.SharedLog;
+import android.os.Handler;
+import android.provider.Settings;
 
 /**
  * A class to encapsulate the business logic of programming the tethering
@@ -31,19 +35,22 @@
 
     private final Handler mHandler;
     private final OffloadHardwareInterface mHwInterface;
+    private final ContentResolver mContentResolver;
     private final SharedLog mLog;
     private boolean mConfigInitialized;
     private boolean mControlInitialized;
     private LinkProperties mUpstreamLinkProperties;
 
-    public OffloadController(Handler h, OffloadHardwareInterface hwi, SharedLog log) {
+    public OffloadController(Handler h, OffloadHardwareInterface hwi,
+            ContentResolver contentResolver, SharedLog log) {
         mHandler = h;
         mHwInterface = hwi;
+        mContentResolver = contentResolver;
         mLog = log.forSubComponent(TAG);
     }
 
     public void start() {
-        if (started()) return;
+        if (isOffloadDisabled() || started()) return;
 
         if (!mConfigInitialized) {
             mConfigInitialized = mHwInterface.initOffloadConfig();
@@ -91,6 +98,11 @@
 
     // TODO: public void addDownStream(...)
 
+    private boolean isOffloadDisabled() {
+        // Defaults to |false| if not present.
+        return (Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0) != 0);
+    }
+
     private boolean started() {
         return mConfigInitialized && mControlInitialized;
     }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 060dd73..4152070 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -31,7 +31,6 @@
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.SET_DEFAULT;
 import static android.net.NetworkStats.SET_FOREGROUND;
-import static android.net.NetworkStats.TAG_ALL;
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
@@ -58,14 +57,13 @@
 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static com.android.internal.util.Preconditions.checkArgument;
+
 import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
 
 import android.app.AlarmManager;
-import android.app.IAlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -1031,7 +1029,7 @@
         // snapshot and record current counters; read UID stats first to
         // avoid over counting dev stats.
         final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
-        final NetworkStats xtSnapshot = getNetworkStatsXtAndVt();
+        final NetworkStats xtSnapshot = getNetworkStatsXt();
         final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
 
 
@@ -1323,7 +1321,8 @@
 
     /**
      * Return snapshot of current UID statistics, including any
-     * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
+     * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations}
+     * values.
      */
     private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
         final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
@@ -1331,43 +1330,34 @@
         // fold tethering stats and operations into uid snapshot
         final NetworkStats tetherSnapshot = getNetworkStatsTethering();
         uidSnapshot.combineAllValues(tetherSnapshot);
+
+        final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
+                Context.TELEPHONY_SERVICE);
+
+        // fold video calling data usage stats into uid snapshot
+        final NetworkStats vtStats = telephonyManager.getVtDataUsage(true);
+        if (vtStats != null) {
+            uidSnapshot.combineAllValues(vtStats);
+        }
         uidSnapshot.combineAllValues(mUidOperations);
 
         return uidSnapshot;
     }
 
     /**
-     * Return snapshot of current XT plus VT statistics.
+     * Return snapshot of current XT statistics with video calling data usage statistics.
      */
-    private NetworkStats getNetworkStatsXtAndVt() throws RemoteException {
+    private NetworkStats getNetworkStatsXt() throws RemoteException {
         final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
 
-        TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
+        final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
                 Context.TELEPHONY_SERVICE);
 
-        long usage = tm.getVtDataUsage();
-
-        if (LOGV) Slog.d(TAG, "VT call data usage = " + usage);
-
-        final NetworkStats vtSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), 1);
-
-        final NetworkStats.Entry entry = new NetworkStats.Entry();
-        entry.iface = VT_INTERFACE;
-        entry.uid = -1;
-        entry.set = TAG_ALL;
-        entry.tag = TAG_NONE;
-
-        // Since modem only tell us the total usage instead of each usage for RX and TX,
-        // we need to split it up (though it might not quite accurate). At
-        // least we can make sure the data usage report to the user will still be accurate.
-        entry.rxBytes = usage / 2;
-        entry.rxPackets = 0;
-        entry.txBytes = usage - entry.rxBytes;
-        entry.txPackets = 0;
-        vtSnapshot.combineValues(entry);
-
-        // Merge VT int XT
-        xtSnapshot.combineAllValues(vtSnapshot);
+        // Merge video calling data usage into XT
+        final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false);
+        if (vtSnapshot != null) {
+            xtSnapshot.combineAllValues(vtSnapshot);
+        }
 
         return xtSnapshot;
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4c732d7..99b74a9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
 import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
 import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
@@ -15627,6 +15628,14 @@
                 callingUid == getPackageUid(mStorageManagerPackage, 0, callingUserId)) {
             return true;
         }
+
+        // Allow caller having MANAGE_PROFILE_AND_DEVICE_OWNERS permission to silently
+        // uninstall for device owner provisioning.
+        if (checkUidPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS, callingUid)
+                == PERMISSION_GRANTED) {
+            return true;
+        }
+
         return false;
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 5c718c7..e81c97e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -32,6 +32,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.NetworkStats;
 import android.net.Uri;
 import android.os.BatteryStats;
 import android.os.Binder;
@@ -39,11 +40,6 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -6433,20 +6429,21 @@
     /**
      * Get aggregated video call data usage since boot.
      * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
-     * @return total data usage in bytes
+     *
+     * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
+     * @return Snapshot of video call data usage
      * @hide
      */
-    public long getVtDataUsage() {
-
+    public NetworkStats getVtDataUsage(boolean perUidStats) {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.getVtDataUsage();
+                return service.getVtDataUsage(getSubId(), perUidStats);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "Error calling getVtDataUsage", e);
+            Log.e(TAG, "Error calling ITelephony#getVtDataUsage", e);
         }
-        return 0;
+        return null;
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index fb6782e..63e7abf 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -22,6 +22,7 @@
 import android.os.IBinder;
 import android.os.Messenger;
 import android.os.ResultReceiver;
+import android.net.NetworkStats;
 import android.net.Uri;
 import android.service.carrier.CarrierIdentifier;
 import android.telecom.PhoneAccount;
@@ -1268,10 +1269,12 @@
     /**
      * Get aggregated video call data usage since boot.
      * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
-     * @return total data usage in bytes
+     *
+     * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
+     * @return Snapshot of video call data usage
      * @hide
      */
-    long getVtDataUsage();
+    NetworkStats getVtDataUsage(int subId, boolean perUidStats);
 
     /**
      * Policy control of data connection. Usually used when data limit is passed.
diff --git a/tests/net/java/android/net/nsd/NsdManagerTest.java b/tests/net/java/android/net/nsd/NsdManagerTest.java
index 063cd5dc..adf6998 100644
--- a/tests/net/java/android/net/nsd/NsdManagerTest.java
+++ b/tests/net/java/android/net/nsd/NsdManagerTest.java
@@ -333,7 +333,7 @@
     public static class MockServiceHandler extends Handler {
         public Context mContext;
         public AsyncChannel chan;
-        public Message lastMessage;
+        public volatile Message lastMessage;
 
         MockServiceHandler(Looper looper, Context context) {
             super(looper);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4fdbfe7..0263c57 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -2411,8 +2411,7 @@
     }
 
     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
-    @SmallTest
-    public void testRequestBenchmark() throws Exception {
+    public void benchmarkRequestRegistrationAndCallbackDispatch() throws Exception {
         // TODO: turn this unit test into a real benchmarking test.
         // Benchmarks connecting and switching performance in the presence of a large number of
         // NetworkRequests.
@@ -2422,9 +2421,9 @@
         //    and NUM_REQUESTS onAvailable callbacks to fire.
         // See how long it took.
         final int NUM_REQUESTS = 90;
-        final int REGISTER_TIME_LIMIT_MS = 180;
-        final int CONNECT_TIME_LIMIT_MS = 50;
-        final int SWITCH_TIME_LIMIT_MS = 50;
+        final int REGISTER_TIME_LIMIT_MS = 200;
+        final int CONNECT_TIME_LIMIT_MS = 60;
+        final int SWITCH_TIME_LIMIT_MS = 60;
         final int UNREGISTER_TIME_LIMIT_MS = 20;
 
         final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index d5a0b86..241b828 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -31,6 +31,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.Intent;
@@ -52,11 +53,14 @@
 import android.os.RemoteException;
 import android.os.test.TestLooper;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.telephony.CarrierConfigManager;
+import android.test.mock.MockContentResolver;
 
 import com.android.internal.util.test.BroadcastInterceptingContext;
+import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.connectivity.tethering.OffloadHardwareInterface;
 import com.android.server.connectivity.tethering.TetheringDependencies;
 
@@ -96,6 +100,7 @@
 
     private Vector<Intent> mIntents;
     private BroadcastInterceptingContext mServiceContext;
+    private MockContentResolver mContentResolver;
     private BroadcastReceiver mBroadcastReceiver;
     private Tethering mTethering;
 
@@ -105,6 +110,12 @@
         }
 
         @Override
+        public ContentResolver getContentResolver() { return mContentResolver; }
+
+        @Override
+        public String getPackageName() { return "TetheringTest"; }
+
+        @Override
         public Resources getResources() { return mResources; }
 
         @Override
@@ -134,6 +145,8 @@
                 .thenReturn(new InterfaceConfiguration());
 
         mServiceContext = new MockContext(mContext);
+        mContentResolver = new MockContentResolver(mServiceContext);
+        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         mIntents = new Vector<>();
         mBroadcastReceiver = new BroadcastReceiver() {
             @Override
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
new file mode 100644
index 0000000..fb7971e
--- /dev/null
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity.tethering;
+
+import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.net.util.SharedLog;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+import com.android.internal.util.test.FakeSettingsProvider;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class OffloadControllerTest {
+
+    @Mock private OffloadHardwareInterface mHardware;
+    @Mock private Context mContext;
+    private MockContentResolver mContentResolver;
+
+    @Before public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mContentResolver = new MockContentResolver(mContext);
+        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(mContext.getPackageName()).thenReturn("OffloadControllerTest");
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+    }
+
+    private void setupFunctioningHardwareInterface() {
+        when(mHardware.initOffloadConfig()).thenReturn(true);
+        when(mHardware.initOffloadControl(any(OffloadHardwareInterface.ControlCallback.class)))
+                .thenReturn(true);
+    }
+
+    @Test
+    public void testNoSettingsValueAllowsStart() {
+        setupFunctioningHardwareInterface();
+        try {
+            Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
+            fail();
+        } catch (SettingNotFoundException expected) {}
+
+        final OffloadController offload =
+                new OffloadController(null, mHardware, mContentResolver, new SharedLog("test"));
+        offload.start();
+
+        final InOrder inOrder = inOrder(mHardware);
+        inOrder.verify(mHardware, times(1)).initOffloadConfig();
+        inOrder.verify(mHardware, times(1)).initOffloadControl(
+                any(OffloadHardwareInterface.ControlCallback.class));
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testSettingsAllowsStart() {
+        setupFunctioningHardwareInterface();
+        Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0);
+
+        final OffloadController offload =
+                new OffloadController(null, mHardware, mContentResolver, new SharedLog("test"));
+        offload.start();
+
+        final InOrder inOrder = inOrder(mHardware);
+        inOrder.verify(mHardware, times(1)).initOffloadConfig();
+        inOrder.verify(mHardware, times(1)).initOffloadControl(
+                any(OffloadHardwareInterface.ControlCallback.class));
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testSettingsDisablesStart() {
+        setupFunctioningHardwareInterface();
+        Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1);
+
+        final OffloadController offload =
+                new OffloadController(null, mHardware, mContentResolver, new SharedLog("test"));
+        offload.start();
+
+        final InOrder inOrder = inOrder(mHardware);
+        inOrder.verify(mHardware, never()).initOffloadConfig();
+        inOrder.verify(mHardware, never()).initOffloadControl(anyObject());
+        inOrder.verifyNoMoreInteractions();
+    }
+}