diff options
41 files changed, 808 insertions, 114 deletions
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk index f932388b0617..536cbef41feb 100644 --- a/cmds/uiautomator/library/Android.mk +++ b/cmds/uiautomator/library/Android.mk @@ -64,10 +64,9 @@ include $(CLEAR_VARS) 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 2d25659bd773..c31a9b20e286 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -767,6 +767,28 @@ public final class BluetoothHeadset implements BluetoothProfile { } /** + * 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 6ad442b6138d..6bd0d7fb43b0 100755 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl @@ -52,6 +52,7 @@ interface IBluetoothHeadset { 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 2c1796370558..feb9cfe9d21f 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7498,6 +7498,15 @@ public final class Settings { */ 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 2b5c0d6c735a..07f1b45fe01a 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -606,7 +606,6 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) { 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 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) // 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 68a085191067..821d0e515d09 100644 --- a/core/jni/android_os_Debug.cpp +++ b/core/jni/android_os_Debug.cpp @@ -1035,7 +1035,7 @@ static void android_os_Debug_dumpNativeBacktraceToFileTimeout(JNIEnv* env, jobje 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 14b032e37f4c..c66a10cc31f7 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk @@ -18,7 +18,7 @@ LOCAL_PATH:= $(call my-dir) ## 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 @@ mainDexList:= \ $(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 7fff71118604..98d8f27179fd 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 index 8d065a43ac61..d6ac3e57242b 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 000000000000..758ac1dcb4a0 --- /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 000000000000..3a8acc6b59be --- /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 000000000000..31cb939813d3 --- /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 000000000000..94a5b7fa66f2 --- /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 000000000000..4885c2ef5865 --- /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 0d027ed236fb..000000000000 --- 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 208eceb6273d..278419315779 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk @@ -44,6 +44,8 @@ ifdef LOCAL_JACK_ENABLED LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/test.jpp endif +LOCAL_MIN_SDK_VERSION := 8 + include $(BUILD_PACKAGE) ifndef LOCAL_JACK_ENABLED @@ -85,6 +87,8 @@ ifdef LOCAL_JACK_ENABLED 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 000000000000..69ec5ceb1daf --- /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 000000000000..35369c7da6a1 --- /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 000000000000..a0288f2e0d9c --- /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 000000000000..9a79c7aa4db7 --- /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 000000000000..e28584b5f321 --- /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 000000000000..f2bd35363003 --- /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 000000000000..1cadfcdf3b81 --- /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 000000000000..4e6ec142e690 --- /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 000000000000..3e5e81e5babb --- /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 000000000000..963f90432dd7 --- /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 000000000000..acff80fdd846 --- /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 2f0a411448a5..232459338f48 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 4a99638aec95..f6c233954b52 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 34465e92a1ef..57e155a04bd7 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.Log; 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 @@ public class CaptivePortalLoginActivity extends Activity { // 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 @@ public class CaptivePortalLoginActivity extends Activity { } 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 @@ public class CaptivePortalLoginActivity extends Activity { 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 @@ public class CaptivePortalLoginActivity extends Activity { 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 @@ public class CaptivePortalLoginActivity extends Activity { // 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 @@ public class CaptivePortalLoginActivity extends Activity { 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 4691e1aac390..abbdd5412c23 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 @@ final class TaskRecord { 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 80885543288d..dffa670f6e7a 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 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering 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 12899d803ca4..c64e70516abc 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 @@ public class OffloadController { 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 @@ public class OffloadController { // 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 060dd73d11c8..4152070dc61b 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.IFACE_ALL; 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.DAY_IN_MILLIS; 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 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // 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 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** * 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 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // 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 4c732d762bd8..99b74a93e982 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 @@ public class PackageManagerService extends IPackageManager.Stub { 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 5c718c75e68a..e81c97e5fca8 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -32,6 +32,7 @@ import android.content.ContentResolver; 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; 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 @@ public class TelephonyManager { /** * 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 fb6782e17f4b..63e7abf8ec04 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.Bundle; 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 @@ interface ITelephony { /** * 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 063cd5dc48b7..adf699808666 100644 --- a/tests/net/java/android/net/nsd/NsdManagerTest.java +++ b/tests/net/java/android/net/nsd/NsdManagerTest.java @@ -333,7 +333,7 @@ public class NsdManagerTest { 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 4fdbfe75da28..0263c57879dc 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -2411,8 +2411,7 @@ public class ConnectivityServiceTest extends AndroidTestCase { } @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 @@ public class ConnectivityServiceTest extends AndroidTestCase { // 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 d5a0b864583a..241b828d8f4d 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.verifyNoMoreInteractions; 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.PersistableBundle; 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 @@ public class TetheringTest { private Vector<Intent> mIntents; private BroadcastInterceptingContext mServiceContext; + private MockContentResolver mContentResolver; private BroadcastReceiver mBroadcastReceiver; private Tethering mTethering; @@ -105,6 +110,12 @@ public class TetheringTest { } @Override + public ContentResolver getContentResolver() { return mContentResolver; } + + @Override + public String getPackageName() { return "TetheringTest"; } + + @Override public Resources getResources() { return mResources; } @Override @@ -134,6 +145,8 @@ public class TetheringTest { .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 000000000000..fb7971e1e104 --- /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(); + } +} |