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();
+ }
+}