Merge "Add sources read implicitly when building android.test.mock.stubs.source.test"
diff --git a/apex/Android.bp b/apex/Android.bp
index c381c0f..3a63c805 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -63,6 +63,63 @@
"--hide-annotation android.annotation.Hide " +
"--hide InternalClasses " // com.android.* classes are okay in this interface
+// Defaults for mainline module provided java_sdk_library instances.
+java_defaults {
+ name: "framework-module-defaults",
+
+ // Additional annotations used for compiling both the implementation and the
+ // stubs libraries.
+ libs: ["framework-annotations-lib"],
+
+ // Enable api lint. This will eventually become the default for java_sdk_library
+ // but it cannot yet be turned on because some usages have not been cleaned up.
+ // TODO(b/156126315) - Remove when no longer needed.
+ api_lint: {
+ enabled: true,
+ },
+
+ // The API scope specific properties.
+ public: {
+ enabled: true,
+ sdk_version: "module_current",
+ },
+ system: {
+ enabled: true,
+ sdk_version: "module_current",
+ },
+ module_lib: {
+ enabled: true,
+ sdk_version: "module_current",
+ },
+
+ // Configure framework module specific metalava options.
+ droiddoc_options: [mainline_stubs_args],
+
+ // The stub libraries must be visible to frameworks/base so they can be combined
+ // into API specific libraries.
+ stubs_library_visibility: [
+ "//frameworks/base", // Framework
+ ],
+
+ // Set the visibility of the modules creating the stubs source.
+ stubs_source_visibility: [
+ // Ignore any visibility rules specified on the java_sdk_library when
+ // setting the visibility of the stubs source modules.
+ "//visibility:override",
+
+ // Currently, the stub source is not required for anything other than building
+ // the stubs library so is private to avoid misuse.
+ "//visibility:private",
+ ],
+
+ // Collates API usages from each module for further analysis.
+ plugins: ["java_api_finder"],
+
+ // Mainline modules should only rely on 'module_lib' APIs provided by other modules
+ // and the non updatable parts of the platform.
+ sdk_version: "module_current",
+}
+
stubs_defaults {
name: "framework-module-stubs-defaults-publicapi",
args: mainline_framework_stubs_args,
diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp
index dbb5bd3d..fdb078e 100644
--- a/apex/sdkextensions/Android.bp
+++ b/apex/sdkextensions/Android.bp
@@ -39,7 +39,7 @@
sdk {
name: "sdkextensions-sdk",
- java_header_libs: [ "framework-sdkextensions-stubs-systemapi" ],
+ java_sdk_libs: [ "framework-sdkextensions" ],
}
apex_key {
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
index 6a78711..b8aad7d 100644
--- a/apex/sdkextensions/framework/Android.bp
+++ b/apex/sdkextensions/framework/Android.bp
@@ -25,14 +25,18 @@
visibility: [ "//frameworks/base" ] // For the "global" stubs.
}
-java_library {
+java_sdk_library {
name: "framework-sdkextensions",
srcs: [ ":framework-sdkextensions-sources" ],
- sdk_version: "system_current",
- libs: [ "framework-annotations-lib" ],
+ defaults: ["framework-module-defaults"],
+
+ // TODO(b/155480189) - Remove naming_scheme once references have been resolved.
+ // Temporary java_sdk_library component naming scheme to use to ease the transition from separate
+ // modules to java_sdk_library.
+ naming_scheme: "framework-modules",
+
permitted_packages: [ "android.os.ext" ],
installable: true,
- plugins: ["java_api_finder"],
visibility: [
"//frameworks/base/apex/sdkextensions",
"//frameworks/base/apex/sdkextensions/testing",
@@ -43,75 +47,3 @@
"test_com.android.sdkext",
],
}
-
-stubs_defaults {
- name: "framework-sdkextensions-stubs-defaults",
- srcs: [ ":framework-sdkextensions-sources" ],
- libs: [ "framework-annotations-lib" ],
- dist: { dest: "framework-sdkextensions.txt" },
-}
-
-droidstubs {
- name: "framework-sdkextensions-stubs-srcs-publicapi",
- defaults: [
- "framework-module-stubs-defaults-publicapi",
- "framework-sdkextensions-stubs-defaults",
- ],
-}
-
-droidstubs {
- name: "framework-sdkextensions-stubs-srcs-systemapi",
- defaults: [
- "framework-module-stubs-defaults-systemapi",
- "framework-sdkextensions-stubs-defaults",
- ],
-}
-
-droidstubs {
- name: "framework-sdkextensions-api-module_libs_api",
- defaults: [
- "framework-module-api-defaults-module_libs_api",
- "framework-sdkextensions-stubs-defaults",
- ],
-}
-
-droidstubs {
- name: "framework-sdkextensions-stubs-srcs-module_libs_api",
- defaults: [
- "framework-module-stubs-defaults-module_libs_api",
- "framework-sdkextensions-stubs-defaults",
- ],
-}
-
-java_library {
- name: "framework-sdkextensions-stubs-publicapi",
- srcs: [":framework-sdkextensions-stubs-srcs-publicapi"],
- defaults: ["framework-module-stubs-lib-defaults-publicapi"],
- visibility: [
- "//frameworks/base", // Framework
- "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
- ],
- dist: { dest: "framework-sdkextensions.jar" },
-}
-
-java_library {
- name: "framework-sdkextensions-stubs-systemapi",
- srcs: [":framework-sdkextensions-stubs-srcs-systemapi"],
- defaults: ["framework-module-stubs-lib-defaults-systemapi"],
- visibility: [
- "//frameworks/base", // Framework
- "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
- ],
- dist: { dest: "framework-sdkextensions.jar" },
-}
-
-java_library {
- name: "framework-sdkextensions-stubs-module_libs_api",
- srcs: [":framework-sdkextensions-stubs-srcs-module_libs_api"],
- defaults: ["framework-module-stubs-lib-defaults-module_libs_api"],
- visibility: [
- "//frameworks/base", // Framework
- "//frameworks/base/apex/sdkextensions", // sdkextensions SDK
- ],
- dist: { dest: "framework-sdkextensions.jar" },
-}
diff --git a/api/current.txt b/api/current.txt
index e63cb45..8163426 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -41304,6 +41304,7 @@
method public int getPurposes();
method @NonNull public String[] getSignaturePaddings();
method public int getUserAuthenticationValidityDurationSeconds();
+ method public boolean isDevicePropertiesAttestationIncluded();
method @NonNull public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
@@ -41325,6 +41326,7 @@
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateNotBefore(@NonNull java.util.Date);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSerialNumber(@NonNull java.math.BigInteger);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateSubject(@NonNull javax.security.auth.x500.X500Principal);
+ method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setDevicePropertiesAttestationIncluded(boolean);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
diff --git a/cmds/device_config/Android.bp b/cmds/device_config/Android.bp
new file mode 100644
index 0000000..67e014a
--- /dev/null
+++ b/cmds/device_config/Android.bp
@@ -0,0 +1,7 @@
+// Copyright 2018 The Android Open Source Project
+//
+
+sh_binary {
+ name: "device_config",
+ src: "device_config",
+}
diff --git a/cmds/device_config/Android.mk b/cmds/device_config/Android.mk
deleted file mode 100644
index 4041e01..0000000
--- a/cmds/device_config/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2018 The Android Open Source Project
-#
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := device_config
-LOCAL_SRC_FILES := device_config
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_MODULE_TAGS := optional
-include $(BUILD_PREBUILT)
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index d9d697a..52e9385 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -5884,11 +5884,11 @@
* Logs when a data stall event occurs.
*
* Log from:
- * frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+ * packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
*/
message DataStallEvent {
// Data stall evaluation type.
- // See frameworks/base/services/core/java/com/android/server/connectivity/NetworkMonitor.java
+ // See packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
// Refer to the definition of DATA_STALL_EVALUATION_TYPE_*.
optional int32 evaluation_type = 1;
// See definition in data_stall_event.proto.
@@ -5901,6 +5901,10 @@
optional com.android.server.connectivity.CellularData cell_info = 5 [(log_mode) = MODE_BYTES];
// See definition in data_stall_event.proto.
optional com.android.server.connectivity.DnsEvent dns_event = 6 [(log_mode) = MODE_BYTES];
+ // The tcp packets fail rate from the latest tcp polling.
+ optional int32 tcp_fail_rate = 7;
+ // Number of packets sent since the last received packet.
+ optional int32 tcp_sent_since_last_recv = 8;
}
/*
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 9a17346..2888fbd 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -110,8 +110,9 @@
* off to save power. Scanning is resumed when screen is turned on again. To avoid this, use
* {@link #startScan(List, ScanSettings, ScanCallback)} with desired {@link ScanFilter}.
* <p>
- * An app must hold
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+ * An app must have
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
+ * in order to get results. An App targeting Android Q or later must have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get results.
*
@@ -129,8 +130,9 @@
* resumed when screen is turned on again. To avoid this, do filetered scanning by
* using proper {@link ScanFilter}.
* <p>
- * An app must hold
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+ * An app must have
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
+ * in order to get results. An App targeting Android Q or later must have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get results.
*
@@ -150,8 +152,9 @@
* the PendingIntent. Use this method of scanning if your process is not always running and it
* should be started when scan results are available.
* <p>
- * An app must hold
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
+ * An app must have
+ * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} permission
+ * in order to get results. An App targeting Android Q or later must have
* {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
* in order to get results.
* <p>
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index 9086d49..275e38c 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -437,7 +437,7 @@
*/
private long mReportTimestamp;
- /** The detection method used to identify the suspected data stall */
+ /** A bitmask of the detection methods used to identify the suspected data stall */
@DetectionMethod private final int mDetectionMethod;
/** LinkProperties available on the Network at the reported timestamp */
@@ -499,9 +499,9 @@
}
/**
- * Returns the detection method used to identify this suspected data stall.
+ * Returns the bitmask of detection methods used to identify this suspected data stall.
*
- * @return The detection method used to identify the suspected data stall
+ * @return The bitmask of detection methods used to identify the suspected data stall
*/
public int getDetectionMethod() {
return mDetectionMethod;
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index 6632ca5..9b360ed 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -118,7 +118,21 @@
* by this Parcelable object instance.
*/
public @ContentsFlags int describeContents();
-
+
+ /**
+ * 'Stable' means this parcelable is guaranteed to be stable for multiple years.
+ * It must be guaranteed by setting stability field in aidl_interface,
+ * OR explicitly override this method from @JavaOnlyStableParcelable marked Parcelable.
+ * WARNING: isStable() is only expected to be overridden by auto-generated code,
+ * OR @JavaOnlyStableParcelable marked Parcelable only if there is guaranteed to
+ * be only once copy of the parcelable on the system.
+ * @return true if this parcelable is stable.
+ * @hide
+ */
+ default boolean isStable() {
+ return false;
+ }
+
/**
* Flatten this object in to a Parcel.
*
diff --git a/core/java/android/os/Registrant.java b/core/java/android/os/Registrant.java
index d6afd04..bde7ec1 100644
--- a/core/java/android/os/Registrant.java
+++ b/core/java/android/os/Registrant.java
@@ -46,7 +46,7 @@
{
internalNotifyRegistrant (null, null);
}
-
+
@UnsupportedAppUsage
public void
notifyResult(Object result)
@@ -81,9 +81,7 @@
Message msg = Message.obtain();
msg.what = what;
-
msg.obj = new AsyncResult(userObj, result, exception);
-
h.sendMessage(msg);
}
}
@@ -126,4 +124,3 @@
int what;
Object userObj;
}
-
diff --git a/core/java/android/os/RegistrantList.java b/core/java/android/os/RegistrantList.java
index 98f949b..53e0ae4 100644
--- a/core/java/android/os/RegistrantList.java
+++ b/core/java/android/os/RegistrantList.java
@@ -42,9 +42,9 @@
{
// if the handler is already in the registrant list, remove it
remove(h);
- add(new Registrant(h, what, obj));
+ add(new Registrant(h, what, obj));
}
-
+
@UnsupportedAppUsage
public synchronized void
add(Registrant r)
@@ -59,7 +59,7 @@
{
for (int i = registrants.size() - 1; i >= 0 ; i--) {
Registrant r = (Registrant) registrants.get(i);
-
+
if (r.refH == null) {
registrants.remove(i);
}
@@ -88,7 +88,7 @@
r.internalNotifyRegistrant(result, exception);
}
}
-
+
@UnsupportedAppUsage
public /*synchronized*/ void
notifyRegistrants()
@@ -109,14 +109,14 @@
internalNotifyRegistrants (result, null);
}
-
+
@UnsupportedAppUsage
public /*synchronized*/ void
notifyRegistrants(AsyncResult ar)
{
internalNotifyRegistrants(ar.result, ar.exception);
}
-
+
@UnsupportedAppUsage
public synchronized void
remove(Handler h)
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 9cbb035..f44f24a 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -16,6 +16,8 @@
package android.widget;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.annotation.InterpolatorRes;
import android.annotation.NonNull;
@@ -246,6 +248,8 @@
private AccessibilityEventSender mAccessibilityEventSender;
+ private ObjectAnimator mLastProgressAnimator;
+
/**
* Create a new progress bar with range 0...100 and initial progress of 0.
* @param context the application environment
@@ -1544,8 +1548,19 @@
animator.setAutoCancel(true);
animator.setDuration(PROGRESS_ANIM_DURATION);
animator.setInterpolator(PROGRESS_ANIM_INTERPOLATOR);
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mLastProgressAnimator = null;
+ }
+ });
animator.start();
+ mLastProgressAnimator = animator;
} else {
+ if (isPrimary && mLastProgressAnimator != null) {
+ mLastProgressAnimator.cancel();
+ mLastProgressAnimator = null;
+ }
setVisualProgress(id, scale);
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index b30fed6..544340e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -693,6 +693,7 @@
char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
char extraOptsBuf[PROPERTY_VALUE_MAX];
char voldDecryptBuf[PROPERTY_VALUE_MAX];
+ char perfettoHprofOptBuf[sizeof("-XX:PerfettoHprof=") + PROPERTY_VALUE_MAX];
enum {
kEMDefault,
kEMIntPortable,
@@ -807,6 +808,16 @@
addOption("-verbose:gc");
//addOption("-verbose:class");
+ // On Android, we always want to allow loading the PerfettoHprof plugin.
+ // Even with this option set, we will still only actually load the plugin
+ // if we are on a userdebug build or the app is debuggable or profileable.
+ // This is enforced in art/runtime/runtime.cc.
+ //
+ // We want to be able to disable this, because this does not work on host,
+ // and we do not want to enable it in tests.
+ parseRuntimeOption("dalvik.vm.perfetto_hprof", perfettoHprofOptBuf, "-XX:PerfettoHprof=",
+ "true");
+
if (primary_zygote) {
addOption("-Xprimaryzygote");
}
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 9cc04d3..d5733e3 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -39,7 +39,7 @@
<!-- Albania: 5 digits, known short codes listed -->
<shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
- <!-- Argentia: 5 digits, known short codes listed -->
+ <!-- Argentina: 5 digits, known short codes listed -->
<shortcode country="ar" pattern="\\d{5}" free="11711|28291" />
<!-- Armenia: 3-4 digits, emergency numbers 10[123] -->
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
new file mode 100644
index 0000000..2194d4b
--- /dev/null
+++ b/core/tests/hdmitests/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "HdmiCecTests",
+ // Include all test java files
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "frameworks-base-testutils",
+ "truth-prebuilt",
+ ],
+ libs: ["android.test.runner"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/core/tests/hdmitests/Android.mk b/core/tests/hdmitests/Android.mk
deleted file mode 100644
index f155feb..0000000
--- a/core/tests/hdmitests/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules frameworks-base-testutils truth-prebuilt
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_PACKAGE_NAME := HdmiCecTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/packagemanagertests/Android.bp b/core/tests/packagemanagertests/Android.bp
new file mode 100644
index 0000000..6f39af8
--- /dev/null
+++ b/core/tests/packagemanagertests/Android.bp
@@ -0,0 +1,14 @@
+android_test {
+ name: "FrameworksCorePackageManagerTests",
+ // We only want this apk build for tests.
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "frameworks-base-testutils",
+ "mockito-target-minus-junit4",
+ ],
+ libs: ["android.test.runner"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/core/tests/packagemanagertests/Android.mk b/core/tests/packagemanagertests/Android.mk
deleted file mode 100644
index 8c00d14..0000000
--- a/core/tests/packagemanagertests/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- frameworks-base-testutils \
- mockito-target-minus-junit4
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_PACKAGE_NAME := FrameworksCorePackageManagerTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/privacytests/Android.bp b/core/tests/privacytests/Android.bp
new file mode 100644
index 0000000..7f56992
--- /dev/null
+++ b/core/tests/privacytests/Android.bp
@@ -0,0 +1,14 @@
+android_test {
+ name: "FrameworksPrivacyLibraryTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "junit",
+ "rappor-tests",
+ "androidx.test.rules",
+ "truth-prebuilt",
+ ],
+ libs: ["android.test.runner"],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+}
diff --git a/core/tests/privacytests/Android.mk b/core/tests/privacytests/Android.mk
deleted file mode 100644
index 7765977..0000000
--- a/core/tests/privacytests/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit rappor-tests androidx.test.rules truth-prebuilt
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_PACKAGE_NAME := FrameworksPrivacyLibraryTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/core/xsd/vts/Android.bp b/core/xsd/vts/Android.bp
index ca655f1..4b43b41 100644
--- a/core/xsd/vts/Android.bp
+++ b/core/xsd/vts/Android.bp
@@ -40,3 +40,7 @@
],
test_config: "vts_permission_validate_test.xml",
}
+
+vts_config {
+ name: "VtsValidatePermission",
+}
diff --git a/core/xsd/vts/Android.mk b/core/xsd/vts/Android.mk
deleted file mode 100644
index a5754a4..0000000
--- a/core/xsd/vts/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Copyright (C) 2019 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)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := VtsValidatePermission
-include test/vts/tools/build/Android.host_config.mk
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 91aac83..11775ca 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -17,11 +17,10 @@
package android.security.keystore;
import android.annotation.Nullable;
+import android.os.Build;
import android.security.Credentials;
-import android.security.GateKeeper;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore;
-import android.security.KeyStoreException;
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterCertificateChain;
@@ -52,6 +51,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -494,6 +494,20 @@
if (challenge != null) {
KeymasterArguments args = new KeymasterArguments();
args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge);
+
+ if (mSpec.isDevicePropertiesAttestationIncluded()) {
+ args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
+ Build.BRAND.getBytes(StandardCharsets.UTF_8));
+ args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
+ Build.DEVICE.getBytes(StandardCharsets.UTF_8));
+ args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
+ Build.PRODUCT.getBytes(StandardCharsets.UTF_8));
+ args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
+ Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8));
+ args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
+ Build.MODEL.getBytes(StandardCharsets.UTF_8));
+ }
+
return getAttestationChain(privateKeyAlias, keyPair, args);
}
@@ -603,8 +617,14 @@
private Iterable<byte[]> getAttestationChain(String privateKeyAlias,
KeyPair keyPair, KeymasterArguments args)
throws ProviderException {
- KeymasterCertificateChain outChain = new KeymasterCertificateChain();
- int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
+ final KeymasterCertificateChain outChain = new KeymasterCertificateChain();
+ final int errorCode;
+ if (mSpec.isDevicePropertiesAttestationIncluded()
+ && mSpec.getAttestationChallenge() == null) {
+ throw new ProviderException("An attestation challenge must be provided when requesting "
+ + "device properties attestation.");
+ }
+ errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
if (errorCode != KeyStore.NO_ERROR) {
throw new ProviderException("Failed to generate attestation certificate chain",
KeyStore.getKeyStoreException(errorCode));
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 630a6dd..e7e410a 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -24,6 +24,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
+import android.os.Build;
import android.security.GateKeeper;
import android.security.KeyStore;
import android.text.TextUtils;
@@ -264,6 +265,7 @@
private final int mUserAuthenticationValidityDurationSeconds;
private final boolean mUserPresenceRequired;
private final byte[] mAttestationChallenge;
+ private final boolean mDevicePropertiesAttestationIncluded;
private final boolean mUniqueIdIncluded;
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
@@ -301,6 +303,7 @@
int userAuthenticationValidityDurationSeconds,
boolean userPresenceRequired,
byte[] attestationChallenge,
+ boolean devicePropertiesAttestationIncluded,
boolean uniqueIdIncluded,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
@@ -350,6 +353,7 @@
mUserPresenceRequired = userPresenceRequired;
mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds;
mAttestationChallenge = Utils.cloneIfNotNull(attestationChallenge);
+ mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded;
mUniqueIdIncluded = uniqueIdIncluded;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
@@ -644,6 +648,21 @@
}
/**
+ * Returns {@code true} if attestation for the base device properties ({@link Build#BRAND},
+ * {@link Build#DEVICE}, {@link Build#MANUFACTURER}, {@link Build#MODEL}, {@link Build#PRODUCT})
+ * was requested to be added in the attestation certificate for the generated key.
+ *
+ * {@link javax.crypto.KeyGenerator#generateKey()} will throw
+ * {@link java.security.ProviderException} if device properties attestation fails or is not
+ * supported.
+ *
+ * @see Builder#setDevicePropertiesAttestationIncluded(boolean)
+ */
+ public boolean isDevicePropertiesAttestationIncluded() {
+ return mDevicePropertiesAttestationIncluded;
+ }
+
+ /**
* @hide This is a system-only API
*
* Returns {@code true} if the attestation certificate will contain a unique ID field.
@@ -734,6 +753,7 @@
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mUserPresenceRequired = false;
private byte[] mAttestationChallenge = null;
+ private boolean mDevicePropertiesAttestationIncluded = false;
private boolean mUniqueIdIncluded = false;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
@@ -797,6 +817,8 @@
sourceSpec.getUserAuthenticationValidityDurationSeconds();
mUserPresenceRequired = sourceSpec.isUserPresenceRequired();
mAttestationChallenge = sourceSpec.getAttestationChallenge();
+ mDevicePropertiesAttestationIncluded =
+ sourceSpec.isDevicePropertiesAttestationIncluded();
mUniqueIdIncluded = sourceSpec.isUniqueIdIncluded();
mUserAuthenticationValidWhileOnBody = sourceSpec.isUserAuthenticationValidWhileOnBody();
mInvalidatedByBiometricEnrollment = sourceSpec.isInvalidatedByBiometricEnrollment();
@@ -1252,6 +1274,31 @@
}
/**
+ * Sets whether to include the base device properties in the attestation certificate.
+ *
+ * <p>If {@code attestationChallenge} is not {@code null}, the public key certificate for
+ * this key pair will contain an extension that describes the details of the key's
+ * configuration and authorizations, including the device properties values (brand, device,
+ * manufacturer, model, product). These should be the same as in ({@link Build#BRAND},
+ * {@link Build#DEVICE}, {@link Build#MANUFACTURER}, {@link Build#MODEL},
+ * {@link Build#PRODUCT}). The attestation certificate chain can
+ * be retrieved with {@link java.security.KeyStore#getCertificateChain(String)}.
+ *
+ * <p> If {@code attestationChallenge} is {@code null}, the public key certificate for
+ * this key pair will not contain the extension with the requested attested values.
+ *
+ * <p> {@link javax.crypto.KeyGenerator#generateKey()} will throw
+ * {@link java.security.ProviderException} if device properties attestation fails or is not
+ * supported.
+ */
+ @NonNull
+ public Builder setDevicePropertiesAttestationIncluded(
+ boolean devicePropertiesAttestationIncluded) {
+ mDevicePropertiesAttestationIncluded = devicePropertiesAttestationIncluded;
+ return this;
+ }
+
+ /**
* @hide Only system apps can use this method.
*
* Sets whether to include a temporary unique ID field in the attestation certificate.
@@ -1360,6 +1407,7 @@
mUserAuthenticationValidityDurationSeconds,
mUserPresenceRequired,
mAttestationChallenge,
+ mDevicePropertiesAttestationIncluded,
mUniqueIdIncluded,
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
diff --git a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
index d8030fb..0518f45 100644
--- a/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/ParcelableKeyGenParameterSpec.java
@@ -16,8 +16,8 @@
package android.security.keystore;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
@@ -99,6 +99,7 @@
out.writeInt(mSpec.getUserAuthenticationValidityDurationSeconds());
out.writeBoolean(mSpec.isUserPresenceRequired());
out.writeByteArray(mSpec.getAttestationChallenge());
+ out.writeBoolean(mSpec.isDevicePropertiesAttestationIncluded());
out.writeBoolean(mSpec.isUniqueIdIncluded());
out.writeBoolean(mSpec.isUserAuthenticationValidWhileOnBody());
out.writeBoolean(mSpec.isInvalidatedByBiometricEnrollment());
@@ -154,6 +155,7 @@
final int userAuthenticationValidityDurationSeconds = in.readInt();
final boolean userPresenceRequired = in.readBoolean();
final byte[] attestationChallenge = in.createByteArray();
+ final boolean devicePropertiesAttestationIncluded = in.readBoolean();
final boolean uniqueIdIncluded = in.readBoolean();
final boolean userAuthenticationValidWhileOnBody = in.readBoolean();
final boolean invalidatedByBiometricEnrollment = in.readBoolean();
@@ -185,6 +187,7 @@
userAuthenticationValidityDurationSeconds,
userPresenceRequired,
attestationChallenge,
+ devicePropertiesAttestationIncluded,
uniqueIdIncluded,
userAuthenticationValidWhileOnBody,
invalidatedByBiometricEnrollment,
diff --git a/lowpan/tests/Android.bp b/lowpan/tests/Android.bp
new file mode 100644
index 0000000..ad2bc27
--- /dev/null
+++ b/lowpan/tests/Android.bp
@@ -0,0 +1,41 @@
+// 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.
+
+// Make test APK
+// ============================================================
+android_test {
+ name: "FrameworksLowpanApiTests",
+ srcs: ["**/*.java"],
+ // Filter all src files to just java files
+ jacoco: {
+ include_filter: ["android.net.lowpan.*"],
+ exclude_filter: [
+ "android.net.lowpan.LowpanInterfaceTest*",
+ "android.net.lowpan.LowpanManagerTest*",
+ ],
+ },
+ static_libs: [
+ "androidx.test.rules",
+ "guava",
+ "mockito-target-minus-junit4",
+ "frameworks-base-testutils",
+ ],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ certificate: "platform",
+}
diff --git a/lowpan/tests/Android.mk b/lowpan/tests/Android.mk
deleted file mode 100644
index 832ed2f..0000000
--- a/lowpan/tests/Android.mk
+++ /dev/null
@@ -1,63 +0,0 @@
-# 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-# Make test APK
-# ============================================================
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-# This list is generated from the java source files in this module
-# The list is a comma separated list of class names with * matching zero or more characters.
-# Example:
-# Input files: src/com/android/server/lowpan/Test.java src/com/android/server/lowpan/AnotherTest.java
-# Generated exclude list: com.android.server.lowpan.Test*,com.android.server.lowpan.AnotherTest*
-
-# Filter all src files to just java files
-local_java_files := $(filter %.java,$(LOCAL_SRC_FILES))
-# Transform java file names into full class names.
-# This only works if the class name matches the file name and the directory structure
-# matches the package.
-local_classes := $(subst /,.,$(patsubst src/%.java,%,$(local_java_files)))
-# Convert class name list to jacoco exclude list
-# This appends a * to all classes and replace the space separators with commas.
-# These patterns will match all classes in this module and their inner classes.
-jacoco_exclude := $(subst $(space),$(comma),$(patsubst %,%*,$(local_classes)))
-
-jacoco_include := android.net.lowpan.*
-
-LOCAL_JACK_COVERAGE_INCLUDE_FILTER := $(jacoco_include)
-LOCAL_JACK_COVERAGE_EXCLUDE_FILTER := $(jacoco_exclude)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- guava \
- mockito-target-minus-junit4 \
- frameworks-base-testutils \
-
-LOCAL_JAVA_LIBRARIES := \
- android.test.runner \
- android.test.base \
-
-LOCAL_PACKAGE_NAME := FrameworksLowpanApiTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_CERTIFICATE := platform
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-include $(BUILD_PACKAGE)
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 9f52d85..8f36dec 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -93,14 +93,6 @@
},
}
-// Header-only library used for atrace in platform NDK builds
-cc_library_headers {
- name: "libandroid_trace",
- host_supported: true,
- vendor_available: true,
- export_include_dirs: ["trace"],
-}
-
// Network library.
cc_library_shared {
name: "libandroid_net",
diff --git a/native/android/trace/android/trace.h b/native/android/trace/android/trace.h
deleted file mode 100644
index 4e569e5..0000000
--- a/native/android/trace/android/trace.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ANDROID_ATRACE_HEADERS_H
-#define ANDROID_ATRACE_HEADERS_H
-
-#include <cutils/trace.h>
-
-inline void ATrace_beginSection(const char* sectionName) {
- atrace_begin(ATRACE_TAG_APP, sectionName);
-}
-
-inline void ATrace_endSection() {
- atrace_end(ATRACE_TAG_APP);
-}
-
-#endif // ANDROID_ATRACE_HEADERS_H
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 24d0896..c1ec9b0 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -299,22 +299,6 @@
android:excludeFromRecents="true"
android:exported="false" />
- <!--
- The following is used as a no-op/null home activity when
- no other MAIN/HOME activity is present (e.g., in CSI).
- -->
- <activity android:name=".NullHome"
- android:excludeFromRecents="true"
- android:label=""
- android:screenOrientation="nosensor">
- <!-- The priority here is set to be lower than that for Settings -->
- <intent-filter android:priority="-1100">
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.HOME" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<receiver
android:name=".BugreportReceiver"
android:permission="android.permission.DUMP">
diff --git a/packages/Shell/res/layout/null_home_finishing_boot.xml b/packages/Shell/res/layout/null_home_finishing_boot.xml
deleted file mode 100644
index 5f9563a..0000000
--- a/packages/Shell/res/layout/null_home_finishing_boot.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2020 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
- -->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#80000000"
- android:forceHasOverlappingRendering="false">
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_gravity="center"
- android:layout_marginStart="16dp"
- android:layout_marginEnd="16dp">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="40sp"
- android:textColor="?android:attr/textColorPrimary"
- android:text="@*android:string/android_start_title"/>
- <ProgressBar
- style="@android:style/Widget.Material.ProgressBar.Horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="12.75dp"
- android:colorControlActivated="?android:attr/textColorPrimary"
- android:indeterminate="true"/>
- </LinearLayout>
-</FrameLayout>
diff --git a/packages/Shell/src/com/android/shell/NullHome.java b/packages/Shell/src/com/android/shell/NullHome.java
deleted file mode 100644
index bd97561..0000000
--- a/packages/Shell/src/com/android/shell/NullHome.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2020 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.shell;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * This covers the fallback case where no launcher is available.
- * Usually Settings.apk has one fallback home activity.
- * Settings.apk, however, is not part of CSI, which needs to be
- * standalone (bootable and testable).
- */
-public class NullHome extends Activity {
- private static final String TAG = "NullHome";
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.i(TAG, "onCreate");
- setContentView(R.layout.null_home_finishing_boot);
- }
-
- protected void onDestroy() {
- super.onDestroy();
- Log.i(TAG, "onDestroy");
- }
-}
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index de53787..659d344 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -738,7 +738,7 @@
//
// TODO: Evaluate using a data structure than is more directly suited to
// communicating only the relevant information.
- private void updateUpstreamIPv6LinkProperties(LinkProperties v6only) {
+ private void updateUpstreamIPv6LinkProperties(LinkProperties v6only, int ttlAdjustment) {
if (mRaDaemon == null) return;
// Avoid unnecessary work on spurious updates.
@@ -761,7 +761,7 @@
params.mtu = mUsingBpfOffload ? v6only.getMtu() - 16 : v6only.getMtu();
params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
- if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface);
+ if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface, ttlAdjustment);
for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
@@ -1052,12 +1052,11 @@
}
}
- private byte getHopLimit(String upstreamIface) {
+ private byte getHopLimit(String upstreamIface, int adjustTTL) {
try {
int upstreamHopLimit = Integer.parseUnsignedInt(
mNetd.getProcSysNet(INetd.IPV6, INetd.CONF, upstreamIface, "hop_limit"));
- // Add one hop to account for this forwarding device
- upstreamHopLimit++;
+ upstreamHopLimit = upstreamHopLimit + adjustTTL;
// Cap the hop limit to 255.
return (byte) Integer.min(upstreamHopLimit, 255);
} catch (Exception e) {
@@ -1145,7 +1144,7 @@
transitionTo(mUnavailableState);
break;
case CMD_IPV6_TETHER_UPDATE:
- updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
+ updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);
break;
default:
return NOT_HANDLED;
@@ -1209,7 +1208,7 @@
if (DBG) Log.d(TAG, "Untethered (ifdown)" + mIfaceName);
break;
case CMD_IPV6_TETHER_UPDATE:
- updateUpstreamIPv6LinkProperties((LinkProperties) message.obj);
+ updateUpstreamIPv6LinkProperties((LinkProperties) message.obj, message.arg1);
sendLinkProperties();
break;
case CMD_IP_FORWARDING_ENABLE_ERROR:
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java
index d450c46..f3dcaa2 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/IPv6TetheringCoordinator.java
@@ -161,11 +161,28 @@
private void updateIPv6TetheringInterfaces() {
for (IpServer ipServer : mNotifyList) {
final LinkProperties lp = getInterfaceIPv6LinkProperties(ipServer);
- ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, lp);
+ ipServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, getTtlAdjustment(), 0, lp);
break;
}
}
+ private int getTtlAdjustment() {
+ if (mUpstreamNetworkState == null || mUpstreamNetworkState.networkCapabilities == null) {
+ return 0;
+ }
+
+ // If upstream is cellular, set the TTL in Router Advertisements to "network-set TTL" - 1
+ // for carrier requirement.
+ if (mUpstreamNetworkState.networkCapabilities.hasTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return -1;
+ }
+
+ // For other non-cellular upstream, set TTL as "network-set TTL" + 1 to preventing arbitrary
+ // distinction between tethered and untethered traffic.
+ return 1;
+ }
+
private LinkProperties getInterfaceIPv6LinkProperties(IpServer ipServer) {
final Downstream ds = findDownstream(ipServer);
if (ds == null) return null;
diff --git a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
index 7d01273..c11e862 100644
--- a/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/networkstack/tethering/TetheringService.java
@@ -264,10 +264,11 @@
if (onlyAllowPrivileged || mTethering.isTetherProvisioningRequired()) return false;
int uid = Binder.getCallingUid();
+
// If callerPkg's uid is not same as Binder.getCallingUid(),
// checkAndNoteWriteSettingsOperation will return false and the operation will be
// denied.
- return TetheringService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg,
+ return mService.checkAndNoteWriteSettingsOperation(mService, uid, callerPkg,
callingAttributionTag, false /* throwException */);
}
@@ -285,8 +286,8 @@
*
* @return {@code true} iff the package is allowed to write settings.
*/
- // TODO: Remove method and replace with direct call once R code is pushed to AOSP
- private static boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
+ @VisibleForTesting
+ boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
@NonNull String callingPackage, @Nullable String callingAttributionTag,
boolean throwException) {
return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
index 31eaabf..355342f 100644
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -16,9 +16,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack.tethering.tests.unit">
- <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
-
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
<service
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index cd1ff60..307ebf1 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -17,6 +17,7 @@
package android.net.ip;
import static android.net.INetd.IF_STATE_UP;
+import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.TetheringManager.TETHERING_BLUETOOTH;
import static android.net.TetheringManager.TETHERING_NCM;
import static android.net.TetheringManager.TETHERING_USB;
@@ -74,6 +75,7 @@
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IpNeighborMonitor.NeighborEvent;
import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
+import android.net.ip.RouterAdvertisementDaemon.RaParams;
import android.net.util.InterfaceParams;
import android.net.util.InterfaceSet;
import android.net.util.SharedLog;
@@ -196,7 +198,7 @@
if (upstreamIface != null) {
LinkProperties lp = new LinkProperties();
lp.setInterfaceName(upstreamIface);
- dispatchTetherConnectionChanged(upstreamIface, lp);
+ dispatchTetherConnectionChanged(upstreamIface, lp, 0);
}
reset(mNetd, mCallback);
}
@@ -694,7 +696,7 @@
InOrder inOrder = inOrder(mNetd);
LinkProperties lp = new LinkProperties();
lp.setInterfaceName(UPSTREAM_IFACE2);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp, -1);
inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighA, macA));
inOrder.verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighA, macA));
inOrder.verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX2, neighB, macB));
@@ -702,7 +704,7 @@
reset(mNetd);
// When the upstream is lost, rules are removed.
- dispatchTetherConnectionChanged(null, null);
+ dispatchTetherConnectionChanged(null, null, 0);
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighA, macA));
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX2, neighB, macB));
reset(mNetd);
@@ -715,19 +717,19 @@
// Rules can be added again once upstream IPv6 connectivity is available.
lp.setInterfaceName(UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighB, macB));
verify(mNetd, never()).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
// If upstream IPv6 connectivity is lost, rules are removed.
reset(mNetd);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, null);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
verify(mNetd).tetherOffloadRuleRemove(matches(UPSTREAM_IFINDEX, neighB, macB));
// When the interface goes down, rules are removed.
lp.setInterfaceName(UPSTREAM_IFACE);
- dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
verify(mNetd).tetherOffloadRuleAdd(matches(UPSTREAM_IFINDEX, neighA, macA));
@@ -788,6 +790,49 @@
verify(mIpNeighborMonitor, never()).start();
}
+ private LinkProperties buildIpv6OnlyLinkProperties(final String iface) {
+ final LinkProperties linkProp = new LinkProperties();
+ linkProp.setInterfaceName(iface);
+ linkProp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
+ linkProp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, iface, RTN_UNICAST));
+ final InetAddress dns = InetAddresses.parseNumericAddress("2001:4860:4860::8888");
+ linkProp.addDnsServer(dns);
+
+ return linkProp;
+ }
+
+ @Test
+ public void testAdjustTtlValue() throws Exception {
+ final ArgumentCaptor<RaParams> raParamsCaptor =
+ ArgumentCaptor.forClass(RaParams.class);
+ initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
+ verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
+ final RaParams noV6Params = raParamsCaptor.getValue();
+ assertEquals(65, noV6Params.hopLimit);
+ reset(mRaDaemon);
+
+ when(mNetd.getProcSysNet(
+ INetd.IPV6, INetd.CONF, UPSTREAM_IFACE, "hop_limit")).thenReturn("64");
+ final LinkProperties lp = buildIpv6OnlyLinkProperties(UPSTREAM_IFACE);
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, 1);
+ verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
+ final RaParams nonCellularParams = raParamsCaptor.getValue();
+ assertEquals(65, nonCellularParams.hopLimit);
+ reset(mRaDaemon);
+
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, null, 0);
+ verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
+ final RaParams noUpstream = raParamsCaptor.getValue();
+ assertEquals(65, nonCellularParams.hopLimit);
+ reset(mRaDaemon);
+
+ dispatchTetherConnectionChanged(UPSTREAM_IFACE, lp, -1);
+ verify(mRaDaemon).buildNewRa(any(), raParamsCaptor.capture());
+ final RaParams cellularParams = raParamsCaptor.getValue();
+ assertEquals(63, cellularParams.hopLimit);
+ reset(mRaDaemon);
+ }
+
private void assertDhcpServingParams(final DhcpServingParamsParcel params,
final IpPrefix prefix) {
// Last address byte is random
@@ -838,9 +883,10 @@
* @param upstreamIface String name of upstream interface (or null)
* @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
*/
- private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp) {
+ private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp,
+ int ttlAdjustment) {
dispatchTetherConnectionChanged(upstreamIface);
- mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, v6lp);
+ mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, ttlAdjustment, 0, v6lp);
mLooper.dispatchAll();
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java
index 820f255..f2b5314 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/IPv6TetheringCoordinatorTest.java
@@ -128,7 +128,7 @@
final UpstreamNetworkState mobileUpstream = createDualStackUpstream(TRANSPORT_CELLULAR);
final ArgumentCaptor<LinkProperties> lp = ArgumentCaptor.forClass(LinkProperties.class);
mIPv6TetheringCoordinator.updateUpstreamNetworkState(mobileUpstream);
- verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0),
+ verify(firstServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0),
lp.capture());
final LinkProperties v6OnlyLink = lp.getValue();
assertOnlyOneV6AddressAndNoV4(v6OnlyLink);
@@ -140,7 +140,7 @@
mNotifyList.remove(firstServer);
mIPv6TetheringCoordinator.removeActiveDownstream(firstServer);
verify(firstServer).sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, 0, 0, null);
- verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(0), eq(0),
+ verify(secondServer).sendMessage(eq(IpServer.CMD_IPV6_TETHER_UPDATE), eq(-1), eq(0),
lp.capture());
final LinkProperties localOnlyLink = lp.getValue();
assertNotNull(localOnlyLink);
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java
index 1c81c12..071a290e 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/MockTetheringService.java
@@ -15,13 +15,20 @@
*/
package com.android.networkstack.tethering;
+import static android.Manifest.permission.WRITE_SETTINGS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import static org.mockito.Mockito.mock;
+import android.content.Context;
import android.content.Intent;
import android.net.ITetheringConnector;
import android.os.Binder;
import android.os.IBinder;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
public class MockTetheringService extends TetheringService {
private final Tethering mTethering = mock(Tethering.class);
@@ -35,6 +42,15 @@
return mTethering;
}
+ @Override
+ boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
+ @NonNull String callingPackage, @Nullable String callingAttributionTag,
+ boolean throwException) {
+ // Test this does not verify the calling package / UID, as calling package could be shell
+ // and not match the UID.
+ return context.checkCallingOrSelfPermission(WRITE_SETTINGS) == PERMISSION_GRANTED;
+ }
+
public Tethering getTethering() {
return mTethering;
}
diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
index 3dc6a13..cf060ba 100644
--- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringServiceTest.java
@@ -16,20 +16,29 @@
package com.android.networkstack.tethering;
+import static android.Manifest.permission.ACCESS_NETWORK_STATE;
+import static android.Manifest.permission.TETHER_PRIVILEGED;
+import static android.Manifest.permission.WRITE_SETTINGS;
import static android.net.TetheringManager.TETHERING_WIFI;
+import static android.net.TetheringManager.TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION;
+import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import android.app.UiAutomation;
import android.content.Intent;
import android.net.IIntResultListener;
import android.net.ITetheringConnector;
import android.net.ITetheringEventCallback;
import android.net.TetheringRequestParcel;
+import android.os.Bundle;
+import android.os.Handler;
import android.os.ResultReceiver;
import androidx.test.InstrumentationRegistry;
@@ -51,13 +60,14 @@
@SmallTest
public final class TetheringServiceTest {
private static final String TEST_IFACE_NAME = "test_wlan0";
- private static final String TEST_CALLER_PKG = "test_pkg";
+ private static final String TEST_CALLER_PKG = "com.android.shell";
private static final String TEST_ATTRIBUTION_TAG = null;
@Mock private ITetheringEventCallback mITetheringEventCallback;
@Rule public ServiceTestRule mServiceTestRule;
private Tethering mTethering;
private Intent mMockServiceIntent;
private ITetheringConnector mTetheringConnector;
+ private UiAutomation mUiAutomation;
private class TestTetheringResult extends IIntResultListener.Stub {
private int mResult = -1; // Default value that does not match any result code.
@@ -71,9 +81,26 @@
}
}
+ private class MyResultReceiver extends ResultReceiver {
+ MyResultReceiver(Handler handler) {
+ super(handler);
+ }
+ private int mResult = -1; // Default value that does not match any result code.
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mResult = resultCode;
+ }
+
+ public void assertResult(int expected) {
+ assertEquals(expected, mResult);
+ }
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mUiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation();
mServiceTestRule = new ServiceTestRule();
mMockServiceIntent = new Intent(
InstrumentationRegistry.getTargetContext(),
@@ -83,115 +110,364 @@
mTetheringConnector = mockConnector.getTetheringConnector();
final MockTetheringService service = mockConnector.getService();
mTethering = service.getTethering();
- when(mTethering.isTetheringSupported()).thenReturn(true);
}
@After
public void tearDown() throws Exception {
mServiceTestRule.unbindService();
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+
+ private interface TestTetheringCall {
+ void runTetheringCall(TestTetheringResult result) throws Exception;
+ }
+
+ private void runAsNoPermission(final TestTetheringCall test) throws Exception {
+ runTetheringCall(test, new String[0]);
+ }
+
+ private void runAsTetherPrivileged(final TestTetheringCall test) throws Exception {
+ runTetheringCall(test, TETHER_PRIVILEGED);
+ }
+
+ private void runAsAccessNetworkState(final TestTetheringCall test) throws Exception {
+ runTetheringCall(test, ACCESS_NETWORK_STATE);
+ }
+
+ private void runAsWriteSettings(final TestTetheringCall test) throws Exception {
+ runTetheringCall(test, WRITE_SETTINGS);
+ }
+
+ private void runTetheringCall(final TestTetheringCall test, String... permissions)
+ throws Exception {
+ if (permissions.length > 0) mUiAutomation.adoptShellPermissionIdentity(permissions);
+ try {
+ when(mTethering.isTetheringSupported()).thenReturn(true);
+ test.runTetheringCall(new TestTetheringResult());
+ } finally {
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ private void verifyNoMoreInteractionsForTethering() {
+ verifyNoMoreInteractions(mTethering);
+ verifyNoMoreInteractions(mITetheringEventCallback);
+ reset(mTethering, mITetheringEventCallback);
+ }
+
+ private void runTether(final TestTetheringResult result) throws Exception {
+ when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
+ mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
+ verify(mTethering).isTetheringSupported();
+ verify(mTethering).tether(TEST_IFACE_NAME);
+ result.assertResult(TETHER_ERROR_NO_ERROR);
}
@Test
public void testTether() throws Exception {
- when(mTethering.tether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
- final TestTetheringResult result = new TestTetheringResult();
- mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
+ runAsNoPermission((result) -> {
+ mTetheringConnector.tether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runTether(result);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runTether(result);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runUnTether(final TestTetheringResult result) throws Exception {
+ when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
+ mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
verify(mTethering).isTetheringSupported();
- verify(mTethering).tether(TEST_IFACE_NAME);
- verifyNoMoreInteractions(mTethering);
+ verify(mTethering).untether(TEST_IFACE_NAME);
result.assertResult(TETHER_ERROR_NO_ERROR);
}
@Test
public void testUntether() throws Exception {
- when(mTethering.untether(TEST_IFACE_NAME)).thenReturn(TETHER_ERROR_NO_ERROR);
- final TestTetheringResult result = new TestTetheringResult();
- mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
+ runAsNoPermission((result) -> {
+ mTetheringConnector.untether(TEST_IFACE_NAME, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runUnTether(result);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runUnTether(result);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runSetUsbTethering(final TestTetheringResult result) throws Exception {
+ when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
+ mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
+ TEST_ATTRIBUTION_TAG, result);
verify(mTethering).isTetheringSupported();
- verify(mTethering).untether(TEST_IFACE_NAME);
- verifyNoMoreInteractions(mTethering);
+ verify(mTethering).setUsbTethering(true /* enable */);
result.assertResult(TETHER_ERROR_NO_ERROR);
}
@Test
public void testSetUsbTethering() throws Exception {
- when(mTethering.setUsbTethering(true /* enable */)).thenReturn(TETHER_ERROR_NO_ERROR);
- final TestTetheringResult result = new TestTetheringResult();
- mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
- TEST_ATTRIBUTION_TAG, result);
+ runAsNoPermission((result) -> {
+ mTetheringConnector.setUsbTethering(true /* enable */, TEST_CALLER_PKG,
+ TEST_ATTRIBUTION_TAG, result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runSetUsbTethering(result);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runSetUsbTethering(result);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ }
+
+ private void runStartTethering(final TestTetheringResult result,
+ final TetheringRequestParcel request) throws Exception {
+ mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
verify(mTethering).isTetheringSupported();
- verify(mTethering).setUsbTethering(true /* enable */);
- verifyNoMoreInteractions(mTethering);
- result.assertResult(TETHER_ERROR_NO_ERROR);
+ verify(mTethering).startTethering(eq(request), eq(result));
}
@Test
public void testStartTethering() throws Exception {
- final TestTetheringResult result = new TestTetheringResult();
final TetheringRequestParcel request = new TetheringRequestParcel();
request.tetheringType = TETHERING_WIFI;
- mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- verify(mTethering).startTethering(eq(request), eq(result));
- verifyNoMoreInteractions(mTethering);
+
+ runAsNoPermission((result) -> {
+ mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runStartTethering(result, request);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runStartTethering(result, request);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
}
@Test
- public void testStopTethering() throws Exception {
- final TestTetheringResult result = new TestTetheringResult();
- mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
- result);
+ public void testStartTetheringWithExemptFromEntitlementCheck() throws Exception {
+ final TetheringRequestParcel request = new TetheringRequestParcel();
+ request.tetheringType = TETHERING_WIFI;
+ request.exemptFromEntitlementCheck = true;
+
+ runAsTetherPrivileged((result) -> {
+ runStartTethering(result, request);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ mTetheringConnector.startTethering(request, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runStopTethering(final TestTetheringResult result) throws Exception {
+ mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG,
+ TEST_ATTRIBUTION_TAG, result);
verify(mTethering).isTetheringSupported();
verify(mTethering).stopTethering(TETHERING_WIFI);
- verifyNoMoreInteractions(mTethering);
result.assertResult(TETHER_ERROR_NO_ERROR);
}
@Test
- public void testRequestLatestTetheringEntitlementResult() throws Exception {
- final ResultReceiver result = new ResultReceiver(null);
+ public void testStopTethering() throws Exception {
+ runAsNoPermission((result) -> {
+ mTetheringConnector.stopTethering(TETHERING_WIFI, TEST_CALLER_PKG,
+ TEST_ATTRIBUTION_TAG, result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runStopTethering(result);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runStopTethering(result);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runRequestLatestTetheringEntitlementResult() throws Exception {
+ final MyResultReceiver result = new MyResultReceiver(null);
mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
verify(mTethering).isTetheringSupported();
verify(mTethering).requestLatestTetheringEntitlementResult(eq(TETHERING_WIFI),
eq(result), eq(true) /* showEntitlementUi */);
+ }
+
+ @Test
+ public void testRequestLatestTetheringEntitlementResult() throws Exception {
+ // Run as no permission.
+ final MyResultReceiver result = new MyResultReceiver(null);
+ mTetheringConnector.requestLatestTetheringEntitlementResult(TETHERING_WIFI, result,
+ true /* showEntitlementUi */, TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
verifyNoMoreInteractions(mTethering);
+
+ runAsTetherPrivileged((none) -> {
+ runRequestLatestTetheringEntitlementResult();
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((none) -> {
+ runRequestLatestTetheringEntitlementResult();
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runRegisterTetheringEventCallback() throws Exception {
+ mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback,
+ TEST_CALLER_PKG);
+ verify(mTethering).registerTetheringEventCallback(eq(mITetheringEventCallback));
}
@Test
public void testRegisterTetheringEventCallback() throws Exception {
- mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback,
+ runAsNoPermission((result) -> {
+ mTetheringConnector.registerTetheringEventCallback(mITetheringEventCallback,
+ TEST_CALLER_PKG);
+ verify(mITetheringEventCallback).onCallbackStopped(
+ TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((none) -> {
+ runRegisterTetheringEventCallback();
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsAccessNetworkState((none) -> {
+ runRegisterTetheringEventCallback();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runUnregisterTetheringEventCallback() throws Exception {
+ mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback,
TEST_CALLER_PKG);
- verify(mTethering).registerTetheringEventCallback(eq(mITetheringEventCallback));
- verifyNoMoreInteractions(mTethering);
+ verify(mTethering).unregisterTetheringEventCallback(eq(mITetheringEventCallback));
}
@Test
public void testUnregisterTetheringEventCallback() throws Exception {
- mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback,
- TEST_CALLER_PKG);
- verify(mTethering).unregisterTetheringEventCallback(
- eq(mITetheringEventCallback));
- verifyNoMoreInteractions(mTethering);
+ runAsNoPermission((result) -> {
+ mTetheringConnector.unregisterTetheringEventCallback(mITetheringEventCallback,
+ TEST_CALLER_PKG);
+ verify(mITetheringEventCallback).onCallbackStopped(
+ TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((none) -> {
+ runUnregisterTetheringEventCallback();
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsAccessNetworkState((none) -> {
+ runUnregisterTetheringEventCallback();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runStopAllTethering(final TestTetheringResult result) throws Exception {
+ mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
+ verify(mTethering).isTetheringSupported();
+ verify(mTethering).untetherAll();
+ result.assertResult(TETHER_ERROR_NO_ERROR);
}
@Test
public void testStopAllTethering() throws Exception {
- final TestTetheringResult result = new TestTetheringResult();
- mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
+ runAsNoPermission((result) -> {
+ mTetheringConnector.stopAllTethering(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runStopAllTethering(result);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runStopAllTethering(result);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
+ }
+
+ private void runIsTetheringSupported(final TestTetheringResult result) throws Exception {
+ mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
verify(mTethering).isTetheringSupported();
- verify(mTethering).untetherAll();
- verifyNoMoreInteractions(mTethering);
result.assertResult(TETHER_ERROR_NO_ERROR);
}
@Test
public void testIsTetheringSupported() throws Exception {
- final TestTetheringResult result = new TestTetheringResult();
- mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG, result);
- verify(mTethering).isTetheringSupported();
- verifyNoMoreInteractions(mTethering);
- result.assertResult(TETHER_ERROR_NO_ERROR);
+ runAsNoPermission((result) -> {
+ mTetheringConnector.isTetheringSupported(TEST_CALLER_PKG, TEST_ATTRIBUTION_TAG,
+ result);
+ verify(mTethering).isTetherProvisioningRequired();
+ result.assertResult(TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsTetherPrivileged((result) -> {
+ runIsTetheringSupported(result);
+ verifyNoMoreInteractionsForTethering();
+ });
+
+ runAsWriteSettings((result) -> {
+ runIsTetheringSupported(result);
+ verify(mTethering).isTetherProvisioningRequired();
+ verifyNoMoreInteractionsForTethering();
+ });
}
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index d9a5349..74fddb2 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -28,7 +28,7 @@
"android.hardware.power-V1.0-java",
"android.hardware.tv.cec-V1.0-java",
"android.hardware.vibrator-java",
- "android.net.ipsec.ike.stubs.module_libs_api",
+ "android.net.ipsec.ike.stubs.module_lib",
"app-compat-annotations",
"framework-tethering-stubs-module_libs_api",
],
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 635f184..6e026ab 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3079,23 +3079,7 @@
@Override
public void notifyDataStallSuspected(DataStallReportParcelable p) {
- final PersistableBundle extras = new PersistableBundle();
- switch (p.detectionMethod) {
- case DETECTION_METHOD_DNS_EVENTS:
- extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
- break;
- case DETECTION_METHOD_TCP_METRICS:
- extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
- extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
- p.tcpMetricsCollectionPeriodMillis);
- break;
- default:
- log("Unknown data stall detection method, ignoring: " + p.detectionMethod);
- return;
- }
-
- proxyDataStallToConnectivityDiagnosticsHandler(
- p.detectionMethod, mNetId, p.timestampMillis, extras);
+ ConnectivityService.this.notifyDataStallSuspected(p, mNetId);
}
@Override
@@ -3109,11 +3093,25 @@
}
}
- private void proxyDataStallToConnectivityDiagnosticsHandler(int detectionMethod, int netId,
- long timestampMillis, @NonNull PersistableBundle extras) {
+ private void notifyDataStallSuspected(DataStallReportParcelable p, int netId) {
+ log("Data stall detected with methods: " + p.detectionMethod);
+
+ final PersistableBundle extras = new PersistableBundle();
+ int detectionMethod = 0;
+ if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
+ extras.putInt(KEY_DNS_CONSECUTIVE_TIMEOUTS, p.dnsConsecutiveTimeouts);
+ detectionMethod |= DETECTION_METHOD_DNS_EVENTS;
+ }
+ if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
+ extras.putInt(KEY_TCP_PACKET_FAIL_RATE, p.tcpPacketFailRate);
+ extras.putInt(KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS,
+ p.tcpMetricsCollectionPeriodMillis);
+ detectionMethod |= DETECTION_METHOD_TCP_METRICS;
+ }
+
final Message msg = mConnectivityDiagnosticsHandler.obtainMessage(
- ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED,
- detectionMethod, netId, timestampMillis);
+ ConnectivityDiagnosticsHandler.EVENT_DATA_STALL_SUSPECTED, detectionMethod, netId,
+ p.timestampMillis);
msg.setData(new Bundle(extras));
// NetworkStateTrackerHandler currently doesn't take any actions based on data
@@ -3122,6 +3120,10 @@
mConnectivityDiagnosticsHandler.sendMessage(msg);
}
+ private boolean hasDataStallDetectionMethod(DataStallReportParcelable p, int detectionMethod) {
+ return (p.detectionMethod & detectionMethod) != 0;
+ }
+
private boolean networkRequiresPrivateDnsValidation(NetworkAgentInfo nai) {
return isPrivateDnsValidationRequired(nai.networkCapabilities);
}
@@ -8181,7 +8183,19 @@
+ "creators");
}
- proxyDataStallToConnectivityDiagnosticsHandler(
- detectionMethod, network.netId, timestampMillis, extras);
+ final DataStallReportParcelable p = new DataStallReportParcelable();
+ p.timestampMillis = timestampMillis;
+ p.detectionMethod = detectionMethod;
+
+ if (hasDataStallDetectionMethod(p, DETECTION_METHOD_DNS_EVENTS)) {
+ p.dnsConsecutiveTimeouts = extras.getInt(KEY_DNS_CONSECUTIVE_TIMEOUTS);
+ }
+ if (hasDataStallDetectionMethod(p, DETECTION_METHOD_TCP_METRICS)) {
+ p.tcpPacketFailRate = extras.getInt(KEY_TCP_PACKET_FAIL_RATE);
+ p.tcpMetricsCollectionPeriodMillis = extras.getInt(
+ KEY_TCP_METRICS_COLLECTION_PERIOD_MILLIS);
+ }
+
+ notifyDataStallSuspected(p, network.netId);
}
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 341a88d..4bb17a2 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -33,9 +33,9 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.os.Binder;
import android.os.Environment;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.sysprop.ApexProperties;
import android.util.Slog;
@@ -73,12 +73,7 @@
*/
static ApexManager create(Context systemContext) {
if (ApexProperties.updatable().orElse(false)) {
- try {
- return new ApexManagerImpl(systemContext, IApexService.Stub.asInterface(
- ServiceManager.getServiceOrThrow("apexservice")));
- } catch (ServiceManager.ServiceNotFoundException e) {
- throw new IllegalStateException("Required service apexservice not available");
- }
+ return new ApexManagerImpl(systemContext);
} else {
return new ApexManagerFlattenedApex();
}
@@ -247,8 +242,7 @@
* APEX packages.
*/
@VisibleForTesting
- static class ApexManagerImpl extends ApexManager {
- private final IApexService mApexService;
+ protected static class ApexManagerImpl extends ApexManager {
private final Context mContext;
private final Object mLock = new Object();
/**
@@ -261,9 +255,8 @@
@GuardedBy("mLock")
private List<PackageInfo> mAllPackagesCache;
- ApexManagerImpl(Context context, IApexService apexService) {
+ ApexManagerImpl(Context context) {
mContext = context;
- mApexService = apexService;
}
/**
@@ -286,10 +279,23 @@
return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
+ /**
+ * Retrieve the service from ServiceManager. If the service is not running, it will be
+ * started, and this function will block until it is ready.
+ */
+ @VisibleForTesting
+ protected IApexService waitForApexService() {
+ try {
+ return IApexService.Stub.asInterface(Binder.waitForService("apexservice"));
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Required service apexservice not available");
+ }
+ }
+
@Override
List<ActiveApexInfo> getActiveApexInfos() {
try {
- return Arrays.stream(mApexService.getActivePackages())
+ return Arrays.stream(waitForApexService().getActivePackages())
.map(apexInfo -> new ActiveApexInfo(
new File(
Environment.getApexDirectory() + File.separator
@@ -324,7 +330,7 @@
mAllPackagesCache = new ArrayList<>();
HashSet<String> activePackagesSet = new HashSet<>();
HashSet<String> factoryPackagesSet = new HashSet<>();
- final ApexInfo[] allPkgs = mApexService.getAllPackages();
+ final ApexInfo[] allPkgs = waitForApexService().getAllPackages();
for (ApexInfo ai : allPkgs) {
// If the device is using flattened APEX, don't report any APEX
// packages since they won't be managed or updated by PackageManager.
@@ -431,7 +437,8 @@
@Override
@Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
try {
- ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
+ ApexSessionInfo apexSessionInfo =
+ waitForApexService().getStagedSessionInfo(sessionId);
if (apexSessionInfo.isUnknown) {
return null;
}
@@ -450,7 +457,7 @@
ApexSessionParams params = new ApexSessionParams();
params.sessionId = sessionId;
params.childSessionIds = childSessionIds;
- mApexService.submitStagedSession(params, apexInfoList);
+ waitForApexService().submitStagedSession(params, apexInfoList);
return apexInfoList;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
@@ -465,7 +472,7 @@
@Override
void markStagedSessionReady(int sessionId) throws PackageManagerException {
try {
- mApexService.markStagedSessionReady(sessionId);
+ waitForApexService().markStagedSessionReady(sessionId);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
throw new RuntimeException(re);
@@ -479,7 +486,7 @@
@Override
void markStagedSessionSuccessful(int sessionId) {
try {
- mApexService.markStagedSessionSuccessful(sessionId);
+ waitForApexService().markStagedSessionSuccessful(sessionId);
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
throw new RuntimeException(re);
@@ -498,7 +505,7 @@
@Override
boolean revertActiveSessions() {
try {
- mApexService.revertActiveSessions();
+ waitForApexService().revertActiveSessions();
return true;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
@@ -512,7 +519,7 @@
@Override
boolean abortStagedSession(int sessionId) throws PackageManagerException {
try {
- mApexService.abortStagedSession(sessionId);
+ waitForApexService().abortStagedSession(sessionId);
return true;
} catch (RemoteException re) {
Slog.e(TAG, "Unable to contact apexservice", re);
@@ -527,7 +534,7 @@
@Override
boolean uninstallApex(String apexPackagePath) {
try {
- mApexService.unstagePackages(Collections.singletonList(apexPackagePath));
+ waitForApexService().unstagePackages(Collections.singletonList(apexPackagePath));
return true;
} catch (Exception e) {
return false;
@@ -578,7 +585,7 @@
ipw.increaseIndent();
ipw.println("APEX session state:");
ipw.increaseIndent();
- final ApexSessionInfo[] sessions = mApexService.getSessions();
+ final ApexSessionInfo[] sessions = waitForApexService().getSessions();
for (ApexSessionInfo si : sessions) {
ipw.println("Session ID: " + si.sessionId);
ipw.increaseIndent();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 72fc189..9d56263 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -28,12 +28,14 @@
import android.graphics.Bitmap.Config;
import android.os.Process;
import android.os.SystemClock;
+import android.os.UserManagerInternal;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.AtomicFile;
+import com.android.server.LocalServices;
import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
import java.io.File;
@@ -73,6 +75,7 @@
private boolean mStarted;
private final Object mLock = new Object();
private final DirectoryResolver mDirectoryResolver;
+ private final UserManagerInternal mUserManagerInternal;
private final float mReducedScale;
/**
@@ -84,6 +87,7 @@
TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
mDirectoryResolver = resolver;
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
if (service.mLowRamTaskSnapshotsAndRecents) {
// Use very low res snapshots if we are using Go version of recents.
mReducedScale = LOW_RAM_RECENTS_REDUCED_SCALE;
@@ -172,7 +176,7 @@
return;
}
}
- SystemClock.sleep(100);
+ SystemClock.sleep(DELAY_MS);
}
}
@@ -218,7 +222,7 @@
private boolean createDirectory(int userId) {
final File dir = getDirectory(userId);
- return dir.exists() || dir.mkdirs();
+ return dir.exists() || dir.mkdir();
}
private void deleteSnapshot(int taskId, int userId) {
@@ -243,18 +247,26 @@
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
while (true) {
WriteQueueItem next;
+ boolean isReadyToWrite = false;
synchronized (mLock) {
if (mPaused) {
next = null;
} else {
next = mWriteQueue.poll();
if (next != null) {
- next.onDequeuedLocked();
+ if (next.isReady()) {
+ isReadyToWrite = true;
+ next.onDequeuedLocked();
+ } else {
+ mWriteQueue.addLast(next);
+ }
}
}
}
if (next != null) {
- next.write();
+ if (isReadyToWrite) {
+ next.write();
+ }
SystemClock.sleep(DELAY_MS);
}
synchronized (mLock) {
@@ -274,6 +286,13 @@
};
private abstract class WriteQueueItem {
+ /**
+ * @return {@code true} if item is ready to have {@link WriteQueueItem#write} called
+ */
+ boolean isReady() {
+ return true;
+ }
+
abstract void write();
/**
@@ -313,6 +332,11 @@
}
@Override
+ boolean isReady() {
+ return mUserManagerInternal.isUserUnlocked(mUserId);
+ }
+
+ @Override
void write() {
if (!createDirectory(mUserId)) {
Slog.e(TAG, "Unable to create snapshot directory for user dir="
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e1f8544..404863a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7717,14 +7717,19 @@
@Override
public void syncInputTransactions() {
- waitForAnimationsToComplete();
+ long token = Binder.clearCallingIdentity();
+ try {
+ waitForAnimationsToComplete();
- synchronized (mGlobalLock) {
- mWindowPlacerLocked.performSurfacePlacementIfScheduled();
- mRoot.forAllDisplays(displayContent ->
+ synchronized (mGlobalLock) {
+ mWindowPlacerLocked.performSurfacePlacementIfScheduled();
+ mRoot.forAllDisplays(displayContent ->
displayContent.getInputMonitor().updateInputWindowsImmediately());
+ }
+ new SurfaceControl.Transaction().syncInputWindows().apply(true);
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
- new SurfaceControl.Transaction().syncInputWindows().apply(true);
}
private void waitForAnimationsToComplete() {
diff --git a/services/core/jni/com_android_server_AlarmManagerService.cpp b/services/core/jni/com_android_server_AlarmManagerService.cpp
index e79612f..a99c0a3 100644
--- a/services/core/jni/com_android_server_AlarmManagerService.cpp
+++ b/services/core/jni/com_android_server_AlarmManagerService.cpp
@@ -40,6 +40,7 @@
#include <linux/rtc.h>
#include <array>
+#include <limits>
#include <memory>
namespace android {
@@ -213,22 +214,20 @@
static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
{
AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
- struct timeval tv;
- int ret;
- if (millis <= 0 || millis / 1000LL >= INT_MAX) {
+ if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) {
return -1;
}
- tv.tv_sec = (time_t) (millis / 1000LL);
- tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);
+ struct timeval tv;
+ tv.tv_sec = (millis / 1000LL);
+ tv.tv_usec = ((millis % 1000LL) * 1000LL);
- ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);
+ ALOGD("Setting time of day to sec=%ld", tv.tv_sec);
- ret = impl->setTime(&tv);
-
- if(ret < 0) {
- ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));
+ int ret = impl->setTime(&tv);
+ if (ret < 0) {
+ ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno));
ret = -1;
}
return ret;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 30d1035..c086718 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -21,8 +21,10 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -68,7 +70,9 @@
@Before
public void setUp() throws RemoteException {
mContext = InstrumentationRegistry.getInstrumentation().getContext();
- mApexManager = new ApexManager.ApexManagerImpl(mContext, mApexService);
+ ApexManager.ApexManagerImpl managerImpl = spy(new ApexManager.ApexManagerImpl(mContext));
+ doReturn(mApexService).when(managerImpl).waitForApexService();
+ mApexManager = managerImpl;
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index e004cd3..f25110f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -23,6 +23,9 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.app.ActivityManager.TaskSnapshot;
import android.content.ComponentName;
import android.graphics.Canvas;
@@ -32,9 +35,14 @@
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.UserManager;
+import android.os.UserManagerInternal;
+
+import com.android.server.LocalServices;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import java.io.File;
@@ -50,10 +58,26 @@
TaskSnapshotLoader mLoader;
int mTestUserId;
+ @BeforeClass
+ public static void setUpOnce() {
+ final UserManagerInternal userManager = mock(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, userManager);
+ }
+
+ @AfterClass
+ public static void tearDownOnce() {
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ }
+
@Before
public void setUp() {
final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
mTestUserId = um.getUserHandle();
+
+ final UserManagerInternal userManagerInternal =
+ LocalServices.getService(UserManagerInternal.class);
+ when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true);
+
mPersister = new TaskSnapshotPersister(mWm, userId -> FILES_DIR);
mLoader = new TaskSnapshotLoader(mPersister);
mPersister.start();
diff --git a/telephony/java/android/telephony/PinResult.java b/telephony/java/android/telephony/PinResult.java
index 68c9d99..d9b5de5 100644
--- a/telephony/java/android/telephony/PinResult.java
+++ b/telephony/java/android/telephony/PinResult.java
@@ -37,6 +37,7 @@
PIN_RESULT_TYPE_SUCCESS,
PIN_RESULT_TYPE_INCORRECT,
PIN_RESULT_TYPE_FAILURE,
+ PIN_RESULT_TYPE_ABORTED,
})
public @interface PinResultType {}
@@ -55,6 +56,11 @@
*/
public static final int PIN_RESULT_TYPE_FAILURE = PhoneConstants.PIN_GENERAL_FAILURE;
+ /**
+ * Indicates that the pin attempt was aborted.
+ */
+ public static final int PIN_RESULT_TYPE_ABORTED = PhoneConstants.PIN_OPERATION_ABORTED;
+
private static final PinResult sFailedResult =
new PinResult(PinResult.PIN_RESULT_TYPE_FAILURE, -1);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index e57402d..7d1398b 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -10314,7 +10314,7 @@
* <p>To recognize a carrier (including MVNO) as a first-class identity, Android assigns each
* carrier with a canonical integer a.k.a. carrier id. The carrier ID is an Android
* platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in
- * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+ * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
*
* <p>Apps which have carrier-specific configurations or business logic can use the carrier id
* as an Android platform-wide identifier for carriers.
@@ -10376,7 +10376,7 @@
*
* <p>For carriers without fine-grained specific carrier ids, return {@link #getSimCarrierId()}
* <p>Specific carrier ids are defined in the same way as carrier id
- * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+ * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
* except each with a "parent" id linking to its top-level carrier id.
*
* @return Returns fine-grained carrier id of the current subscription.
@@ -10425,7 +10425,7 @@
* This is used for fallback when configurations/logic for exact carrier id
* {@link #getSimCarrierId()} are not found.
*
- * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+ * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
* can be updated out-of-band, its possible a MVNO (Mobile Virtual Network Operator) carrier
* was not fully recognized and assigned to its MNO (Mobile Network Operator) carrier id
* by default. After carrier id table update, a new carrier id was assigned. If apps don't
@@ -10452,7 +10452,7 @@
* used for fallback when configurations/logic for exact carrier id {@link #getSimCarrierId()}
* are not found.
*
- * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
+ * Android carrier id table <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb">here</a>
* can be updated out-of-band, its possible a MVNO (Mobile Virtual Network Operator) carrier
* was not fully recognized and assigned to its MNO (Mobile Network Operator) carrier id
* by default. After carrier id table update, a new carrier id was assigned. If apps don't
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 6eea88f..db9fdf5 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -111,6 +111,7 @@
public static final int PIN_RESULT_SUCCESS = 0;
public static final int PIN_PASSWORD_INCORRECT = 1;
public static final int PIN_GENERAL_FAILURE = 2;
+ public static final int PIN_OPERATION_ABORTED = 3;
/**
* Return codes for <code>enableApnType()</code>
diff --git a/tests/GamePerformance/Android.bp b/tests/GamePerformance/Android.bp
new file mode 100644
index 0000000..648fd81
--- /dev/null
+++ b/tests/GamePerformance/Android.bp
@@ -0,0 +1,32 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+ name: "GamePerformance",
+ // Don't include this package in any target
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+ srcs: ["src/**/*.java"],
+ static_libs: ["android-support-test"],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/GamePerformance/Android.mk b/tests/GamePerformance/Android.mk
deleted file mode 100644
index 58654de..0000000
--- a/tests/GamePerformance/Android.mk
+++ /dev/null
@@ -1,39 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
-
-LOCAL_JAVA_LIBRARIES := android.test.base android.test.runner
-
-LOCAL_PACKAGE_NAME := GamePerformance
-
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-
-include $(BUILD_PACKAGE)
diff --git a/tests/NullHomeTest/Android.bp b/tests/NullHomeTest/Android.bp
new file mode 100644
index 0000000..99248bf
--- /dev/null
+++ b/tests/NullHomeTest/Android.bp
@@ -0,0 +1,22 @@
+// Copyright 2020 Google Inc. All Rights Reserved.
+//
+// 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.
+
+android_test {
+ name: "NullHomeTest",
+ srcs: ["src/**/*.java"],
+ certificate: "platform",
+ platform_apis: true,
+ static_libs: ["android-support-test"],
+ test_suites: ["device-tests"],
+}
diff --git a/tests/NullHomeTest/AndroidManifest.xml b/tests/NullHomeTest/AndroidManifest.xml
new file mode 100644
index 0000000..dc6402e
--- /dev/null
+++ b/tests/NullHomeTest/AndroidManifest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.test.nullhome"
+ android:sharedUserId="android.uid.system" >
+
+ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />
+
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.test.nullhome"
+ android:label="Check if no null Home exists/is enabled" />
+
+ <application android:label="Null Home Test">
+ <uses-library android:name="android.test.runner" />
+ </application>
+</manifest>
diff --git a/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java b/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java
new file mode 100644
index 0000000..1d77cdc5
--- /dev/null
+++ b/tests/NullHomeTest/src/com/android/test/nullhome/NullHomeTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.test.nullhome;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * Check if NullHome/SystemUserHome activity does not exist/is disabled.
+ *
+ * SystemUserHome is only enabled in bootable CSI (csi_x86, csi_arm64)
+ * products and should not be enabled in other products.
+ *
+ * Shell's NullHome is empty and caused issues in sevaral manual GUI tests
+ * that try to select/use it, and should be removed.
+ *
+ * Settings' FallbackHome is fine because it's specially handled by Settings.
+ *
+ */
+
+@RunWith(JUnit4.class)
+public class NullHomeTest {
+ private static final String TAG = "NullHomeTest";
+ private Context mContext;
+ private PackageManager mPm;
+
+ @Before
+ public void before() {
+ Log.d(TAG, "beforeClass()");
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ mPm = mContext.getPackageManager();
+ }
+
+ @Test
+ public void checkNullHome() {
+ final List<ResolveInfo> homeActivities = new ArrayList<>();
+
+ mPm.getHomeActivities(homeActivities);
+ for (ResolveInfo activity : homeActivities) {
+ Log.d(TAG, "Home activity: " + activity.activityInfo.packageName);
+ Assert.assertNotEquals(activity.activityInfo.packageName,
+ "com.android.internal.app.SystemUserHomeActivity");
+ Assert.assertNotEquals(activity.activityInfo.packageName,
+ "com.android.shell");
+ }
+ }
+}
diff --git a/tests/ProtoInputStreamTests/Android.bp b/tests/ProtoInputStreamTests/Android.bp
new file mode 100644
index 0000000..ecc40566
--- /dev/null
+++ b/tests/ProtoInputStreamTests/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2019 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.
+
+android_test {
+ name: "ProtoInputStreamTests",
+ proto: {
+ type: "nano",
+ },
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.proto",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+ libs: ["android.test.runner"],
+ static_libs: [
+ "androidx.test.rules",
+ "frameworks-base-testutils",
+ "mockito-target-minus-junit4",
+ ],
+}
diff --git a/tests/ProtoInputStreamTests/Android.mk b/tests/ProtoInputStreamTests/Android.mk
deleted file mode 100644
index eb747cc..0000000
--- a/tests/ProtoInputStreamTests/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2019 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)
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := ProtoInputStreamTests
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_MODULE_TAGS := tests optional
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src) \
- $(call all-proto-files-under, src)
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- frameworks-base-testutils \
- mockito-target-minus-junit4
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/net/integration/AndroidManifest.xml b/tests/net/integration/AndroidManifest.xml
index 09c0e48..f5a4234 100644
--- a/tests/net/integration/AndroidManifest.xml
+++ b/tests/net/integration/AndroidManifest.xml
@@ -16,50 +16,55 @@
* limitations under the License.
*/
-->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.server.net.integrationtests">
+ package="com.android.server.net.integrationtests">
<!-- For ConnectivityService registerReceiverAsUser (receiving broadcasts) -->
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
+ <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<!-- PermissionMonitor sets network permissions for each user -->
- <uses-permission android:name="android.permission.MANAGE_USERS" />
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
<!-- ConnectivityService sends notifications to BatteryStats -->
- <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
+ <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/>
<!-- Reading network status -->
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.NETWORK_FACTORY" />
- <uses-permission android:name="android.permission.NETWORK_STACK" />
- <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" />
- <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.NETWORK_FACTORY"/>
+ <!-- Obtain LinkProperties callbacks with sensitive fields -->
+ <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
+ <uses-permission android:name="android.permission.NETWORK_STACK"/>
+ <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY"/>
+ <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<!-- Reading DeviceConfig flags -->
- <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
+ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/>
<application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
+ <uses-library android:name="android.test.runner"/>
<!-- This manifest is merged with the base manifest of the real NetworkStack app.
- Remove the NetworkStackService from the base (real) manifest, and replace with a test
- service that responds to the same intent -->
+ Remove the NetworkStackService from the base (real) manifest, and replace with a test
+ service that responds to the same intent -->
<service android:name=".TestNetworkStackService"
- android:process="com.android.server.net.integrationtests.testnetworkstack">
+ android:process="com.android.server.net.integrationtests.testnetworkstack"
+ android:exported="true">
<intent-filter>
<action android:name="android.net.INetworkStackConnector.Test"/>
</intent-filter>
</service>
<service android:name=".NetworkStackInstrumentationService"
- android:process="com.android.server.net.integrationtests.testnetworkstack">
+ android:process="com.android.server.net.integrationtests.testnetworkstack"
+ android:exported="true">
<intent-filter>
<action android:name=".INetworkStackInstrumentation"/>
</intent-filter>
</service>
<service android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService"
- android:process="com.android.server.net.integrationtests.testnetworkstack"
- android:permission="android.permission.BIND_JOB_SERVICE"/>
+ android:process="com.android.server.net.integrationtests.testnetworkstack"
+ android:permission="android.permission.BIND_JOB_SERVICE"/>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.android.server.net.integrationtests"
- android:label="Frameworks Net Integration Tests" />
+ android:targetPackage="com.android.server.net.integrationtests"
+ android:label="Frameworks Net Integration Tests"/>
</manifest>
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index c4801aa..bc069e1 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -28,10 +28,13 @@
import android.net.INetworkPolicyManager
import android.net.INetworkStatsService
import android.net.LinkProperties
+import android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
+import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkRequest
import android.net.TestNetworkStackClient
+import android.net.Uri
import android.net.metrics.IpConnectivityLog
import android.os.ConditionVariable
import android.os.IBinder
@@ -64,6 +67,8 @@
import org.mockito.MockitoAnnotations
import org.mockito.Spy
import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+import kotlin.test.assertNotNull
import kotlin.test.assertTrue
import kotlin.test.fail
@@ -110,6 +115,10 @@
private val bindingCondition = ConditionVariable(false)
private val realContext get() = InstrumentationRegistry.getInstrumentation().context
+ private val httpProbeUrl get() =
+ realContext.getResources().getString(R.string.config_captive_portal_http_url)
+ private val httpsProbeUrl get() =
+ realContext.getResources().getString(R.string.config_captive_portal_https_url)
private class InstrumentationServiceConnection : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
@@ -188,12 +197,8 @@
val testCallback = TestableNetworkCallback()
cm.registerNetworkCallback(request, testCallback)
- nsInstrumentation.addHttpResponse(HttpResponse(
- "http://test.android.com",
- responseCode = 204, contentLength = 42, redirectUrl = null))
- nsInstrumentation.addHttpResponse(HttpResponse(
- "https://secure.test.android.com",
- responseCode = 204, contentLength = 42, redirectUrl = null))
+ nsInstrumentation.addHttpResponse(HttpResponse(httpProbeUrl, responseCode = 204))
+ nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204))
val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), context)
networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS)
@@ -204,4 +209,52 @@
testCallback.expectAvailableThenValidatedCallbacks(na.network, TEST_TIMEOUT_MS)
assertEquals(2, nsInstrumentation.getRequestUrls().size)
}
+
+ @Test
+ fun testCapportApi() {
+ val request = NetworkRequest.Builder()
+ .clearCapabilities()
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build()
+ val testCb = TestableNetworkCallback()
+ val apiUrl = "https://capport.android.com"
+
+ cm.registerNetworkCallback(request, testCb)
+ nsInstrumentation.addHttpResponse(HttpResponse(
+ apiUrl,
+ """
+ |{
+ | "captive": true,
+ | "user-portal-url": "https://login.capport.android.com",
+ | "venue-info-url": "https://venueinfo.capport.android.com"
+ |}
+ """.trimMargin()))
+
+ // Tests will fail if a non-mocked query is received: mock the HTTPS probe, but not the
+ // HTTP probe as it should not be sent.
+ // Even if the HTTPS probe succeeds, a portal should be detected as the API takes precedence
+ // in that case.
+ nsInstrumentation.addHttpResponse(HttpResponse(httpsProbeUrl, responseCode = 204))
+
+ val lp = LinkProperties()
+ lp.captivePortalApiUrl = Uri.parse(apiUrl)
+ val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, lp, context)
+ networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS)
+
+ na.addCapability(NET_CAPABILITY_INTERNET)
+ na.connect()
+
+ testCb.expectAvailableCallbacks(na.network, validated = false, tmt = TEST_TIMEOUT_MS)
+
+ val capportData = testCb.expectLinkPropertiesThat(na, TEST_TIMEOUT_MS) {
+ it.captivePortalData != null
+ }.lp.captivePortalData
+ assertNotNull(capportData)
+ assertTrue(capportData.isCaptive)
+ assertEquals(Uri.parse("https://login.capport.android.com"), capportData.userPortalUrl)
+ assertEquals(Uri.parse("https://venueinfo.capport.android.com"), capportData.venueInfoUrl)
+
+ val nc = testCb.expectCapabilitiesWith(NET_CAPABILITY_CAPTIVE_PORTAL, na, TEST_TIMEOUT_MS)
+ assertFalse(nc.hasCapability(NET_CAPABILITY_VALIDATED))
+ }
}
\ No newline at end of file
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt b/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt
index 45073d8..e206313 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/HttpResponse.kt
@@ -22,16 +22,21 @@
data class HttpResponse(
val requestUrl: String,
val responseCode: Int,
- val contentLength: Long,
- val redirectUrl: String?
+ val content: String = "",
+ val redirectUrl: String? = null
) : Parcelable {
- constructor(p: Parcel): this(p.readString(), p.readInt(), p.readLong(), p.readString())
+ constructor(p: Parcel): this(p.readString(), p.readInt(), p.readString(), p.readString())
+ constructor(requestUrl: String, contentBody: String): this(
+ requestUrl,
+ responseCode = 200,
+ content = contentBody,
+ redirectUrl = null)
override fun writeToParcel(dest: Parcel, flags: Int) {
with(dest) {
writeString(requestUrl)
writeInt(responseCode)
- writeLong(contentLength)
+ writeString(content)
writeString(redirectUrl)
}
}
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt
index 4827d29..e807952 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/NetworkStackInstrumentationService.kt
@@ -65,6 +65,9 @@
*
* <p>For any subsequent HTTP/HTTPS query, the first response with a matching URL will be
* used to mock the query response.
+ *
+ * <p>All requests that are expected to be sent must have a mock response: if an unexpected
+ * request is seen, the test will fail.
*/
override fun addHttpResponse(response: HttpResponse) {
httpResponses.getValue(response.requestUrl).add(response)
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index 8c2de40..a44ad1e 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
@@ -33,9 +33,11 @@
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
+import java.io.ByteArrayInputStream
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLConnection
+import java.nio.charset.StandardCharsets
private const val TEST_NETID = 42
@@ -71,11 +73,13 @@
private inner class TestNetwork(netId: Int) : Network(netId) {
override fun openConnection(url: URL): URLConnection {
val response = InstrumentationConnector.processRequest(url)
+ val responseBytes = response.content.toByteArray(StandardCharsets.UTF_8)
val connection = mock(HttpURLConnection::class.java)
doReturn(response.responseCode).`when`(connection).responseCode
- doReturn(response.contentLength).`when`(connection).contentLengthLong
+ doReturn(responseBytes.size.toLong()).`when`(connection).contentLengthLong
doReturn(response.redirectUrl).`when`(connection).getHeaderField("location")
+ doReturn(ByteArrayInputStream(responseBytes)).`when`(connection).inputStream
return connection
}
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 5e2ef04..065ddd3 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -5494,6 +5494,8 @@
assertFalse(nc.hasTransport(TRANSPORT_WIFI));
// For safety reasons a VPN without underlying networks is considered metered.
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_METERED));
+ // A VPN without underlying networks is not suspended.
+ assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
// Connect cell and use it as an underlying network.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
@@ -6352,12 +6354,36 @@
expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromDns);
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromDns.toString());
- // If the RA prefix reappears, clatd is restarted and prefix discovery is stopped.
+ // If an RA advertises the same prefix that was discovered by DNS, nothing happens: prefix
+ // discovery is not stopped, and there are no callbacks.
+ lp.setNat64Prefix(pref64FromDns);
+ mCellNetworkAgent.sendLinkProperties(lp);
+ callback.assertNoCallback();
+ inOrder.verify(mMockNetd, never()).clatdStop(iface);
+ inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
+ inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
+ inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
+
+ // If the RA is later withdrawn, nothing happens again.
+ lp.setNat64Prefix(null);
+ mCellNetworkAgent.sendLinkProperties(lp);
+ callback.assertNoCallback();
+ inOrder.verify(mMockNetd, never()).clatdStop(iface);
+ inOrder.verify(mMockNetd, never()).clatdStart(eq(iface), anyString());
+ inOrder.verify(mMockDnsResolver, never()).stopPrefix64Discovery(netId);
+ inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
+
+ // If the RA prefix changes, clatd is restarted and prefix discovery is stopped.
lp.setNat64Prefix(pref64FromRa);
mCellNetworkAgent.sendLinkProperties(lp);
expectNat64PrefixChange(callback, mCellNetworkAgent, pref64FromRa);
inOrder.verify(mMockNetd).clatdStop(iface);
inOrder.verify(mMockDnsResolver).stopPrefix64Discovery(netId);
+
+ // Stopping prefix discovery results in a prefix removed notification.
+ mService.mNetdEventCallback.onNat64PrefixEvent(netId, false /* added */,
+ pref64FromDnsStr, 96);
+
inOrder.verify(mMockNetd).clatdStart(iface, pref64FromRa.toString());
inOrder.verify(mMockDnsResolver, never()).startPrefix64Discovery(netId);
diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
index 42d4cf3..a10a3c8 100644
--- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
+++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+// Don't warn about deprecated types anywhere in this test, because LegacyTypeTracker's very reason
+// for existence is to power deprecated APIs. The annotation has to apply to the whole file because
+// otherwise warnings will be generated by the imports of deprecated constants like TYPE_xxx.
+@file:Suppress("DEPRECATION")
+
package com.android.server
import android.net.ConnectivityManager.TYPE_ETHERNET
diff --git a/tests/testables/src/android/testing/TestableLooper.java b/tests/testables/src/android/testing/TestableLooper.java
index 8d99ac71..7218ae3 100644
--- a/tests/testables/src/android/testing/TestableLooper.java
+++ b/tests/testables/src/android/testing/TestableLooper.java
@@ -222,6 +222,10 @@
return sLoopers.get(test);
}
+ public static void remove(Object test) {
+ sLoopers.remove(test);
+ }
+
static class LooperFrameworkMethod extends FrameworkMethod {
private HandlerThread mHandlerThread;
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index e8970d4..7afb000 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1659,10 +1659,8 @@
return 1;
}
- // Determine the package name under which to merge resources.
- if (options_.rename_resources_package) {
- context_->SetCompilationPackage(options_.rename_resources_package.value());
- } else if (Maybe<AppInfo> maybe_app_info =
+ // First extract the package name without modifying it (via --rename-manifest-package).
+ if (Maybe<AppInfo> maybe_app_info =
ExtractAppInfoFromManifest(manifest_xml.get(), context_->GetDiagnostics())) {
// Extract the package name from the manifest ignoring the value of --rename-manifest-package.
const AppInfo& app_info = maybe_app_info.value();
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 0b2077d..de6b478 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -18,10 +18,10 @@
"""
import argparse
from collections import defaultdict
-import os
-import sys
-import re
import functools
+import os
+import re
+import sys
# Names of flags recognized by the `hiddenapi` tool.
FLAG_WHITELIST = "whitelist"
@@ -30,6 +30,7 @@
FLAG_GREYLIST_MAX_O = "greylist-max-o"
FLAG_GREYLIST_MAX_P = "greylist-max-p"
FLAG_GREYLIST_MAX_Q = "greylist-max-q"
+FLAG_GREYLIST_MAX_R = "greylist-max-r"
FLAG_CORE_PLATFORM_API = "core-platform-api"
FLAG_PUBLIC_API = "public-api"
FLAG_SYSTEM_API = "system-api"
@@ -43,13 +44,14 @@
FLAG_GREYLIST_MAX_O,
FLAG_GREYLIST_MAX_P,
FLAG_GREYLIST_MAX_Q,
+ FLAG_GREYLIST_MAX_R,
]
ALL_FLAGS = FLAGS_API_LIST + [
FLAG_CORE_PLATFORM_API,
FLAG_PUBLIC_API,
FLAG_SYSTEM_API,
FLAG_TEST_API,
- ]
+]
FLAGS_API_LIST_SET = set(FLAGS_API_LIST)
ALL_FLAGS_SET = set(ALL_FLAGS)