Merge "Improve the error handling for armRebootEscrow"
diff --git a/Android.bp b/Android.bp
index 0b0a9b7..1415b6a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -257,37 +257,6 @@
srcs: ["framework-jarjar-rules.txt"],
}
-filegroup {
- name: "libincident_aidl",
- srcs: [
- "core/java/android/os/IIncidentDumpCallback.aidl",
- "core/java/android/os/IIncidentManager.aidl",
- "core/java/android/os/IIncidentReportStatusListener.aidl",
- ],
- path: "core/java",
-}
-
-filegroup {
- name: "libvibrator_aidl",
- srcs: [
- "core/java/android/os/IExternalVibrationController.aidl",
- "core/java/android/os/IExternalVibratorService.aidl",
- ],
- path: "core/java",
-}
-
-filegroup {
- name: "libpowermanager_aidl",
- srcs: [
- "core/java/android/os/Temperature.aidl",
- "core/java/android/os/CoolingDevice.aidl",
- "core/java/android/os/IThermalEventListener.aidl",
- "core/java/android/os/IThermalStatusListener.aidl",
- "core/java/android/os/IThermalService.aidl",
- ],
- path: "core/java",
-}
-
java_library {
name: "framework-minus-apex",
defaults: ["framework-aidl-export-defaults"],
@@ -376,84 +345,6 @@
src: ":framework-minus-apex",
}
-genrule {
- name: "statslog-framework-java-gen",
- tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --java $(out) --module framework" +
- " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
- out: ["com/android/internal/util/FrameworkStatsLog.java"],
-}
-
-java_library {
- name: "uieventloggerlib",
- srcs: [
- "core/java/com/android/internal/logging/UiEvent.java",
- "core/java/com/android/internal/logging/UiEventLogger.java",
- "core/java/com/android/internal/logging/UiEventLoggerImpl.java",
- "core/java/com/android/internal/logging/InstanceId.java",
- "core/java/com/android/internal/logging/InstanceIdSequence.java",
- ":statslog-framework-java-gen",
- ],
-}
-
-gensrcs {
- name: "framework-javastream-protos",
- depfile: true,
-
- tools: [
- "aprotoc",
- "protoc-gen-javastream",
- "soong_zip",
- ],
-
- cmd: "mkdir -p $(genDir)/$(in) " +
- "&& $(location aprotoc) " +
- " --plugin=$(location protoc-gen-javastream) " +
- " --dependency_out=$(depfile) " +
- " --javastream_out=$(genDir)/$(in) " +
- " -Iexternal/protobuf/src " +
- " -I . " +
- " $(in) " +
- "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
-
- srcs: [
- ":ipconnectivity-proto-src",
- ":libstats_atom_enum_protos",
- ":libtombstone_proto-src",
- "core/proto/**/*.proto",
- "libs/incident/**/*.proto",
- ],
- output_extension: "srcjar",
-}
-
-gensrcs {
- name: "framework-cppstream-protos",
- depfile: true,
-
- tools: [
- "aprotoc",
- "protoc-gen-cppstream",
- ],
-
- cmd: "mkdir -p $(genDir) " +
- "&& $(location aprotoc) " +
- " --plugin=$(location protoc-gen-cppstream) " +
- " --dependency_out=$(depfile) " +
- " --cppstream_out=$(genDir) " +
- " -Iexternal/protobuf/src " +
- " -I . " +
- " $(in)",
-
- srcs: [
- ":ipconnectivity-proto-src",
- ":libstats_atom_enum_protos",
- "core/proto/**/*.proto",
- "libs/incident/**/*.proto",
- ],
-
- output_extension: "proto.h",
-}
-
filegroup {
name: "framework-annotations",
srcs: [
@@ -528,30 +419,6 @@
],
}
-filegroup {
- name: "framework-services-net-module-wifi-shared-srcs",
- srcs: [
- "core/java/android/net/DhcpResults.java",
- "core/java/android/util/LocalLog.java",
- ],
-}
-
-// keep these files in sync with the package/Tethering/jarjar-rules.txt and
-// package/Connectivity/jarjar-rules.txt for the tethering module and connectivity module.
-filegroup {
- name: "framework-connectivity-shared-srcs",
- srcs: [
- "core/java/android/util/LocalLog.java",
- // This should be android.util.IndentingPrintWriter, but it's not available in all branches.
- "core/java/com/android/internal/util/IndentingPrintWriter.java",
- "core/java/com/android/internal/util/IState.java",
- "core/java/com/android/internal/util/MessageUtils.java",
- "core/java/com/android/internal/util/State.java",
- "core/java/com/android/internal/util/StateMachine.java",
- "core/java/com/android/internal/util/WakeupMessage.java",
- ],
-}
-
// Build ext.jar
// ============================================================
java_library {
@@ -566,371 +433,6 @@
dxflags: ["--core-library"],
}
-// ==== java proto host library ==============================
-java_library_host {
- name: "platformprotos",
- srcs: [
- ":ipconnectivity-proto-src",
- ":libstats_atom_enum_protos",
- ":libstats_internal_protos",
- ":statsd_internal_protos",
- "cmds/am/proto/instrumentation_data.proto",
- "cmds/statsd/src/**/*.proto",
- "core/proto/**/*.proto",
- "libs/incident/proto/**/*.proto",
- ],
- proto: {
- include_dirs: [
- "external/protobuf/src",
- "frameworks/proto_logging/stats",
- ],
- type: "full",
- },
- errorprone: {
- javacflags: ["-Xep:MissingOverride:OFF"], // b/72714520
- },
-}
-
-// ==== java proto device library (for test only) ==============================
-java_library {
- name: "platformprotosnano",
- proto: {
- type: "nano",
- output_params: ["store_unknown_fields=true"],
- include_dirs: ["external/protobuf/src"],
- },
- exclude_srcs: [
- "core/proto/android/privacy.proto",
- "core/proto/android/section.proto",
- ],
- sdk_version: "9",
- srcs: [
- ":ipconnectivity-proto-src",
- ":libstats_atom_enum_protos",
- "core/proto/**/*.proto",
- "libs/incident/proto/android/os/**/*.proto",
- ],
-}
-
-// ==== java proto device library (for test only) ==============================
-java_library {
- name: "platformprotoslite",
- proto: {
- type: "lite",
- include_dirs: ["external/protobuf/src"],
- },
-
- srcs: [
- ":ipconnectivity-proto-src",
- ":libstats_atom_enum_protos",
- "core/proto/**/*.proto",
- "libs/incident/proto/android/os/**/*.proto",
- ],
- exclude_srcs: [
- "core/proto/android/privacy.proto",
- "core/proto/android/section.proto",
- ],
- sdk_version: "core_current",
- // Protos have lots of MissingOverride and similar.
- errorprone: {
- javacflags: ["-XepDisableAllChecks"],
- },
-}
-
-// ==== c++ proto device library ==============================
-cc_defaults {
- name: "libplatformprotos-defaults",
-
- proto: {
- export_proto_headers: true,
- include_dirs: [
- "external/protobuf/src",
- ],
- },
-
- cflags: [
- "-Wall",
- "-Werror",
- "-Wno-unused-parameter",
- ],
-
- srcs: [
- ":ipconnectivity-proto-src",
- ":libstats_atom_enum_protos",
- "core/proto/**/*.proto",
- ],
-}
-
-cc_library {
- name: "libplatformprotos",
- defaults: ["libplatformprotos-defaults"],
- host_supported: true,
-
- target: {
- host: {
- proto: {
- type: "full",
- },
- },
- android: {
- proto: {
- type: "lite",
- },
- shared_libs: [
- "libprotobuf-cpp-lite",
- ],
- shared: {
- enabled: false,
- },
- },
- },
-}
-
-// This library is meant for vendor code that needs to output protobuf. It links
-// against the static version of libprotobuf-cpp-lite, for which we can not guarantee
-// binary compatibility.
-cc_library {
- name: "libplatformprotos-static",
- defaults: ["libplatformprotos-defaults"],
- host_supported: false,
-
- // This is okay because this library is only built as a static library. The C++
- // API is not guaranteed. The proto API is guaranteed to be stable via Metrics Council,
- // but is not authorized to be used outside of debugging.
- vendor_available: true,
-
- target: {
- android: {
- proto: {
- type: "lite",
- },
- static_libs: [
- "libprotobuf-cpp-lite",
- ],
- shared: {
- enabled: false,
- },
- },
- },
-}
-
-// This is the full proto version of libplatformprotos. It may only
-// be used by test code that is not shipped on the device.
-cc_library {
- name: "libplatformprotos-test",
- defaults: ["libplatformprotos-defaults"],
- host_supported: false,
-
- target: {
- android: {
- proto: {
- type: "full",
- },
- shared: {
- enabled: false,
- },
- },
- },
-}
-
-filegroup {
- name: "incremental_aidl",
- srcs: [
- "core/java/android/os/incremental/IIncrementalServiceConnector.aidl",
- "core/java/android/os/incremental/IncrementalFileSystemControlParcel.aidl",
- ],
- path: "core/java",
-}
-
-filegroup {
- name: "dataloader_aidl",
- srcs: [
- "core/java/android/content/pm/DataLoaderParamsParcel.aidl",
- "core/java/android/content/pm/DataLoaderType.aidl",
- "core/java/android/content/pm/FileSystemControlParcel.aidl",
- "core/java/android/content/pm/IDataLoader.aidl",
- "core/java/android/content/pm/IDataLoaderManager.aidl",
- "core/java/android/content/pm/InstallationFileParcel.aidl",
- "core/java/android/content/pm/InstallationFileLocation.aidl",
- "core/java/android/content/pm/IDataLoaderStatusListener.aidl",
- "core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
- ],
- path: "core/java",
-}
-
-filegroup {
- name: "incremental_manager_aidl",
- srcs: [
- "core/java/android/os/incremental/IIncrementalService.aidl",
- "core/java/android/os/incremental/IncrementalNewFileParams.aidl",
- "core/java/android/os/incremental/IStorageHealthListener.aidl",
- "core/java/android/os/incremental/StorageHealthCheckParams.aidl",
- ],
- path: "core/java",
-}
-
-filegroup {
- name: "activity_manager_procstate_aidl",
- srcs: [
- // internal only
- ],
- path: "core/java",
-}
-
-aidl_interface {
- name: "libincremental_aidl",
- unstable: true,
- srcs: [
- ":incremental_aidl",
- ],
- backend: {
- java: {
- sdk_version: "28",
- },
- cpp: {
- enabled: true,
- },
- ndk: {
- enabled: true,
- },
- },
-}
-
-aidl_interface {
- name: "libdataloader_aidl",
- unstable: true,
- srcs: [
- ":dataloader_aidl",
- ],
- imports: [
- "libincremental_aidl",
- ],
- backend: {
- java: {
- sdk_version: "28",
- },
- cpp: {
- enabled: true,
- },
- ndk: {
- enabled: false,
- },
- },
-}
-
-aidl_interface {
- name: "libincremental_manager_aidl",
- unstable: true,
- srcs: [
- ":incremental_manager_aidl",
- ],
- imports: [
- "libincremental_aidl",
- "libdataloader_aidl",
- ],
- backend: {
- java: {
- sdk_version: "28",
- },
- cpp: {
- enabled: true,
- },
- ndk: {
- enabled: false,
- },
- },
-}
-
-// Build Rust bindings for PermissionController. Needed by keystore2.
-aidl_interface {
- name: "android.os.permissions_aidl",
- unstable: true,
- local_include_dir: "core/java",
- srcs: [
- "core/java/android/os/IPermissionController.aidl",
- ],
- backend: {
- rust: {
- enabled: true,
- },
- },
-}
-
-python_defaults {
- name: "base_default",
- version: {
- py2: {
- enabled: false,
- embedded_launcher: false,
- },
- py3: {
- enabled: true,
- embedded_launcher: true,
- },
- },
-}
-
-python_binary_host {
- name: "fontchain_linter",
- defaults: ["base_default"],
- main: "tools/fonts/fontchain_linter.py",
- srcs: [
- "tools/fonts/fontchain_linter.py",
- ],
- libs: [
- "fontTools",
- ],
-}
-
-// Avoid including Parcelable classes as we don't want to have two copies of
-// Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
-// and TeleService app (packages/services/Telephony).
-filegroup {
- name: "framework-telephony-common-shared-srcs",
- srcs: [
- "core/java/android/os/RegistrantList.java",
- "core/java/android/os/Registrant.java",
- "core/java/android/util/LocalLog.java",
- "core/java/android/util/TimeUtils.java",
- "core/java/com/android/internal/os/SomeArgs.java",
- "core/java/com/android/internal/util/AsyncChannel.java",
- "core/java/com/android/internal/util/AsyncService.java",
- "core/java/com/android/internal/util/BitwiseInputStream.java",
- "core/java/com/android/internal/util/FastXmlSerializer.java",
- "core/java/com/android/internal/util/HexDump.java",
- "core/java/com/android/internal/util/IState.java",
- "core/java/com/android/internal/util/IndentingPrintWriter.java",
- "core/java/com/android/internal/util/Preconditions.java",
- "core/java/com/android/internal/util/State.java",
- "core/java/com/android/internal/util/StateMachine.java",
- "core/java/com/android/internal/util/UserIcons.java",
- ],
-}
-
-// Avoid including Parcelable classes as we don't want to have two copies of
-// Parcelable cross the process.
-filegroup {
- name: "framework-cellbroadcast-shared-srcs",
- srcs: [
- "core/java/android/os/HandlerExecutor.java",
- "core/java/android/util/LocalLog.java",
- "core/java/com/android/internal/util/IState.java",
- "core/java/com/android/internal/util/Preconditions.java",
- "core/java/com/android/internal/util/State.java",
- "core/java/com/android/internal/util/StateMachine.java",
- ],
-}
-
-filegroup {
- name: "framework-ims-common-shared-srcs",
- srcs: [
- "core/java/android/os/RegistrantList.java",
- "core/java/android/os/Registrant.java",
- "core/java/com/android/internal/os/SomeArgs.java",
- "core/java/com/android/internal/util/Preconditions.java",
- ],
-}
-
// utility classes statically linked into framework-wifi and dynamically linked
// into wifi-service
java_library {
@@ -959,33 +461,6 @@
],
}
-filegroup {
- name: "framework-wifi-util-lib-aidls",
- srcs: ["core/java/android/content/pm/ParceledListSlice.aidl"],
- path: "core/java",
-}
-
-// utility classes statically linked into wifi-service
-filegroup {
- name: "framework-wifi-service-shared-srcs",
- srcs: [
- "core/java/android/net/InterfaceConfiguration.java",
- "core/java/android/util/BackupUtils.java",
- "core/java/android/util/Rational.java",
- "core/java/com/android/internal/util/FastXmlSerializer.java",
- "core/java/com/android/internal/util/HexDump.java",
- "core/java/com/android/internal/util/IState.java",
- "core/java/com/android/internal/util/MessageUtils.java",
- "core/java/com/android/internal/util/State.java",
- "core/java/com/android/internal/util/StateMachine.java",
- "core/java/com/android/internal/util/WakeupMessage.java",
- ],
- visibility: [
- "//frameworks/opt/net/wifi/service",
- "//packages/modules/Wifi/service",
- ],
-}
-
// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
"--hide-package com.android.server " +
@@ -1019,4 +494,5 @@
build = [
"StubLibraries.bp",
"ApiDocs.bp",
+ "ProtoLibraries.bp",
]
diff --git a/OWNERS b/OWNERS
index 710f13e..4970dd1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -30,3 +30,4 @@
per-file Android.mk = file:platform/build/soong:/OWNERS
per-file ApiDocs.bp = file:platform/build/soong:/OWNERS
per-file StubLibraries.bp = file:platform/build/soong:/OWNERS
+per-file ProtoLibraries.bp = file:platform/build/soong:/OWNERS
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 2fd2e33..33fd399 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,5 +1,6 @@
[Builtin Hooks]
clang_format = true
+bpfmt = true
[Builtin Hooks Options]
# Only turn on clang-format check for the following subfolders.
diff --git a/ProtoLibraries.bp b/ProtoLibraries.bp
new file mode 100644
index 0000000..c127449
--- /dev/null
+++ b/ProtoLibraries.bp
@@ -0,0 +1,238 @@
+// Copyright (C) 2021 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.
+
+gensrcs {
+ name: "framework-javastream-protos",
+ depfile: true,
+
+ tools: [
+ "aprotoc",
+ "protoc-gen-javastream",
+ "soong_zip",
+ ],
+
+ cmd: "mkdir -p $(genDir)/$(in) " +
+ "&& $(location aprotoc) " +
+ " --plugin=$(location protoc-gen-javastream) " +
+ " --dependency_out=$(depfile) " +
+ " --javastream_out=$(genDir)/$(in) " +
+ " -Iexternal/protobuf/src " +
+ " -I . " +
+ " $(in) " +
+ "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+
+ srcs: [
+ ":ipconnectivity-proto-src",
+ ":libstats_atom_enum_protos",
+ ":libtombstone_proto-src",
+ "core/proto/**/*.proto",
+ "libs/incident/**/*.proto",
+ ],
+ output_extension: "srcjar",
+}
+
+gensrcs {
+ name: "framework-cppstream-protos",
+ depfile: true,
+
+ tools: [
+ "aprotoc",
+ "protoc-gen-cppstream",
+ ],
+
+ cmd: "mkdir -p $(genDir) " +
+ "&& $(location aprotoc) " +
+ " --plugin=$(location protoc-gen-cppstream) " +
+ " --dependency_out=$(depfile) " +
+ " --cppstream_out=$(genDir) " +
+ " -Iexternal/protobuf/src " +
+ " -I . " +
+ " $(in)",
+
+ srcs: [
+ ":ipconnectivity-proto-src",
+ ":libstats_atom_enum_protos",
+ "core/proto/**/*.proto",
+ "libs/incident/**/*.proto",
+ ],
+
+ output_extension: "proto.h",
+}
+
+// ==== java proto host library ==============================
+java_library_host {
+ name: "platformprotos",
+ srcs: [
+ ":ipconnectivity-proto-src",
+ ":libstats_atom_enum_protos",
+ ":libstats_internal_protos",
+ ":statsd_internal_protos",
+ "cmds/am/proto/instrumentation_data.proto",
+ "cmds/statsd/src/**/*.proto",
+ "core/proto/**/*.proto",
+ "libs/incident/proto/**/*.proto",
+ ],
+ proto: {
+ include_dirs: [
+ "external/protobuf/src",
+ "frameworks/proto_logging/stats",
+ ],
+ type: "full",
+ },
+ errorprone: {
+ javacflags: ["-Xep:MissingOverride:OFF"], // b/72714520
+ },
+}
+
+// ==== java proto device library (for test only) ==============================
+java_library {
+ name: "platformprotosnano",
+ proto: {
+ type: "nano",
+ output_params: ["store_unknown_fields=true"],
+ include_dirs: ["external/protobuf/src"],
+ },
+ exclude_srcs: [
+ "core/proto/android/privacy.proto",
+ "core/proto/android/section.proto",
+ ],
+ sdk_version: "9",
+ srcs: [
+ ":ipconnectivity-proto-src",
+ ":libstats_atom_enum_protos",
+ "core/proto/**/*.proto",
+ "libs/incident/proto/android/os/**/*.proto",
+ ],
+}
+
+// ==== java proto device library (for test only) ==============================
+java_library {
+ name: "platformprotoslite",
+ proto: {
+ type: "lite",
+ include_dirs: ["external/protobuf/src"],
+ },
+
+ srcs: [
+ ":ipconnectivity-proto-src",
+ ":libstats_atom_enum_protos",
+ "core/proto/**/*.proto",
+ "libs/incident/proto/android/os/**/*.proto",
+ ],
+ exclude_srcs: [
+ "core/proto/android/privacy.proto",
+ "core/proto/android/section.proto",
+ ],
+ sdk_version: "core_current",
+ // Protos have lots of MissingOverride and similar.
+ errorprone: {
+ javacflags: ["-XepDisableAllChecks"],
+ },
+}
+
+// ==== c++ proto device library ==============================
+cc_defaults {
+ name: "libplatformprotos-defaults",
+
+ proto: {
+ export_proto_headers: true,
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ },
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ ],
+
+ srcs: [
+ ":ipconnectivity-proto-src",
+ ":libstats_atom_enum_protos",
+ "core/proto/**/*.proto",
+ ],
+}
+
+cc_library {
+ name: "libplatformprotos",
+ defaults: ["libplatformprotos-defaults"],
+ host_supported: true,
+
+ target: {
+ host: {
+ proto: {
+ type: "full",
+ },
+ },
+ android: {
+ proto: {
+ type: "lite",
+ },
+ shared_libs: [
+ "libprotobuf-cpp-lite",
+ ],
+ shared: {
+ enabled: false,
+ },
+ },
+ },
+}
+
+// This library is meant for vendor code that needs to output protobuf. It links
+// against the static version of libprotobuf-cpp-lite, for which we can not guarantee
+// binary compatibility.
+cc_library {
+ name: "libplatformprotos-static",
+ defaults: ["libplatformprotos-defaults"],
+ host_supported: false,
+
+ // This is okay because this library is only built as a static library. The C++
+ // API is not guaranteed. The proto API is guaranteed to be stable via Metrics Council,
+ // but is not authorized to be used outside of debugging.
+ vendor_available: true,
+
+ target: {
+ android: {
+ proto: {
+ type: "lite",
+ },
+ static_libs: [
+ "libprotobuf-cpp-lite",
+ ],
+ shared: {
+ enabled: false,
+ },
+ },
+ },
+}
+
+// This is the full proto version of libplatformprotos. It may only
+// be used by test code that is not shipped on the device.
+cc_library {
+ name: "libplatformprotos-test",
+ defaults: ["libplatformprotos-defaults"],
+ host_supported: false,
+
+ target: {
+ android: {
+ proto: {
+ type: "full",
+ },
+ shared: {
+ enabled: false,
+ },
+ },
+ },
+}
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 1644a55..ae92e79 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -111,7 +111,7 @@
last_released: {
api_file: ":android-non-updatable.api.public.latest",
removed_api_file: ":android-non-updatable-removed.api.public.latest",
- baseline_file: ":android-incompatibilities.api.public.latest",
+ baseline_file: ":android-non-updatable-incompatibilities.api.public.latest",
},
api_lint: {
enabled: true,
@@ -163,7 +163,7 @@
last_released: {
api_file: ":android-non-updatable.api.system.latest",
removed_api_file: ":android-non-updatable-removed.api.system.latest",
- baseline_file: ":android-incompatibilities.api.system.latest"
+ baseline_file: ":android-non-updatable-incompatibilities.api.system.latest"
},
api_lint: {
enabled: true,
@@ -268,19 +268,98 @@
// from stub sources
/////////////////////////////////////////////////////////////////////
+modules_public_stubs = [
+ "android.net.ipsec.ike.stubs",
+ "art.module.public.api.stubs",
+ "conscrypt.module.public.api.stubs",
+ "framework-connectivity.stubs",
+ "framework-media.stubs",
+ "framework-mediaprovider.stubs",
+ "framework-permission.stubs",
+ "framework-sdkextensions.stubs",
+ "framework-statsd.stubs",
+ "framework-tethering.stubs",
+ "framework-wifi.stubs",
+ "i18n.module.public.api.stubs",
+]
+
+modules_system_stubs = [
+ "android.net.ipsec.ike.stubs.system",
+ "art.module.public.api.stubs", // Only has public stubs
+ "conscrypt.module.public.api.stubs", // Only has public stubs
+ "framework-connectivity.stubs.system",
+ "framework-media.stubs.system",
+ "framework-mediaprovider.stubs.system",
+ "framework-permission.stubs.system",
+ "framework-sdkextensions.stubs.system",
+ "framework-statsd.stubs.system",
+ "framework-tethering.stubs.system",
+ "framework-wifi.stubs.system",
+ "i18n.module.public.api.stubs", // Only has public stubs
+]
+
+java_defaults {
+ name: "android-non-updatable_defaults_stubs_current",
+ libs: ["stub-annotations"],
+ static_libs: ["framework-res-package-jar"], // Export package of framework-res
+ sdk_version: "none",
+ system_modules: "none",
+ java_version: "1.8",
+ compile_dex: true,
+ dist: {
+ targets: ["sdk", "win_sdk"],
+ tag: ".jar",
+ dest: "android-non-updatable.jar",
+ }
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [":api-stubs-docs-non-updatable"],
+ libs: modules_public_stubs,
+ dist: {
+ dir: "apistubs/android/public",
+ },
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs.system",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [ ":system-api-stubs-docs-non-updatable" ],
+ libs: modules_system_stubs,
+ dist: {
+ dir: "apistubs/android/system",
+ },
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs.module_lib",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [":module-lib-api-stubs-docs-non-updatable"],
+ libs: [
+ "sdk_system_current_android",
+ // NOTE: The below can be removed once the prebuilt stub contains IKE.
+ "sdk_system_current_android.net.ipsec.ike",
+ ],
+ dist: {
+ dir: "apistubs/android/module-lib",
+ },
+}
+
+java_library_static {
+ name: "android-non-updatable.stubs.test",
+ defaults: ["android-non-updatable_defaults_stubs_current"],
+ srcs: [":test-api-stubs-docs-non-updatable"],
+ libs: modules_system_stubs,
+ dist: {
+ dir: "apistubs/android/test",
+ },
+}
+
java_defaults {
name: "android_defaults_stubs_current",
- libs: [ "stub-annotations" ],
- static_libs: [
- // License notices from art module
- "art-notices-for-framework-stubs-jar",
- "framework-res-package-jar", // Export package of framework-res
- ],
- errorprone: {
- javacflags: [
- "-XepDisableAllChecks",
- ],
- },
+ static_libs: ["art-notices-for-framework-stubs-jar"], // License notices from art module
sdk_version: "none",
system_modules: "none",
java_version: "1.8",
@@ -298,20 +377,8 @@
java_library_static {
name: "android_stubs_current",
- srcs: [ ":api-stubs-docs-non-updatable" ],
- static_libs: [
- "android.net.ipsec.ike.stubs",
- "art.module.public.api.stubs",
- "conscrypt.module.public.api.stubs",
- "framework-connectivity.stubs",
- "framework-media.stubs",
- "framework-mediaprovider.stubs",
- "framework-permission.stubs",
- "framework-sdkextensions.stubs",
- "framework-statsd.stubs",
- "framework-tethering.stubs",
- "framework-wifi.stubs",
- "i18n.module.public.api.stubs",
+ static_libs: modules_public_stubs + [
+ "android-non-updatable.stubs",
"private-stub-annotations-jar",
],
defaults: ["android_defaults_stubs_current"],
@@ -319,20 +386,8 @@
java_library_static {
name: "android_system_stubs_current",
- srcs: [ ":system-api-stubs-docs-non-updatable" ],
- static_libs: [
- "android.net.ipsec.ike.stubs.system",
- "art.module.public.api.stubs",
- "conscrypt.module.public.api.stubs",
- "framework-connectivity.stubs.system",
- "framework-media.stubs.system",
- "framework-mediaprovider.stubs.system",
- "framework-permission.stubs.system",
- "framework-sdkextensions.stubs.system",
- "framework-statsd.stubs.system",
- "framework-tethering.stubs.system",
- "framework-wifi.stubs.system",
- "i18n.module.public.api.stubs",
+ static_libs: modules_system_stubs + [
+ "android-non-updatable.stubs.system",
"private-stub-annotations-jar",
],
defaults: [
@@ -354,22 +409,10 @@
java_library_static {
name: "android_test_stubs_current",
- srcs: [ ":test-api-stubs-docs-non-updatable" ],
- static_libs: [
- // Modules do not have test APIs, but we want to include their SystemApis, like we include
- // the SystemApi of framework-non-updatable-sources.
- "android.net.ipsec.ike.stubs.system",
- "art.module.public.api.stubs",
- "conscrypt.module.public.api.stubs",
- "framework-connectivity.stubs.system",
- "framework-media.stubs.system",
- "framework-mediaprovider.stubs.system",
- "framework-permission.stubs.system",
- "framework-sdkextensions.stubs.system",
- "framework-statsd.stubs.system",
- "framework-tethering.stubs.system",
- "framework-wifi.stubs.system",
- "i18n.module.public.api.stubs",
+ // Modules do not have test APIs, but we want to include their SystemApis, like we include
+ // the SystemApi of framework-non-updatable-sources.
+ static_libs: modules_system_stubs + [
+ "android-non-updatable.stubs.test",
"private-stub-annotations-jar",
],
defaults: [
@@ -391,17 +434,14 @@
java_library_static {
name: "android_module_lib_stubs_current",
- srcs: [ ":module-lib-api-stubs-docs-non-updatable" ],
defaults: [
"android_defaults_stubs_current",
"android_stubs_dists_default",
],
- libs: [
- "sdk_system_current_android",
- // NOTE: The below can be removed once the prebuilt stub contains IKE.
- "sdk_system_current_android.net.ipsec.ike",
+ static_libs: [
+ "android-non-updatable.stubs.module_lib",
+ "art.module.public.api.stubs",
],
- static_libs: ["art.module.public.api.stubs"],
dist: {
dir: "apistubs/android/module-lib",
},
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index a522237..5487e87 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -693,13 +693,6 @@
StateControllerProto.ConnectivityController.REQUESTED_STANDBY_EXCEPTION_UIDS,
mRequestedWhitelistJobs.keyAt(i));
}
- for (int i = 0; i < mAvailableNetworks.size(); i++) {
- Network network = mAvailableNetworks.keyAt(i);
- if (network != null) {
- network.dumpDebug(proto,
- StateControllerProto.ConnectivityController.AVAILABLE_NETWORKS);
- }
- }
for (int i = 0; i < mTrackedJobs.size(); i++) {
final ArraySet<JobStatus> jobs = mTrackedJobs.valueAt(i);
for (int j = 0; j < jobs.size(); j++) {
@@ -713,12 +706,6 @@
StateControllerProto.ConnectivityController.TrackedJob.INFO);
proto.write(StateControllerProto.ConnectivityController.TrackedJob.SOURCE_UID,
js.getSourceUid());
- NetworkRequest rn = js.getJob().getRequiredNetwork();
- if (rn != null) {
- rn.dumpDebug(proto,
- StateControllerProto.ConnectivityController.TrackedJob
- .REQUIRED_NETWORK);
- }
proto.end(jsToken);
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index ea8e7bc..a346812 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -1911,9 +1911,6 @@
if (uriPerms != null) {
uriPerms.dump(proto, JobStatusDumpProto.JobInfo.GRANTED_URI_PERMISSIONS);
}
- if (job.getRequiredNetwork() != null) {
- job.getRequiredNetwork().dumpDebug(proto, JobStatusDumpProto.JobInfo.REQUIRED_NETWORK);
- }
if (mTotalNetworkDownloadBytes != JobInfo.NETWORK_BYTES_UNKNOWN) {
proto.write(JobStatusDumpProto.JobInfo.TOTAL_NETWORK_DOWNLOAD_BYTES,
mTotalNetworkDownloadBytes);
@@ -2002,10 +1999,6 @@
}
}
- if (network != null) {
- network.dumpDebug(proto, JobStatusDumpProto.NETWORK);
- }
-
if (pendingWork != null) {
for (int i = 0; i < pendingWork.size(); i++) {
dumpJobWorkItem(proto, JobStatusDumpProto.PENDING_WORK, pendingWork.get(i));
diff --git a/api/Android.bp b/api/Android.bp
index 485255f..6e83c08 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -308,6 +308,9 @@
genrule {
name: "combined-removed-dex",
+ visibility: [
+ "//frameworks/base/boot",
+ ],
srcs: [
":frameworks-base-api-removed.txt",
":frameworks-base-api-system-removed.txt",
diff --git a/api/dump_api_shas.sh b/api/dump_api_shas.sh
new file mode 100755
index 0000000..c023b31
--- /dev/null
+++ b/api/dump_api_shas.sh
@@ -0,0 +1,56 @@
+#!/bin/bash -e
+# This script dumps the git SHAs of all commits inside api tracking directories.
+# It can used by tools wanting to track API changes, and the primary original
+# purpose is to verify verify all API change SHAs have been tracked by the
+# server-side API-council tools.
+#
+# The only argument is used to specify a git commit range to filter by.
+#
+# Example invocation (API changes between O and P):
+# frameworks/base/api/dump_api_shas.sh origin/oreo-dev..origin/pie-dev
+
+set -o pipefail
+
+eecho() { echo $@ >&2 ; }
+
+if [[ $1 == *..* ]]; then
+ exclude=${1/..*}
+ include=${1/*..}
+else
+ eecho No range or invalid range specified, defaulting to all commits from HEAD.
+ exclude=
+ include=HEAD
+fi
+
+eecho -n building queryview...
+{ source build/envsetup.sh && lunch aosp_arm && m queryview; } >/dev/null 2>&1 \
+ || { eecho failed; exit 1; }
+eecho "done"
+
+# This finds the directories where the dependant java_sdk_libs are defined
+bpdirs=$(
+ bazel query --config=queryview --output=package \
+ 'kind(java_sdk_library, deps(//frameworks/base/api/..., 1))' 2>/dev/null
+ echo frameworks/base/core/api # Not a java_sdk_library.
+ echo frameworks/base/services/api # Not a java_sdk_library.
+)
+
+# Find relevant api subdirectories
+apidirs=$(
+ find $bpdirs -type f -name '*current.txt' -path '*/api/*' \
+ | xargs realpath --relative-to=$(pwd) | xargs dirname | sort | uniq
+)
+
+# Dump sorted SHAs of commits in these directories
+{ for d in $apidirs; do
+ ( cd $d
+ eecho inspecting $d
+ exclude_arg=$(test -n "$exclude" && {
+ git rev-parse -q --verify $exclude > /dev/null && echo "--not $exclude" \
+ || eecho "$d has no revision $exclude, including all commits"; } || true)
+ for f in $(find . -name '*current.txt'); do
+ git --no-pager log --pretty=format:%H --no-merges --follow $include $exclude_arg -- $f
+ echo # No trailing newline with --no-pager
+ done
+ )
+done; } | sort | uniq
diff --git a/boot/Android.bp b/boot/Android.bp
index 71edea2..844dd64 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -43,4 +43,49 @@
// done correctly.
platform_bootclasspath {
name: "platform-bootclasspath",
+
+ // Additional information needed by hidden api processing.
+ hidden_api: {
+ unsupported: [
+ "hiddenapi/hiddenapi-unsupported.txt",
+ ],
+ removed: [
+ ":combined-removed-dex",
+ ],
+ max_target_r_low_priority: [
+ "hiddenapi/hiddenapi-max-target-r-loprio.txt",
+ ],
+ max_target_q: [
+ "hiddenapi/hiddenapi-max-target-q.txt",
+ ],
+ max_target_p: [
+ "hiddenapi/hiddenapi-max-target-p.txt",
+ ],
+ max_target_o_low_priority: [
+ "hiddenapi/hiddenapi-max-target-o.txt",
+ ],
+ blocked: [
+ "hiddenapi/hiddenapi-force-blocked.txt",
+ ],
+ unsupported_packages: [
+ "hiddenapi/hiddenapi-unsupported-packages.txt",
+ ],
+ },
+
+ dists: [
+ {
+ targets: ["droidcore"],
+ tag: "hiddenapi-flags.csv",
+ },
+ {
+ targets: ["droidcore"],
+ tag: "hiddenapi-index.csv",
+ },
+ {
+ targets: ["droidcore"],
+ tag: "hiddenapi-metadata.csv",
+ // Legacy name
+ dest: "hiddenapi-unsupported.csv",
+ },
+ ],
}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
new file mode 100644
index 0000000..99c39f6
--- /dev/null
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -0,0 +1,392 @@
+/*
+ * 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.
+ */
+
+#define DEBUG false
+#include "Log.h"
+
+#include "StatsPullerManager.h"
+
+#include <cutils/log.h>
+#include <math.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <iostream>
+
+#include "../StatsService.h"
+#include "../logd/LogEvent.h"
+#include "../stats_log_util.h"
+#include "../statscompanion_util.h"
+#include "StatsCallbackPuller.h"
+#include "TrainInfoPuller.h"
+#include "statslog_statsd.h"
+
+using std::shared_ptr;
+using std::vector;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// Stores the puller as a wp to avoid holding a reference in case it is unregistered and
+// pullAtomCallbackDied is never called.
+struct PullAtomCallbackDeathCookie {
+ PullAtomCallbackDeathCookie(const wp<StatsPullerManager>& pullerManager,
+ const PullerKey& pullerKey, const wp<StatsPuller>& puller) :
+ mPullerManager(pullerManager), mPullerKey(pullerKey), mPuller(puller) {
+ }
+
+ wp<StatsPullerManager> mPullerManager;
+ PullerKey mPullerKey;
+ wp<StatsPuller> mPuller;
+};
+
+void StatsPullerManager::pullAtomCallbackDied(void* cookie) {
+ PullAtomCallbackDeathCookie* cookie_ = static_cast<PullAtomCallbackDeathCookie*>(cookie);
+ sp<StatsPullerManager> thiz = cookie_->mPullerManager.promote();
+ if (!thiz) {
+ return;
+ }
+
+ const PullerKey& pullerKey = cookie_->mPullerKey;
+ wp<StatsPuller> puller = cookie_->mPuller;
+
+ // Erase the mapping from the puller key to the puller if the mapping still exists.
+ // Note that we are removing the StatsPuller object, which internally holds the binder
+ // IPullAtomCallback. However, each new registration creates a new StatsPuller, so this works.
+ lock_guard<mutex> lock(thiz->mLock);
+ const auto& it = thiz->kAllPullAtomInfo.find(pullerKey);
+ if (it != thiz->kAllPullAtomInfo.end() && puller != nullptr && puller == it->second) {
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(pullerKey.atomTag,
+ /*registered=*/false);
+ thiz->kAllPullAtomInfo.erase(pullerKey);
+ }
+ // The death recipient corresponding to this specific IPullAtomCallback can never
+ // be triggered again, so free up resources.
+ delete cookie_;
+}
+
+// Values smaller than this may require to update the alarm.
+const int64_t NO_ALARM_UPDATE = INT64_MAX;
+
+StatsPullerManager::StatsPullerManager()
+ : kAllPullAtomInfo({
+ // TrainInfo.
+ {{.atomTag = util::TRAIN_INFO, .uid = AID_STATSD}, new TrainInfoPuller()},
+ }),
+ mNextPullTimeNs(NO_ALARM_UPDATE),
+ mPullAtomCallbackDeathRecipient(AIBinder_DeathRecipient_new(pullAtomCallbackDied)) {
+}
+
+bool StatsPullerManager::Pull(int tagId, const ConfigKey& configKey, const int64_t eventTimeNs,
+ vector<shared_ptr<LogEvent>>* data, bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return PullLocked(tagId, configKey, eventTimeNs, data, useUids);
+}
+
+bool StatsPullerManager::Pull(int tagId, const vector<int32_t>& uids, const int64_t eventTimeNs,
+ vector<std::shared_ptr<LogEvent>>* data, bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ return PullLocked(tagId, uids, eventTimeNs, data, useUids);
+}
+
+bool StatsPullerManager::PullLocked(int tagId, const ConfigKey& configKey,
+ const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data,
+ bool useUids) {
+ vector<int32_t> uids;
+ if (useUids) {
+ auto uidProviderIt = mPullUidProviders.find(configKey);
+ if (uidProviderIt == mPullUidProviders.end()) {
+ ALOGE("Error pulling tag %d. No pull uid provider for config key %s", tagId,
+ configKey.ToString().c_str());
+ StatsdStats::getInstance().notePullUidProviderNotFound(tagId);
+ return false;
+ }
+ sp<PullUidProvider> pullUidProvider = uidProviderIt->second.promote();
+ if (pullUidProvider == nullptr) {
+ ALOGE("Error pulling tag %d, pull uid provider for config %s is gone.", tagId,
+ configKey.ToString().c_str());
+ StatsdStats::getInstance().notePullUidProviderNotFound(tagId);
+ return false;
+ }
+ uids = pullUidProvider->getPullAtomUids(tagId);
+ }
+ return PullLocked(tagId, uids, eventTimeNs, data, useUids);
+}
+
+bool StatsPullerManager::PullLocked(int tagId, const vector<int32_t>& uids,
+ const int64_t eventTimeNs, vector<shared_ptr<LogEvent>>* data,
+ bool useUids) {
+ VLOG("Initiating pulling %d", tagId);
+ if (useUids) {
+ for (int32_t uid : uids) {
+ PullerKey key = {.atomTag = tagId, .uid = uid};
+ auto pullerIt = kAllPullAtomInfo.find(key);
+ if (pullerIt != kAllPullAtomInfo.end()) {
+ bool ret = pullerIt->second->Pull(eventTimeNs, data);
+ VLOG("pulled %zu items", data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
+ return ret;
+ }
+ }
+ StatsdStats::getInstance().notePullerNotFound(tagId);
+ ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
+ return false; // Return early since we don't know what to pull.
+ } else {
+ PullerKey key = {.atomTag = tagId, .uid = -1};
+ auto pullerIt = kAllPullAtomInfo.find(key);
+ if (pullerIt != kAllPullAtomInfo.end()) {
+ bool ret = pullerIt->second->Pull(eventTimeNs, data);
+ VLOG("pulled %zu items", data->size());
+ if (!ret) {
+ StatsdStats::getInstance().notePullFailed(tagId);
+ }
+ return ret;
+ }
+ ALOGW("StatsPullerManager: Unknown tagId %d", tagId);
+ return false; // Return early since we don't know what to pull.
+ }
+}
+
+bool StatsPullerManager::PullerForMatcherExists(int tagId) const {
+ // Pulled atoms might be registered after we parse the config, so just make sure the id is in
+ // an appropriate range.
+ return isVendorPulledAtom(tagId) || isPulledAtom(tagId);
+}
+
+void StatsPullerManager::updateAlarmLocked() {
+ if (mNextPullTimeNs == NO_ALARM_UPDATE) {
+ VLOG("No need to set alarms. Skipping");
+ return;
+ }
+
+ // TODO(b/151045771): do not hold a lock while making a binder call
+ if (mStatsCompanionService != nullptr) {
+ mStatsCompanionService->setPullingAlarm(mNextPullTimeNs / 1000000);
+ } else {
+ VLOG("StatsCompanionService not available. Alarm not set.");
+ }
+ return;
+}
+
+void StatsPullerManager::SetStatsCompanionService(
+ shared_ptr<IStatsCompanionService> statsCompanionService) {
+ std::lock_guard<std::mutex> _l(mLock);
+ shared_ptr<IStatsCompanionService> tmpForLock = mStatsCompanionService;
+ mStatsCompanionService = statsCompanionService;
+ for (const auto& pulledAtom : kAllPullAtomInfo) {
+ pulledAtom.second->SetStatsCompanionService(statsCompanionService);
+ }
+ if (mStatsCompanionService != nullptr) {
+ updateAlarmLocked();
+ }
+}
+
+void StatsPullerManager::RegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver, int64_t nextPullTimeNs,
+ int64_t intervalNs) {
+ std::lock_guard<std::mutex> _l(mLock);
+ auto& receivers = mReceivers[{.atomTag = tagId, .configKey = configKey}];
+ for (auto it = receivers.begin(); it != receivers.end(); it++) {
+ if (it->receiver == receiver) {
+ VLOG("Receiver already registered of %d", (int)receivers.size());
+ return;
+ }
+ }
+ ReceiverInfo receiverInfo;
+ receiverInfo.receiver = receiver;
+
+ // Round it to the nearest minutes. This is the limit of alarm manager.
+ // In practice, we should always have larger buckets.
+ int64_t roundedIntervalNs = intervalNs / NS_PER_SEC / 60 * NS_PER_SEC * 60;
+ // Scheduled pulling should be at least 1 min apart.
+ // This can be lower in cts tests, in which case we round it to 1 min.
+ if (roundedIntervalNs < 60 * (int64_t)NS_PER_SEC) {
+ roundedIntervalNs = 60 * (int64_t)NS_PER_SEC;
+ }
+
+ receiverInfo.intervalNs = roundedIntervalNs;
+ receiverInfo.nextPullTimeNs = nextPullTimeNs;
+ receivers.push_back(receiverInfo);
+
+ // There is only one alarm for all pulled events. So only set it to the smallest denom.
+ if (nextPullTimeNs < mNextPullTimeNs) {
+ VLOG("Updating next pull time %lld", (long long)mNextPullTimeNs);
+ mNextPullTimeNs = nextPullTimeNs;
+ updateAlarmLocked();
+ }
+ VLOG("Puller for tagId %d registered of %d", tagId, (int)receivers.size());
+}
+
+void StatsPullerManager::UnRegisterReceiver(int tagId, const ConfigKey& configKey,
+ wp<PullDataReceiver> receiver) {
+ std::lock_guard<std::mutex> _l(mLock);
+ auto receiversIt = mReceivers.find({.atomTag = tagId, .configKey = configKey});
+ if (receiversIt == mReceivers.end()) {
+ VLOG("Unknown pull code or no receivers: %d", tagId);
+ return;
+ }
+ std::list<ReceiverInfo>& receivers = receiversIt->second;
+ for (auto it = receivers.begin(); it != receivers.end(); it++) {
+ if (receiver == it->receiver) {
+ receivers.erase(it);
+ VLOG("Puller for tagId %d unregistered of %d", tagId, (int)receivers.size());
+ return;
+ }
+ }
+}
+
+void StatsPullerManager::RegisterPullUidProvider(const ConfigKey& configKey,
+ wp<PullUidProvider> provider) {
+ std::lock_guard<std::mutex> _l(mLock);
+ mPullUidProviders[configKey] = provider;
+}
+
+void StatsPullerManager::UnregisterPullUidProvider(const ConfigKey& configKey,
+ wp<PullUidProvider> provider) {
+ std::lock_guard<std::mutex> _l(mLock);
+ const auto& it = mPullUidProviders.find(configKey);
+ if (it != mPullUidProviders.end() && it->second == provider) {
+ mPullUidProviders.erase(it);
+ }
+}
+
+void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
+ std::lock_guard<std::mutex> _l(mLock);
+ int64_t wallClockNs = getWallClockNs();
+
+ int64_t minNextPullTimeNs = NO_ALARM_UPDATE;
+
+ vector<pair<const ReceiverKey*, vector<ReceiverInfo*>>> needToPull;
+ for (auto& pair : mReceivers) {
+ vector<ReceiverInfo*> receivers;
+ if (pair.second.size() != 0) {
+ for (ReceiverInfo& receiverInfo : pair.second) {
+ if (receiverInfo.nextPullTimeNs <= elapsedTimeNs) {
+ receivers.push_back(&receiverInfo);
+ } else {
+ if (receiverInfo.nextPullTimeNs < minNextPullTimeNs) {
+ minNextPullTimeNs = receiverInfo.nextPullTimeNs;
+ }
+ }
+ }
+ if (receivers.size() > 0) {
+ needToPull.push_back(make_pair(&pair.first, receivers));
+ }
+ }
+ }
+ for (const auto& pullInfo : needToPull) {
+ vector<shared_ptr<LogEvent>> data;
+ bool pullSuccess = PullLocked(pullInfo.first->atomTag, pullInfo.first->configKey,
+ elapsedTimeNs, &data);
+ if (!pullSuccess) {
+ VLOG("pull failed at %lld, will try again later", (long long)elapsedTimeNs);
+ }
+
+ // Convention is to mark pull atom timestamp at request time.
+ // If we pull at t0, puller starts at t1, finishes at t2, and send back
+ // at t3, we mark t0 as its timestamp, which should correspond to its
+ // triggering event, such as condition change at t0.
+ // Here the triggering event is alarm fired from AlarmManager.
+ // In ValueMetricProducer and GaugeMetricProducer we do same thing
+ // when pull on condition change, etc.
+ for (auto& event : data) {
+ event->setElapsedTimestampNs(elapsedTimeNs);
+ event->setLogdWallClockTimestampNs(wallClockNs);
+ }
+
+ for (const auto& receiverInfo : pullInfo.second) {
+ sp<PullDataReceiver> receiverPtr = receiverInfo->receiver.promote();
+ if (receiverPtr != nullptr) {
+ receiverPtr->onDataPulled(data, pullSuccess, elapsedTimeNs);
+ // We may have just come out of a coma, compute next pull time.
+ int numBucketsAhead =
+ (elapsedTimeNs - receiverInfo->nextPullTimeNs) / receiverInfo->intervalNs;
+ receiverInfo->nextPullTimeNs += (numBucketsAhead + 1) * receiverInfo->intervalNs;
+ if (receiverInfo->nextPullTimeNs < minNextPullTimeNs) {
+ minNextPullTimeNs = receiverInfo->nextPullTimeNs;
+ }
+ } else {
+ VLOG("receiver already gone.");
+ }
+ }
+ }
+
+ VLOG("mNextPullTimeNs: %lld updated to %lld", (long long)mNextPullTimeNs,
+ (long long)minNextPullTimeNs);
+ mNextPullTimeNs = minNextPullTimeNs;
+ updateAlarmLocked();
+}
+
+int StatsPullerManager::ForceClearPullerCache() {
+ std::lock_guard<std::mutex> _l(mLock);
+ int totalCleared = 0;
+ for (const auto& pulledAtom : kAllPullAtomInfo) {
+ totalCleared += pulledAtom.second->ForceClearCache();
+ }
+ return totalCleared;
+}
+
+int StatsPullerManager::ClearPullerCacheIfNecessary(int64_t timestampNs) {
+ std::lock_guard<std::mutex> _l(mLock);
+ int totalCleared = 0;
+ for (const auto& pulledAtom : kAllPullAtomInfo) {
+ totalCleared += pulledAtom.second->ClearCacheIfNecessary(timestampNs);
+ }
+ return totalCleared;
+}
+
+void StatsPullerManager::RegisterPullAtomCallback(const int uid, const int32_t atomTag,
+ const int64_t coolDownNs, const int64_t timeoutNs,
+ const vector<int32_t>& additiveFields,
+ const shared_ptr<IPullAtomCallback>& callback,
+ bool useUid) {
+ std::lock_guard<std::mutex> _l(mLock);
+ VLOG("RegisterPullerCallback: adding puller for tag %d", atomTag);
+
+ if (callback == nullptr) {
+ ALOGW("SetPullAtomCallback called with null callback for atom %d.", atomTag);
+ return;
+ }
+
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/true);
+ int64_t actualCoolDownNs = coolDownNs < kMinCoolDownNs ? kMinCoolDownNs : coolDownNs;
+ int64_t actualTimeoutNs = timeoutNs > kMaxTimeoutNs ? kMaxTimeoutNs : timeoutNs;
+
+ sp<StatsCallbackPuller> puller = new StatsCallbackPuller(atomTag, callback, actualCoolDownNs,
+ actualTimeoutNs, additiveFields);
+ PullerKey key = {.atomTag = atomTag, .uid = useUid ? uid : -1};
+ AIBinder_linkToDeath(callback->asBinder().get(), mPullAtomCallbackDeathRecipient.get(),
+ new PullAtomCallbackDeathCookie(this, key, puller));
+ kAllPullAtomInfo[key] = puller;
+}
+
+void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag,
+ bool useUids) {
+ std::lock_guard<std::mutex> _l(mLock);
+ PullerKey key = {.atomTag = atomTag, .uid = useUids ? uid : -1};
+ if (kAllPullAtomInfo.find(key) != kAllPullAtomInfo.end()) {
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag,
+ /*registered=*/false);
+ kAllPullAtomInfo.erase(key);
+ }
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
new file mode 100644
index 0000000..4f03172
--- /dev/null
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -0,0 +1,618 @@
+/*
+ * 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.
+ */
+
+#define DEBUG false // STOPSHIP if true
+#include "logd/LogEvent.h"
+
+#include <android-base/stringprintf.h>
+#include <android/binder_ibinder.h>
+#include <log/log.h>
+#include <private/android_filesystem_config.h>
+
+#include "annotations.h"
+#include "stats_log_util.h"
+#include "statslog_statsd.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+// for TrainInfo experiment id serialization
+const int FIELD_ID_EXPERIMENT_ID = 1;
+
+using namespace android::util;
+using android::base::StringPrintf;
+using android::util::ProtoOutputStream;
+using std::string;
+using std::vector;
+
+// stats_event.h socket types. Keep in sync.
+/* ERRORS */
+#define ERROR_NO_TIMESTAMP 0x1
+#define ERROR_NO_ATOM_ID 0x2
+#define ERROR_OVERFLOW 0x4
+#define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
+#define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
+#define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
+#define ERROR_INVALID_ANNOTATION_ID 0x40
+#define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
+#define ERROR_TOO_MANY_ANNOTATIONS 0x100
+#define ERROR_TOO_MANY_FIELDS 0x200
+#define ERROR_INVALID_VALUE_TYPE 0x400
+#define ERROR_STRING_NOT_NULL_TERMINATED 0x800
+
+/* TYPE IDS */
+#define INT32_TYPE 0x00
+#define INT64_TYPE 0x01
+#define STRING_TYPE 0x02
+#define LIST_TYPE 0x03
+#define FLOAT_TYPE 0x04
+#define BOOL_TYPE 0x05
+#define BYTE_ARRAY_TYPE 0x06
+#define OBJECT_TYPE 0x07
+#define KEY_VALUE_PAIRS_TYPE 0x08
+#define ATTRIBUTION_CHAIN_TYPE 0x09
+#define ERROR_TYPE 0x0F
+
+LogEvent::LogEvent(int32_t uid, int32_t pid)
+ : mLogdTimestampNs(time(nullptr)), mLogUid(uid), mLogPid(pid) {
+}
+
+LogEvent::LogEvent(const string& trainName, int64_t trainVersionCode, bool requiresStaging,
+ bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
+ const std::vector<uint8_t>& experimentIds, int32_t userId) {
+ mLogdTimestampNs = getWallClockNs();
+ mElapsedTimestampNs = getElapsedRealtimeNs();
+ mTagId = util::BINARY_PUSH_STATE_CHANGED;
+ mLogUid = AIBinder_getCallingUid();
+ mLogPid = AIBinder_getCallingPid();
+
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(1)), Value(trainName)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainVersionCode)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value((int)requiresStaging)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value((int)rollbackEnabled)));
+ mValues.push_back(
+ FieldValue(Field(mTagId, getSimpleField(5)), Value((int)requiresLowLatencyMonitor)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(6)), Value(state)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(7)), Value(experimentIds)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(8)), Value(userId)));
+}
+
+LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+ const InstallTrainInfo& trainInfo) {
+ mLogdTimestampNs = wallClockTimestampNs;
+ mElapsedTimestampNs = elapsedTimestampNs;
+ mTagId = util::TRAIN_INFO;
+
+ mValues.push_back(
+ FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
+ std::vector<uint8_t> experimentIdsProto;
+ writeExperimentIdsToProto(trainInfo.experimentIds, &experimentIdsProto);
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(experimentIdsProto)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(3)), Value(trainInfo.trainName)));
+ mValues.push_back(FieldValue(Field(mTagId, getSimpleField(4)), Value(trainInfo.status)));
+}
+
+void LogEvent::parseInt32(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ int32_t value = readNextValue<int32_t>();
+ addToValues(pos, depth, value, last);
+ parseAnnotations(numAnnotations);
+}
+
+void LogEvent::parseInt64(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ int64_t value = readNextValue<int64_t>();
+ addToValues(pos, depth, value, last);
+ parseAnnotations(numAnnotations);
+}
+
+void LogEvent::parseString(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ int32_t numBytes = readNextValue<int32_t>();
+ if ((uint32_t)numBytes > mRemainingLen) {
+ mValid = false;
+ return;
+ }
+
+ string value = string((char*)mBuf, numBytes);
+ mBuf += numBytes;
+ mRemainingLen -= numBytes;
+ addToValues(pos, depth, value, last);
+ parseAnnotations(numAnnotations);
+}
+
+void LogEvent::parseFloat(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ float value = readNextValue<float>();
+ addToValues(pos, depth, value, last);
+ parseAnnotations(numAnnotations);
+}
+
+void LogEvent::parseBool(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ // cast to int32_t because FieldValue does not support bools
+ int32_t value = (int32_t)readNextValue<uint8_t>();
+ addToValues(pos, depth, value, last);
+ parseAnnotations(numAnnotations);
+}
+
+void LogEvent::parseByteArray(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ int32_t numBytes = readNextValue<int32_t>();
+ if ((uint32_t)numBytes > mRemainingLen) {
+ mValid = false;
+ return;
+ }
+
+ vector<uint8_t> value(mBuf, mBuf + numBytes);
+ mBuf += numBytes;
+ mRemainingLen -= numBytes;
+ addToValues(pos, depth, value, last);
+ parseAnnotations(numAnnotations);
+}
+
+void LogEvent::parseKeyValuePairs(int32_t* pos, int32_t depth, bool* last, uint8_t numAnnotations) {
+ int32_t numPairs = readNextValue<uint8_t>();
+
+ for (pos[1] = 1; pos[1] <= numPairs; pos[1]++) {
+ last[1] = (pos[1] == numPairs);
+
+ // parse key
+ pos[2] = 1;
+ parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+
+ // parse value
+ last[2] = true;
+
+ uint8_t typeInfo = readNextValue<uint8_t>();
+ switch (getTypeId(typeInfo)) {
+ case INT32_TYPE:
+ pos[2] = 2; // pos[2] determined by index of type in KeyValuePair in atoms.proto
+ parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+ break;
+ case INT64_TYPE:
+ pos[2] = 3;
+ parseInt64(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+ break;
+ case STRING_TYPE:
+ pos[2] = 4;
+ parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+ break;
+ case FLOAT_TYPE:
+ pos[2] = 5;
+ parseFloat(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+ break;
+ default:
+ mValid = false;
+ }
+ }
+
+ parseAnnotations(numAnnotations);
+
+ pos[1] = pos[2] = 1;
+ last[1] = last[2] = false;
+}
+
+void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
+ uint8_t numAnnotations) {
+ const unsigned int firstUidInChainIndex = mValues.size();
+ const int32_t numNodes = readNextValue<uint8_t>();
+ for (pos[1] = 1; pos[1] <= numNodes; pos[1]++) {
+ last[1] = (pos[1] == numNodes);
+
+ // parse uid
+ pos[2] = 1;
+ parseInt32(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+
+ // parse tag
+ pos[2] = 2;
+ last[2] = true;
+ parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
+ }
+
+ if (mValues.size() - 1 > INT8_MAX) {
+ mValid = false;
+ } else if (mValues.size() - 1 > firstUidInChainIndex) {
+ // At least one node was successfully parsed.
+ mAttributionChainStartIndex = static_cast<int8_t>(firstUidInChainIndex);
+ mAttributionChainEndIndex = static_cast<int8_t>(mValues.size() - 1);
+ }
+
+ if (mValid) {
+ parseAnnotations(numAnnotations, firstUidInChainIndex);
+ }
+
+ pos[1] = pos[2] = 1;
+ last[1] = last[2] = false;
+}
+
+// Assumes that mValues is not empty
+bool LogEvent::checkPreviousValueType(Type expected) {
+ return mValues[mValues.size() - 1].mValue.getType() == expected;
+}
+
+void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
+ if (mValues.empty() || mValues.size() - 1 > INT8_MAX || !checkPreviousValueType(INT)
+ || annotationType != BOOL_TYPE) {
+ mValid = false;
+ return;
+ }
+
+ bool isUid = readNextValue<uint8_t>();
+ if (isUid) mUidFieldIndex = static_cast<int8_t>(mValues.size() - 1);
+ mValues[mValues.size() - 1].mAnnotations.setUidField(isUid);
+}
+
+void LogEvent::parseTruncateTimestampAnnotation(uint8_t annotationType) {
+ if (!mValues.empty() || annotationType != BOOL_TYPE) {
+ mValid = false;
+ return;
+ }
+
+ mTruncateTimestamp = readNextValue<uint8_t>();
+}
+
+void LogEvent::parsePrimaryFieldAnnotation(uint8_t annotationType) {
+ if (mValues.empty() || annotationType != BOOL_TYPE) {
+ mValid = false;
+ return;
+ }
+
+ const bool primaryField = readNextValue<uint8_t>();
+ mValues[mValues.size() - 1].mAnnotations.setPrimaryField(primaryField);
+}
+
+void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
+ int firstUidInChainIndex) {
+ if (mValues.empty() || annotationType != BOOL_TYPE || -1 == firstUidInChainIndex) {
+ mValid = false;
+ return;
+ }
+
+ if (static_cast<int>(mValues.size() - 1) < firstUidInChainIndex) { // AttributionChain is empty.
+ mValid = false;
+ android_errorWriteLog(0x534e4554, "174485572");
+ return;
+ }
+
+ const bool primaryField = readNextValue<uint8_t>();
+ mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField);
+}
+
+void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType) {
+ if (mValues.empty() || annotationType != BOOL_TYPE) {
+ mValid = false;
+ return;
+ }
+
+ if (mValues.size() - 1 > INT8_MAX) {
+ android_errorWriteLog(0x534e4554, "174488848");
+ mValid = false;
+ return;
+ }
+
+ const bool exclusiveState = readNextValue<uint8_t>();
+ mExclusiveStateFieldIndex = static_cast<int8_t>(mValues.size() - 1);
+ mValues[getExclusiveStateFieldIndex()].mAnnotations.setExclusiveState(exclusiveState);
+}
+
+void LogEvent::parseTriggerStateResetAnnotation(uint8_t annotationType) {
+ if (mValues.empty() || annotationType != INT32_TYPE) {
+ mValid = false;
+ return;
+ }
+
+ mResetState = readNextValue<int32_t>();
+}
+
+void LogEvent::parseStateNestedAnnotation(uint8_t annotationType) {
+ if (mValues.empty() || annotationType != BOOL_TYPE) {
+ mValid = false;
+ return;
+ }
+
+ bool nested = readNextValue<uint8_t>();
+ mValues[mValues.size() - 1].mAnnotations.setNested(nested);
+}
+
+// firstUidInChainIndex is a default parameter that is only needed when parsing
+// annotations for attribution chains.
+void LogEvent::parseAnnotations(uint8_t numAnnotations, int firstUidInChainIndex) {
+ for (uint8_t i = 0; i < numAnnotations; i++) {
+ uint8_t annotationId = readNextValue<uint8_t>();
+ uint8_t annotationType = readNextValue<uint8_t>();
+
+ switch (annotationId) {
+ case ANNOTATION_ID_IS_UID:
+ parseIsUidAnnotation(annotationType);
+ break;
+ case ANNOTATION_ID_TRUNCATE_TIMESTAMP:
+ parseTruncateTimestampAnnotation(annotationType);
+ break;
+ case ANNOTATION_ID_PRIMARY_FIELD:
+ parsePrimaryFieldAnnotation(annotationType);
+ break;
+ case ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID:
+ parsePrimaryFieldFirstUidAnnotation(annotationType, firstUidInChainIndex);
+ break;
+ case ANNOTATION_ID_EXCLUSIVE_STATE:
+ parseExclusiveStateAnnotation(annotationType);
+ break;
+ case ANNOTATION_ID_TRIGGER_STATE_RESET:
+ parseTriggerStateResetAnnotation(annotationType);
+ break;
+ case ANNOTATION_ID_STATE_NESTED:
+ parseStateNestedAnnotation(annotationType);
+ break;
+ default:
+ mValid = false;
+ return;
+ }
+ }
+}
+
+// This parsing logic is tied to the encoding scheme used in StatsEvent.java and
+// stats_event.c
+bool LogEvent::parseBuffer(uint8_t* buf, size_t len) {
+ mBuf = buf;
+ mRemainingLen = (uint32_t)len;
+
+ int32_t pos[] = {1, 1, 1};
+ bool last[] = {false, false, false};
+
+ // Beginning of buffer is OBJECT_TYPE | NUM_FIELDS | TIMESTAMP | ATOM_ID
+ uint8_t typeInfo = readNextValue<uint8_t>();
+ if (getTypeId(typeInfo) != OBJECT_TYPE) mValid = false;
+
+ uint8_t numElements = readNextValue<uint8_t>();
+ if (numElements < 2 || numElements > 127) mValid = false;
+
+ typeInfo = readNextValue<uint8_t>();
+ if (getTypeId(typeInfo) != INT64_TYPE) mValid = false;
+ mElapsedTimestampNs = readNextValue<int64_t>();
+ numElements--;
+
+ typeInfo = readNextValue<uint8_t>();
+ if (getTypeId(typeInfo) != INT32_TYPE) mValid = false;
+ mTagId = readNextValue<int32_t>();
+ numElements--;
+ parseAnnotations(getNumAnnotations(typeInfo)); // atom-level annotations
+
+ for (pos[0] = 1; pos[0] <= numElements && mValid; pos[0]++) {
+ last[0] = (pos[0] == numElements);
+
+ typeInfo = readNextValue<uint8_t>();
+ uint8_t typeId = getTypeId(typeInfo);
+
+ switch (typeId) {
+ case BOOL_TYPE:
+ parseBool(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case INT32_TYPE:
+ parseInt32(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case INT64_TYPE:
+ parseInt64(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case FLOAT_TYPE:
+ parseFloat(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case BYTE_ARRAY_TYPE:
+ parseByteArray(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case STRING_TYPE:
+ parseString(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case KEY_VALUE_PAIRS_TYPE:
+ parseKeyValuePairs(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case ATTRIBUTION_CHAIN_TYPE:
+ parseAttributionChain(pos, /*depth=*/0, last, getNumAnnotations(typeInfo));
+ break;
+ case ERROR_TYPE:
+ /* mErrorBitmask =*/ readNextValue<int32_t>();
+ mValid = false;
+ break;
+ default:
+ mValid = false;
+ break;
+ }
+ }
+
+ if (mRemainingLen != 0) mValid = false;
+ mBuf = nullptr;
+ return mValid;
+}
+
+uint8_t LogEvent::getTypeId(uint8_t typeInfo) {
+ return typeInfo & 0x0F; // type id in lower 4 bytes
+}
+
+uint8_t LogEvent::getNumAnnotations(uint8_t typeInfo) {
+ return (typeInfo >> 4) & 0x0F; // num annotations in upper 4 bytes
+}
+
+int64_t LogEvent::GetLong(size_t key, status_t* err) const {
+ // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
+ int field = getSimpleField(key);
+ for (const auto& value : mValues) {
+ if (value.mField.getField() == field) {
+ if (value.mValue.getType() == LONG) {
+ return value.mValue.long_value;
+ } else if (value.mValue.getType() == INT) {
+ return value.mValue.int_value;
+ } else {
+ *err = BAD_TYPE;
+ return 0;
+ }
+ }
+ if ((size_t)value.mField.getPosAtDepth(0) > key) {
+ break;
+ }
+ }
+
+ *err = BAD_INDEX;
+ return 0;
+}
+
+int LogEvent::GetInt(size_t key, status_t* err) const {
+ int field = getSimpleField(key);
+ for (const auto& value : mValues) {
+ if (value.mField.getField() == field) {
+ if (value.mValue.getType() == INT) {
+ return value.mValue.int_value;
+ } else {
+ *err = BAD_TYPE;
+ return 0;
+ }
+ }
+ if ((size_t)value.mField.getPosAtDepth(0) > key) {
+ break;
+ }
+ }
+
+ *err = BAD_INDEX;
+ return 0;
+}
+
+const char* LogEvent::GetString(size_t key, status_t* err) const {
+ int field = getSimpleField(key);
+ for (const auto& value : mValues) {
+ if (value.mField.getField() == field) {
+ if (value.mValue.getType() == STRING) {
+ return value.mValue.str_value.c_str();
+ } else {
+ *err = BAD_TYPE;
+ return 0;
+ }
+ }
+ if ((size_t)value.mField.getPosAtDepth(0) > key) {
+ break;
+ }
+ }
+
+ *err = BAD_INDEX;
+ return NULL;
+}
+
+bool LogEvent::GetBool(size_t key, status_t* err) const {
+ int field = getSimpleField(key);
+ for (const auto& value : mValues) {
+ if (value.mField.getField() == field) {
+ if (value.mValue.getType() == INT) {
+ return value.mValue.int_value != 0;
+ } else if (value.mValue.getType() == LONG) {
+ return value.mValue.long_value != 0;
+ } else {
+ *err = BAD_TYPE;
+ return false;
+ }
+ }
+ if ((size_t)value.mField.getPosAtDepth(0) > key) {
+ break;
+ }
+ }
+
+ *err = BAD_INDEX;
+ return false;
+}
+
+float LogEvent::GetFloat(size_t key, status_t* err) const {
+ int field = getSimpleField(key);
+ for (const auto& value : mValues) {
+ if (value.mField.getField() == field) {
+ if (value.mValue.getType() == FLOAT) {
+ return value.mValue.float_value;
+ } else {
+ *err = BAD_TYPE;
+ return 0.0;
+ }
+ }
+ if ((size_t)value.mField.getPosAtDepth(0) > key) {
+ break;
+ }
+ }
+
+ *err = BAD_INDEX;
+ return 0.0;
+}
+
+std::vector<uint8_t> LogEvent::GetStorage(size_t key, status_t* err) const {
+ int field = getSimpleField(key);
+ for (const auto& value : mValues) {
+ if (value.mField.getField() == field) {
+ if (value.mValue.getType() == STORAGE) {
+ return value.mValue.storage_value;
+ } else {
+ *err = BAD_TYPE;
+ return vector<uint8_t>();
+ }
+ }
+ if ((size_t)value.mField.getPosAtDepth(0) > key) {
+ break;
+ }
+ }
+
+ *err = BAD_INDEX;
+ return vector<uint8_t>();
+}
+
+string LogEvent::ToString() const {
+ string result;
+ result += StringPrintf("{ uid(%d) %lld %lld (%d)", mLogUid, (long long)mLogdTimestampNs,
+ (long long)mElapsedTimestampNs, mTagId);
+ for (const auto& value : mValues) {
+ result +=
+ StringPrintf("%#x", value.mField.getField()) + "->" + value.mValue.toString() + " ";
+ }
+ result += " }";
+ return result;
+}
+
+void LogEvent::ToProto(ProtoOutputStream& protoOutput) const {
+ writeFieldValueTreeToStream(mTagId, getValues(), &protoOutput);
+}
+
+bool LogEvent::hasAttributionChain(std::pair<int, int>* indexRange) const {
+ if (mAttributionChainStartIndex == -1 || mAttributionChainEndIndex == -1) {
+ return false;
+ }
+
+ if (nullptr != indexRange) {
+ indexRange->first = static_cast<int>(mAttributionChainStartIndex);
+ indexRange->second = static_cast<int>(mAttributionChainEndIndex);
+ }
+
+ return true;
+}
+
+void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds,
+ std::vector<uint8_t>* protoOut) {
+ ProtoOutputStream proto;
+ for (const auto& expId : experimentIds) {
+ proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
+ (long long)expId);
+ }
+
+ protoOut->resize(proto.size());
+ size_t pos = 0;
+ sp<ProtoReader> reader = proto.data();
+ while (reader->readBuffer() != NULL) {
+ size_t toRead = reader->currentToRead();
+ std::memcpy(protoOut->data() + pos, reader->readBuffer(), toRead);
+ pos += toRead;
+ reader->move(toRead);
+ }
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
new file mode 100644
index 0000000..aed2547
--- /dev/null
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -0,0 +1,481 @@
+// 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.
+
+#include "src/logd/LogEvent.h"
+
+#include <gtest/gtest.h>
+
+#include "frameworks/base/cmds/statsd/src/atoms.pb.h"
+#include "frameworks/base/core/proto/android/stats/launcher/launcher.pb.h"
+#include "log/log_event_list.h"
+#include "stats_event.h"
+
+#ifdef __ANDROID__
+
+namespace android {
+namespace os {
+namespace statsd {
+
+using std::string;
+using std::vector;
+using util::ProtoOutputStream;
+using util::ProtoReader;
+
+namespace {
+
+Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
+ Field f(tag, (int32_t*)pos.data(), depth);
+
+ // For loop starts at 1 because the last field at depth 0 is not decorated.
+ for (int i = 1; i < depth; i++) {
+ if (last[i]) f.decorateLastPos(i);
+ }
+
+ return f;
+}
+
+void createIntWithBoolAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
+ bool annotationValue) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
+ AStatsEvent_writeInt32(statsEvent, 10);
+ AStatsEvent_addBoolAnnotation(statsEvent, annotationId, annotationValue);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ EXPECT_TRUE(logEvent->parseBuffer(buf, size));
+
+ AStatsEvent_release(statsEvent);
+}
+
+void createIntWithIntAnnotationLogEvent(LogEvent* logEvent, uint8_t annotationId,
+ int annotationValue) {
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, /*atomId=*/100);
+ AStatsEvent_writeInt32(statsEvent, 10);
+ AStatsEvent_addInt32Annotation(statsEvent, annotationId, annotationValue);
+ AStatsEvent_build(statsEvent);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ EXPECT_TRUE(logEvent->parseBuffer(buf, size));
+
+ AStatsEvent_release(statsEvent);
+}
+
+} // anonymous namespace
+
+TEST(LogEventTest, TestPrimitiveParsing) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+ AStatsEvent_writeInt32(event, 10);
+ AStatsEvent_writeInt64(event, 0x123456789);
+ AStatsEvent_writeFloat(event, 2.0);
+ AStatsEvent_writeBool(event, true);
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
+ EXPECT_EQ(100, logEvent.GetTagId());
+ EXPECT_EQ(1000, logEvent.GetUid());
+ EXPECT_EQ(1001, logEvent.GetPid());
+ EXPECT_FALSE(logEvent.hasAttributionChain());
+
+ const vector<FieldValue>& values = logEvent.getValues();
+ ASSERT_EQ(4, values.size());
+
+ const FieldValue& int32Item = values[0];
+ Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
+ EXPECT_EQ(expectedField, int32Item.mField);
+ EXPECT_EQ(Type::INT, int32Item.mValue.getType());
+ EXPECT_EQ(10, int32Item.mValue.int_value);
+
+ const FieldValue& int64Item = values[1];
+ expectedField = getField(100, {2, 1, 1}, 0, {false, false, false});
+ EXPECT_EQ(expectedField, int64Item.mField);
+ EXPECT_EQ(Type::LONG, int64Item.mValue.getType());
+ EXPECT_EQ(0x123456789, int64Item.mValue.long_value);
+
+ const FieldValue& floatItem = values[2];
+ expectedField = getField(100, {3, 1, 1}, 0, {false, false, false});
+ EXPECT_EQ(expectedField, floatItem.mField);
+ EXPECT_EQ(Type::FLOAT, floatItem.mValue.getType());
+ EXPECT_EQ(2.0, floatItem.mValue.float_value);
+
+ const FieldValue& boolItem = values[3];
+ expectedField = getField(100, {4, 1, 1}, 0, {true, false, false});
+ EXPECT_EQ(expectedField, boolItem.mField);
+ EXPECT_EQ(Type::INT, boolItem.mValue.getType()); // FieldValue does not support boolean type
+ EXPECT_EQ(1, boolItem.mValue.int_value);
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestStringAndByteArrayParsing) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+ string str = "test";
+ AStatsEvent_writeString(event, str.c_str());
+ AStatsEvent_writeByteArray(event, (uint8_t*)str.c_str(), str.length());
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
+ EXPECT_EQ(100, logEvent.GetTagId());
+ EXPECT_EQ(1000, logEvent.GetUid());
+ EXPECT_EQ(1001, logEvent.GetPid());
+ EXPECT_FALSE(logEvent.hasAttributionChain());
+
+ const vector<FieldValue>& values = logEvent.getValues();
+ ASSERT_EQ(2, values.size());
+
+ const FieldValue& stringItem = values[0];
+ Field expectedField = getField(100, {1, 1, 1}, 0, {false, false, false});
+ EXPECT_EQ(expectedField, stringItem.mField);
+ EXPECT_EQ(Type::STRING, stringItem.mValue.getType());
+ EXPECT_EQ(str, stringItem.mValue.str_value);
+
+ const FieldValue& storageItem = values[1];
+ expectedField = getField(100, {2, 1, 1}, 0, {true, false, false});
+ EXPECT_EQ(expectedField, storageItem.mField);
+ EXPECT_EQ(Type::STORAGE, storageItem.mValue.getType());
+ vector<uint8_t> expectedValue = {'t', 'e', 's', 't'};
+ EXPECT_EQ(expectedValue, storageItem.mValue.storage_value);
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestEmptyString) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+ string empty = "";
+ AStatsEvent_writeString(event, empty.c_str());
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
+ EXPECT_EQ(100, logEvent.GetTagId());
+ EXPECT_EQ(1000, logEvent.GetUid());
+ EXPECT_EQ(1001, logEvent.GetPid());
+ EXPECT_FALSE(logEvent.hasAttributionChain());
+
+ const vector<FieldValue>& values = logEvent.getValues();
+ ASSERT_EQ(1, values.size());
+
+ const FieldValue& item = values[0];
+ Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
+ EXPECT_EQ(expectedField, item.mField);
+ EXPECT_EQ(Type::STRING, item.mValue.getType());
+ EXPECT_EQ(empty, item.mValue.str_value);
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestByteArrayWithNullCharacter) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+ uint8_t message[] = {'\t', 'e', '\0', 's', 't'};
+ AStatsEvent_writeByteArray(event, message, 5);
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
+ EXPECT_EQ(100, logEvent.GetTagId());
+ EXPECT_EQ(1000, logEvent.GetUid());
+ EXPECT_EQ(1001, logEvent.GetPid());
+
+ const vector<FieldValue>& values = logEvent.getValues();
+ ASSERT_EQ(1, values.size());
+
+ const FieldValue& item = values[0];
+ Field expectedField = getField(100, {1, 1, 1}, 0, {true, false, false});
+ EXPECT_EQ(expectedField, item.mField);
+ EXPECT_EQ(Type::STORAGE, item.mValue.getType());
+ vector<uint8_t> expectedValue(message, message + 5);
+ EXPECT_EQ(expectedValue, item.mValue.storage_value);
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestAttributionChain) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+
+ string tag1 = "tag1";
+ string tag2 = "tag2";
+
+ uint32_t uids[] = {1001, 1002};
+ const char* tags[] = {tag1.c_str(), tag2.c_str()};
+
+ AStatsEvent_writeAttributionChain(event, uids, tags, 2);
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+
+ EXPECT_EQ(100, logEvent.GetTagId());
+ EXPECT_EQ(1000, logEvent.GetUid());
+ EXPECT_EQ(1001, logEvent.GetPid());
+
+ const vector<FieldValue>& values = logEvent.getValues();
+ ASSERT_EQ(4, values.size()); // 2 per attribution node
+
+ std::pair<int, int> attrIndexRange;
+ EXPECT_TRUE(logEvent.hasAttributionChain(&attrIndexRange));
+ EXPECT_EQ(0, attrIndexRange.first);
+ EXPECT_EQ(3, attrIndexRange.second);
+
+ // Check first attribution node
+ const FieldValue& uid1Item = values[0];
+ Field expectedField = getField(100, {1, 1, 1}, 2, {true, false, false});
+ EXPECT_EQ(expectedField, uid1Item.mField);
+ EXPECT_EQ(Type::INT, uid1Item.mValue.getType());
+ EXPECT_EQ(1001, uid1Item.mValue.int_value);
+
+ const FieldValue& tag1Item = values[1];
+ expectedField = getField(100, {1, 1, 2}, 2, {true, false, true});
+ EXPECT_EQ(expectedField, tag1Item.mField);
+ EXPECT_EQ(Type::STRING, tag1Item.mValue.getType());
+ EXPECT_EQ(tag1, tag1Item.mValue.str_value);
+
+ // Check second attribution nodes
+ const FieldValue& uid2Item = values[2];
+ expectedField = getField(100, {1, 2, 1}, 2, {true, true, false});
+ EXPECT_EQ(expectedField, uid2Item.mField);
+ EXPECT_EQ(Type::INT, uid2Item.mValue.getType());
+ EXPECT_EQ(1002, uid2Item.mValue.int_value);
+
+ const FieldValue& tag2Item = values[3];
+ expectedField = getField(100, {1, 2, 2}, 2, {true, true, true});
+ EXPECT_EQ(expectedField, tag2Item.mField);
+ EXPECT_EQ(Type::STRING, tag2Item.mValue.getType());
+ EXPECT_EQ(tag2, tag2Item.mValue.str_value);
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestAnnotationIdIsUid) {
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_IS_UID, true);
+
+ const vector<FieldValue>& values = event.getValues();
+ ASSERT_EQ(values.size(), 1);
+ EXPECT_EQ(event.getUidFieldIndex(), 0);
+}
+
+TEST(LogEventTest, TestAnnotationIdStateNested) {
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_STATE_NESTED, true);
+
+ const vector<FieldValue>& values = event.getValues();
+ ASSERT_EQ(values.size(), 1);
+ EXPECT_TRUE(values[0].mAnnotations.isNested());
+}
+
+TEST(LogEventTest, TestPrimaryFieldAnnotation) {
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_PRIMARY_FIELD, true);
+
+ const vector<FieldValue>& values = event.getValues();
+ ASSERT_EQ(values.size(), 1);
+ EXPECT_TRUE(values[0].mAnnotations.isPrimaryField());
+}
+
+TEST(LogEventTest, TestExclusiveStateAnnotation) {
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ createIntWithBoolAnnotationLogEvent(&event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
+
+ const vector<FieldValue>& values = event.getValues();
+ ASSERT_EQ(values.size(), 1);
+ EXPECT_TRUE(values[0].mAnnotations.isExclusiveState());
+}
+
+TEST(LogEventTest, TestPrimaryFieldFirstUidAnnotation) {
+ // Event has 10 ints and then an attribution chain
+ int numInts = 10;
+ int firstUidInChainIndex = numInts;
+ string tag1 = "tag1";
+ string tag2 = "tag2";
+ uint32_t uids[] = {1001, 1002};
+ const char* tags[] = {tag1.c_str(), tag2.c_str()};
+
+ // Construct AStatsEvent
+ AStatsEvent* statsEvent = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(statsEvent, 100);
+ for (int i = 0; i < numInts; i++) {
+ AStatsEvent_writeInt32(statsEvent, 10);
+ }
+ AStatsEvent_writeAttributionChain(statsEvent, uids, tags, 2);
+ AStatsEvent_addBoolAnnotation(statsEvent, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
+ AStatsEvent_build(statsEvent);
+
+ // Construct LogEvent
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(statsEvent, &size);
+ LogEvent logEvent(/*uid=*/0, /*pid=*/0);
+ EXPECT_TRUE(logEvent.parseBuffer(buf, size));
+ AStatsEvent_release(statsEvent);
+
+ // Check annotation
+ const vector<FieldValue>& values = logEvent.getValues();
+ ASSERT_EQ(values.size(), numInts + 4);
+ EXPECT_TRUE(values[firstUidInChainIndex].mAnnotations.isPrimaryField());
+}
+
+TEST(LogEventTest, TestResetStateAnnotation) {
+ int32_t resetState = 10;
+ LogEvent event(/*uid=*/0, /*pid=*/0);
+ createIntWithIntAnnotationLogEvent(&event, ANNOTATION_ID_TRIGGER_STATE_RESET, resetState);
+
+ const vector<FieldValue>& values = event.getValues();
+ ASSERT_EQ(values.size(), 1);
+ EXPECT_EQ(event.getResetState(), resetState);
+}
+
+TEST(LogEventTest, TestExclusiveStateAnnotationAfterTooManyFields) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+
+ const unsigned int numAttributionNodes = 64;
+
+ uint32_t uids[numAttributionNodes];
+ const char* tags[numAttributionNodes];
+
+ for (unsigned int i = 1; i <= numAttributionNodes; i++) {
+ uids[i-1] = i;
+ tags[i-1] = std::to_string(i).c_str();
+ }
+
+ AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
+ AStatsEvent_writeInt32(event, 1);
+ AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
+
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_FALSE(logEvent.parseBuffer(buf, size));
+ EXPECT_EQ(-1, logEvent.getExclusiveStateFieldIndex());
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestUidAnnotationAfterTooManyFields) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+
+ const unsigned int numAttributionNodes = 64;
+
+ uint32_t uids[numAttributionNodes];
+ const char* tags[numAttributionNodes];
+
+ for (unsigned int i = 1; i <= numAttributionNodes; i++) {
+ uids[i-1] = i;
+ tags[i-1] = std::to_string(i).c_str();
+ }
+
+ AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
+ AStatsEvent_writeInt32(event, 1);
+ AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_IS_UID, true);
+
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_FALSE(logEvent.parseBuffer(buf, size));
+ EXPECT_EQ(-1, logEvent.getUidFieldIndex());
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestAttributionChainEndIndexAfterTooManyFields) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+
+ const unsigned int numAttributionNodes = 65;
+
+ uint32_t uids[numAttributionNodes];
+ const char* tags[numAttributionNodes];
+
+ for (unsigned int i = 1; i <= numAttributionNodes; i++) {
+ uids[i-1] = i;
+ tags[i-1] = std::to_string(i).c_str();
+ }
+
+ AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
+
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_FALSE(logEvent.parseBuffer(buf, size));
+ EXPECT_FALSE(logEvent.hasAttributionChain());
+
+ AStatsEvent_release(event);
+}
+
+TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) {
+ AStatsEvent* event = AStatsEvent_obtain();
+ AStatsEvent_setAtomId(event, 100);
+
+ uint32_t uids[] = {};
+ const char* tags[] = {};
+
+ AStatsEvent_writeInt32(event, 10);
+ AStatsEvent_writeAttributionChain(event, uids, tags, 0);
+ AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
+
+ AStatsEvent_build(event);
+
+ size_t size;
+ uint8_t* buf = AStatsEvent_getBuffer(event, &size);
+
+ LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
+ EXPECT_FALSE(logEvent.parseBuffer(buf, size));
+
+ AStatsEvent_release(event);
+}
+
+} // namespace statsd
+} // namespace os
+} // namespace android
+#else
+GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
diff --git a/config/OWNERS b/config/OWNERS
index 001038d..0691dbc 100644
--- a/config/OWNERS
+++ b/config/OWNERS
@@ -1,14 +1,8 @@
include /ZYGOTE_OWNERS
-# compat-team@ for changes to hiddenapi files
-
-per-file hiddenapi-* = andreionea@google.com, mathewi@google.com, satayev@google.com
-
# art-team@ manages the boot image profiles
per-file boot-* = calin@google.com, mathieuc@google.com, ngeoffray@google.com
per-file dirty-image-objects = calin@google.com, mathieuc@google.com, ngeoffray@google.com
per-file generate-preloaded-classes.sh = calin@google.com, mathieuc@google.com, ngeoffray@google.com
per-file preloaded-classes* = calin@google.com, mathieuc@google.com, ngeoffray@google.com
-# Escalations:
-per-file hiddenapi-* = bdc@google.com, narayan@google.com
diff --git a/core/api/current.txt b/core/api/current.txt
index 5a2b8bd..cc425f0 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29284,7 +29284,6 @@
field public static final String HARDWARE;
field public static final String HOST;
field public static final String ID;
- field public static final boolean IS_DEBUGGABLE;
field public static final String MANUFACTURER;
field public static final String MODEL;
field @NonNull public static final String ODM_SKU;
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index fe8b9d6..e7a7fd2 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -27,10 +27,6 @@
field public static final String TEST_NETWORK_SERVICE = "test_network";
}
- public class Intent implements java.lang.Cloneable android.os.Parcelable {
- field public static final String ACTION_CLEAR_DNS_CACHE = "android.intent.action.CLEAR_DNS_CACHE";
- }
-
}
package android.net {
@@ -121,6 +117,10 @@
method public final void markVintfStability();
}
+ public class Build {
+ method public static boolean isDebuggable();
+ }
+
public static class Build.VERSION {
field public static final int FIRST_SDK_INT;
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index d8ca055..1102a0d 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1480,6 +1480,7 @@
method public boolean disableBLE();
method public boolean enableBLE();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean enableNoAutoConnect();
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public long getDiscoveryEndMillis();
method public boolean isBleScanAlwaysAvailable();
method public boolean isLeEnabled();
@@ -1491,12 +1492,18 @@
field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2
field public static final int ACTIVE_DEVICE_AUDIO = 0; // 0x0
field public static final int ACTIVE_DEVICE_PHONE_CALL = 1; // 0x1
+ field public static final int OOB_ERROR_ADAPTER_DISABLED = 2; // 0x2
+ field public static final int OOB_ERROR_ANOTHER_ACTIVE_REQUEST = 1; // 0x1
+ field public static final int OOB_ERROR_UNKNOWN = 0; // 0x0
}
public static interface BluetoothAdapter.OnMetadataChangedListener {
method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
}
+ public static interface BluetoothAdapter.OobDataCallback {
+ }
+
public final class BluetoothDevice implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean cancelBondProcess();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
@@ -6808,14 +6815,14 @@
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int) throws java.lang.RuntimeException;
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiBatchedScanStartedFromSource(@NonNull android.os.WorkSource, @IntRange(from=0) int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiBatchedScanStoppedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiMulticastDisabled(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiMulticastEnabled(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiOff();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiOn();
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRadioPowerState(boolean, int) throws java.lang.RuntimeException;
+ method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRadioPowerState(boolean, int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiRssiChanged(@IntRange(from=0xffffff81, to=0) int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiScanStartedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportWifiScanStoppedFromSource(@NonNull android.os.WorkSource);
@@ -7307,7 +7314,7 @@
method @NonNull public static String formatUid(int);
method public static int getAppId(int);
method public int getIdentifier();
- method public static int getUid(@NonNull android.os.UserHandle, int);
+ method public int getUid(int);
method @Deprecated public boolean isOwner();
method public boolean isSystem();
method public static int myUserId();
@@ -8128,7 +8135,7 @@
}
public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
- method @Nullable public int[] getAttestationIds();
+ method @NonNull public int[] getAttestationIds();
method public int getNamespace();
}
@@ -11895,7 +11902,8 @@
}
public interface SipDelegateConnection {
- method public void closeDialog(@NonNull String);
+ method public default void cleanupSession(@NonNull String);
+ method @Deprecated public default void closeDialog(@NonNull String);
method public void notifyMessageReceiveError(@NonNull String, int);
method public void notifyMessageReceived(@NonNull String);
method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long);
@@ -11996,7 +12004,6 @@
method public int describeContents();
method @Nullable public String getCallIdParameter();
method @NonNull public byte[] getContent();
- method @Deprecated @NonNull public byte[] getEncodedMessage();
method @NonNull public String getHeaderSection();
method @NonNull public String getStartLine();
method @NonNull public String getViaBranchParameter();
@@ -12345,7 +12352,8 @@
}
public interface SipDelegate {
- method public void closeDialog(@NonNull String);
+ method public default void cleanupSession(@NonNull String);
+ method @Deprecated public default void closeDialog(@NonNull String);
method public void notifyMessageReceiveError(@NonNull String, int);
method public void notifyMessageReceived(@NonNull String);
method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long);
@@ -12504,7 +12512,7 @@
public final class DistanceMeasurement implements android.os.Parcelable {
method public int describeContents();
method @FloatRange(from=0.0, to=1.0) public double getConfidenceLevel();
- method public double getErrorMeters();
+ method @FloatRange(from=0.0) public double getErrorMeters();
method public double getMeters();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.uwb.DistanceMeasurement> CREATOR;
@@ -12513,8 +12521,8 @@
public static final class DistanceMeasurement.Builder {
ctor public DistanceMeasurement.Builder();
method @NonNull public android.uwb.DistanceMeasurement build();
- method @NonNull public android.uwb.DistanceMeasurement.Builder setConfidenceLevel(double);
- method @NonNull public android.uwb.DistanceMeasurement.Builder setErrorMeters(double);
+ method @NonNull public android.uwb.DistanceMeasurement.Builder setConfidenceLevel(@FloatRange(from=0.0, to=1.0) double);
+ method @NonNull public android.uwb.DistanceMeasurement.Builder setErrorMeters(@FloatRange(from=0.0) double);
method @NonNull public android.uwb.DistanceMeasurement.Builder setMeters(double);
}
@@ -12573,7 +12581,7 @@
method public void onStartFailed(int, @NonNull android.os.PersistableBundle);
method public void onStarted(@NonNull android.os.PersistableBundle);
method public void onStopFailed(int, @NonNull android.os.PersistableBundle);
- method public void onStopped();
+ method public void onStopped(int, @NonNull android.os.PersistableBundle);
field public static final int REASON_BAD_PARAMETERS = 3; // 0x3
field public static final int REASON_GENERIC_ERROR = 4; // 0x4
field public static final int REASON_LOCAL_REQUEST = 1; // 0x1
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 0c57f4e..f7b101d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1022,6 +1022,7 @@
public class Build {
method public static boolean is64BitAbi(String);
+ method public static boolean isDebuggable();
field public static final boolean IS_EMULATOR;
}
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 919f1e2..965665d 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -127,3 +127,269 @@
],
visibility: ["//frameworks/base/test-mock"],
}
+
+filegroup {
+ name: "libincident_aidl",
+ srcs: [
+ "android/os/IIncidentDumpCallback.aidl",
+ "android/os/IIncidentManager.aidl",
+ "android/os/IIncidentReportStatusListener.aidl",
+ ],
+}
+
+filegroup {
+ name: "libvibrator_aidl",
+ srcs: [
+ "android/os/IExternalVibrationController.aidl",
+ "android/os/IExternalVibratorService.aidl",
+ ],
+}
+
+filegroup {
+ name: "libpowermanager_aidl",
+ srcs: [
+ "android/os/Temperature.aidl",
+ "android/os/CoolingDevice.aidl",
+ "android/os/IThermalEventListener.aidl",
+ "android/os/IThermalStatusListener.aidl",
+ "android/os/IThermalService.aidl",
+ ],
+}
+
+genrule {
+ name: "statslog-framework-java-gen",
+ tools: ["stats-log-api-gen"],
+ cmd: "$(location stats-log-api-gen) --java $(out) --module framework" +
+ " --javaPackage com.android.internal.util --javaClass FrameworkStatsLog --worksource",
+ out: ["com/android/internal/util/FrameworkStatsLog.java"],
+}
+
+java_library {
+ name: "uieventloggerlib",
+ srcs: [
+ "com/android/internal/logging/UiEvent.java",
+ "com/android/internal/logging/UiEventLogger.java",
+ "com/android/internal/logging/UiEventLoggerImpl.java",
+ "com/android/internal/logging/InstanceId.java",
+ "com/android/internal/logging/InstanceIdSequence.java",
+ ":statslog-framework-java-gen",
+ ],
+}
+
+filegroup {
+ name: "framework-services-net-module-wifi-shared-srcs",
+ srcs: [
+ "android/net/DhcpResults.java",
+ "android/util/LocalLog.java",
+ ],
+}
+
+// keep these files in sync with the package/Tethering/jarjar-rules.txt and
+// package/Connectivity/jarjar-rules.txt for the tethering module and connectivity module.
+filegroup {
+ name: "framework-connectivity-shared-srcs",
+ srcs: [
+ "android/util/LocalLog.java",
+ // This should be android.util.IndentingPrintWriter, but it's not available in all branches.
+ "com/android/internal/util/IndentingPrintWriter.java",
+ "com/android/internal/util/IState.java",
+ "com/android/internal/util/MessageUtils.java",
+ "com/android/internal/util/State.java",
+ "com/android/internal/util/StateMachine.java",
+ "com/android/internal/util/WakeupMessage.java",
+ ],
+}
+
+filegroup {
+ name: "incremental_aidl",
+ srcs: [
+ "android/os/incremental/IIncrementalServiceConnector.aidl",
+ "android/os/incremental/IncrementalFileSystemControlParcel.aidl",
+ ],
+}
+
+filegroup {
+ name: "dataloader_aidl",
+ srcs: [
+ "android/content/pm/DataLoaderParamsParcel.aidl",
+ "android/content/pm/DataLoaderType.aidl",
+ "android/content/pm/FileSystemControlParcel.aidl",
+ "android/content/pm/IDataLoader.aidl",
+ "android/content/pm/IDataLoaderManager.aidl",
+ "android/content/pm/InstallationFileParcel.aidl",
+ "android/content/pm/InstallationFileLocation.aidl",
+ "android/content/pm/IDataLoaderStatusListener.aidl",
+ "android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
+ ],
+}
+
+filegroup {
+ name: "incremental_manager_aidl",
+ srcs: [
+ "android/os/incremental/IIncrementalService.aidl",
+ "android/os/incremental/IncrementalNewFileParams.aidl",
+ "android/os/incremental/IStorageHealthListener.aidl",
+ "android/os/incremental/StorageHealthCheckParams.aidl",
+ ],
+}
+
+filegroup {
+ name: "activity_manager_procstate_aidl",
+ srcs: [
+ // internal only
+ ],
+}
+
+aidl_interface {
+ name: "libincremental_aidl",
+ unstable: true,
+ srcs: [
+ ":incremental_aidl",
+ ],
+ backend: {
+ java: {
+ sdk_version: "28",
+ },
+ cpp: {
+ enabled: true,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
+}
+
+aidl_interface {
+ name: "libdataloader_aidl",
+ unstable: true,
+ srcs: [
+ ":dataloader_aidl",
+ ],
+ imports: [
+ "libincremental_aidl",
+ ],
+ backend: {
+ java: {
+ sdk_version: "28",
+ },
+ cpp: {
+ enabled: true,
+ },
+ ndk: {
+ enabled: false,
+ },
+ },
+}
+
+aidl_interface {
+ name: "libincremental_manager_aidl",
+ unstable: true,
+ srcs: [
+ ":incremental_manager_aidl",
+ ],
+ imports: [
+ "libincremental_aidl",
+ "libdataloader_aidl",
+ ],
+ backend: {
+ java: {
+ sdk_version: "28",
+ },
+ cpp: {
+ enabled: true,
+ },
+ ndk: {
+ enabled: false,
+ },
+ },
+}
+
+// Build Rust bindings for PermissionController. Needed by keystore2.
+aidl_interface {
+ name: "android.os.permissions_aidl",
+ unstable: true,
+ local_include_dir: ".",
+ srcs: [
+ "android/os/IPermissionController.aidl",
+ ],
+ backend: {
+ rust: {
+ enabled: true,
+ },
+ },
+}
+
+// Avoid including Parcelable classes as we don't want to have two copies of
+// Parcelable cross the libraries. This is used by telephony-common (frameworks/opt/telephony)
+// and TeleService app (packages/services/Telephony).
+filegroup {
+ name: "framework-telephony-common-shared-srcs",
+ srcs: [
+ "android/os/RegistrantList.java",
+ "android/os/Registrant.java",
+ "android/util/LocalLog.java",
+ "android/util/TimeUtils.java",
+ "com/android/internal/os/SomeArgs.java",
+ "com/android/internal/util/AsyncChannel.java",
+ "com/android/internal/util/AsyncService.java",
+ "com/android/internal/util/BitwiseInputStream.java",
+ "com/android/internal/util/FastXmlSerializer.java",
+ "com/android/internal/util/HexDump.java",
+ "com/android/internal/util/IState.java",
+ "com/android/internal/util/IndentingPrintWriter.java",
+ "com/android/internal/util/Preconditions.java",
+ "com/android/internal/util/State.java",
+ "com/android/internal/util/StateMachine.java",
+ "com/android/internal/util/UserIcons.java",
+ ],
+}
+
+// Avoid including Parcelable classes as we don't want to have two copies of
+// Parcelable cross the process.
+filegroup {
+ name: "framework-cellbroadcast-shared-srcs",
+ srcs: [
+ "android/os/HandlerExecutor.java",
+ "android/util/LocalLog.java",
+ "com/android/internal/util/IState.java",
+ "com/android/internal/util/Preconditions.java",
+ "com/android/internal/util/State.java",
+ "com/android/internal/util/StateMachine.java",
+ ],
+}
+
+filegroup {
+ name: "framework-ims-common-shared-srcs",
+ srcs: [
+ "android/os/RegistrantList.java",
+ "android/os/Registrant.java",
+ "com/android/internal/os/SomeArgs.java",
+ "com/android/internal/util/Preconditions.java",
+ ],
+}
+
+filegroup {
+ name: "framework-wifi-util-lib-aidls",
+ srcs: ["android/content/pm/ParceledListSlice.aidl"],
+}
+
+// utility classes statically linked into wifi-service
+filegroup {
+ name: "framework-wifi-service-shared-srcs",
+ srcs: [
+ "android/net/InterfaceConfiguration.java",
+ "android/util/BackupUtils.java",
+ "android/util/Rational.java",
+ "com/android/internal/util/FastXmlSerializer.java",
+ "com/android/internal/util/HexDump.java",
+ "com/android/internal/util/IState.java",
+ "com/android/internal/util/MessageUtils.java",
+ "com/android/internal/util/State.java",
+ "com/android/internal/util/StateMachine.java",
+ "com/android/internal/util/WakeupMessage.java",
+ ],
+ visibility: [
+ "//frameworks/opt/net/wifi/service",
+ "//packages/modules/Wifi/service",
+ ],
+}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 694c519..c4cdbbc 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -7636,8 +7636,8 @@
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
&& (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
- myUid) == PackageManager.PERMISSION_GRANTED
- || isTrustedVoiceServiceProxy(mContext, mContext.getOpPackageName(), op))) {
+ myUid) == PackageManager.PERMISSION_GRANTED || isTrustedVoiceServiceProxy(
+ mContext, mContext.getOpPackageName(), op, mContext.getUserId()))) {
collectNotedOpSync(op, proxiedAttributionTag);
}
}
@@ -7655,7 +7655,7 @@
* @hide
*/
public static boolean isTrustedVoiceServiceProxy(Context context, String packageName,
- int code) {
+ int code, int userId) {
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
if (code != OP_RECORD_AUDIO) {
@@ -7667,7 +7667,7 @@
final String voiceRecognitionServicePackageName =
getComponentPackageNameFromString(voiceRecognitionComponent);
return (Objects.equals(packageName, voiceRecognitionServicePackageName))
- && isPackagePreInstalled(context, packageName);
+ && isPackagePreInstalled(context, packageName, userId);
}
private static String getComponentPackageNameFromString(String from) {
@@ -7675,10 +7675,10 @@
return componentName != null ? componentName.getPackageName() : "";
}
- private static boolean isPackagePreInstalled(Context context, String packageName) {
+ private static boolean isPackagePreInstalled(Context context, String packageName, int userId) {
try {
final PackageManager pm = context.getPackageManager();
- final ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
+ final ApplicationInfo info = pm.getApplicationInfoAsUser(packageName, 0, userId);
return ((info.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
} catch (PackageManager.NameNotFoundException e) {
return false;
diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl
index 7713e25..74018a8 100644
--- a/core/java/android/app/IUidObserver.aidl
+++ b/core/java/android/app/IUidObserver.aidl
@@ -24,7 +24,7 @@
// below block of transactions.
// Since these transactions are also called from native code, these must be kept in sync with
- // the ones in frameworks/native/include/binder/IActivityManager.h
+ // the ones in frameworks/native/include_activitymanager/binder/IActivityManager.h
// =============== Beginning of transactions used on native side as well ======================
/**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 38863c2..7d62327 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -28,6 +28,7 @@
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.PropertyInvalidatedCache;
+import android.bluetooth.BluetoothDevice.Transport;
import android.bluetooth.BluetoothProfile.ConnectionPolicy;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
@@ -3013,6 +3014,168 @@
return false;
}
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "OOB_ERROR_" }, value = {
+ OOB_ERROR_UNKNOWN,
+ OOB_ERROR_ANOTHER_ACTIVE_REQUEST,
+ OOB_ERROR_ADAPTER_DISABLED
+ })
+ public @interface OobError {}
+
+ /**
+ * An unknown error has occurred in the controller, stack, or callback pipeline.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int OOB_ERROR_UNKNOWN = 0;
+
+ /**
+ * If another application has already requested {@link OobData} then another fetch will be
+ * disallowed until the callback is removed.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int OOB_ERROR_ANOTHER_ACTIVE_REQUEST = 1;
+
+ /**
+ * The adapter is currently disabled, please enable it.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int OOB_ERROR_ADAPTER_DISABLED = 2;
+
+ /**
+ * Provides callback methods for receiving {@link OobData} from the host stack, as well as an
+ * error interface in order to allow the caller to determine next steps based on the {@link
+ * ErrorCode}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public interface OobDataCallback {
+ /**
+ * Handles the {@link OobData} received from the host stack.
+ *
+ * @param transport - whether the {@link OobData} is generated for LE or Classic.
+ * @param oobData - data generated in the host stack(LE) or controller (Classic)
+ *
+ * @hide
+ */
+ void onOobData(@Transport int transport, @Nullable OobData oobData);
+
+ /**
+ * Provides feedback when things don't go as expected.
+ *
+ * @param errorCode - the code descibing the type of error that occurred.
+ *
+ * @hide
+ */
+ void onError(@OobError int errorCode);
+ }
+
+ /**
+ * Wraps an AIDL interface around an {@link OobDataCallback} interface.
+ *
+ * @see {@link IBluetoothOobDataCallback} for interface definition.
+ *
+ * @hide
+ */
+ public class WrappedOobDataCallback extends IBluetoothOobDataCallback.Stub {
+ private final OobDataCallback mCallback;
+ private final Executor mExecutor;
+
+ /**
+ * @param callback - object to receive {@link OobData} must be a non null argument
+ *
+ * @throws NullPointerException if the callback is null.
+ */
+ WrappedOobDataCallback(@NonNull OobDataCallback callback,
+ @NonNull @CallbackExecutor Executor executor) {
+ Preconditions.checkNotNull(callback);
+ Preconditions.checkNotNull(executor);
+ mCallback = callback;
+ mExecutor = executor;
+ }
+ /**
+ * Wrapper function to relay to the {@link OobDataCallback#onOobData}
+ *
+ * @param transport - whether the {@link OobData} is generated for LE or Classic.
+ * @param oobData - data generated in the host stack(LE) or controller (Classic)
+ *
+ * @hide
+ */
+ public void onOobData(@Transport int transport, OobData oobData) {
+ mExecutor.execute(new Runnable() {
+ public void run() {
+ mCallback.onOobData(transport, oobData);
+ }
+ });
+ }
+ /**
+ * Wrapper function to relay to the {@link OobDataCallback#onError}
+ *
+ * @param errorCode - the code descibing the type of error that occurred.
+ *
+ * @hide
+ */
+ public void onError(@OobError int errorCode) {
+ mExecutor.execute(new Runnable() {
+ public void run() {
+ mCallback.onError(errorCode);
+ }
+ });
+ }
+ }
+
+ /**
+ * Fetches a secret data value that can be used for a secure and simple pairing experience.
+ *
+ * <p>This is the Local Out of Band data the comes from the
+ *
+ * <p>This secret is the local Out of Band data. This data is used to securely and quickly
+ * pair two devices with minimal user interaction.
+ *
+ * <p>For example, this secret can be transferred to a remote device out of band (meaning any
+ * other way besides using bluetooth). Once the remote device finds this device using the
+ * information given in the data, such as the PUBLIC ADDRESS, the remote device could then
+ * connect to this device using this secret when the pairing sequenece asks for the secret.
+ * This device will respond by automatically accepting the pairing due to the secret being so
+ * trustworthy.
+ *
+ * @param transport - provide type of transport (e.g. LE or Classic).
+ * @param callback - target object to receive the {@link OobData} value.
+ *
+ * @throws NullPointerException if callback is null.
+ * @throws IllegalArgumentException if the transport is not valid.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ public void generateLocalOobData(@Transport int transport,
+ @NonNull @CallbackExecutor Executor executor, @NonNull OobDataCallback callback) {
+ if (transport != BluetoothDevice.TRANSPORT_BREDR && transport
+ != BluetoothDevice.TRANSPORT_LE) {
+ throw new IllegalArgumentException("Invalid transport '" + transport + "'!");
+ }
+ Preconditions.checkNotNull(callback);
+ if (!isEnabled()) {
+ Log.w(TAG, "generateLocalOobData(): Adapter isn't enabled!");
+ callback.onError(OOB_ERROR_ADAPTER_DISABLED);
+ } else {
+ try {
+ mService.generateLocalOobData(transport, new WrappedOobDataCallback(callback,
+ executor));
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ }
+
/**
* Enable control of the Bluetooth Adapter for a single application.
*
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index c30b8af..a40bf34 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -931,6 +931,21 @@
@SystemApi
public static final int ACCESS_REJECTED = 2;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(
+ prefix = { "TRANSPORT_" },
+ value = {
+ /** Allow host to automatically select a transport (dual-mode only) */
+ TRANSPORT_AUTO,
+ /** Use Classic or BR/EDR transport.*/
+ TRANSPORT_BREDR,
+ /** Use Low Energy transport.*/
+ TRANSPORT_LE,
+ }
+ )
+ public @interface Transport {}
+
/**
* No preference of physical transport for GATT connections to remote dual-mode devices
*/
@@ -1063,6 +1078,10 @@
public void onBrEdrDown() {
if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state");
}
+
+ public void onOobData(@Transport int transport, OobData oobData) {
+ if (DBG) Log.d(TAG, "onOobData: got data");
+ }
};
/**
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4d68e90..0fad63f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2324,14 +2324,6 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED";
/**
- * Clear DNS Cache Action: This is broadcast when networks have changed and old
- * DNS entries should be tossed.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public static final String ACTION_CLEAR_DNS_CACHE = "android.intent.action.CLEAR_DNS_CACHE";
- /**
* Alarm Changed Action: This is broadcast when the AlarmClock
* application's alarm is set or unset. It is used by the
* AlarmClock application and the StatusBar service.
diff --git a/core/java/android/net/EthernetNetworkSpecifier.java b/core/java/android/net/EthernetNetworkSpecifier.java
index e168588..62c5761 100644
--- a/core/java/android/net/EthernetNetworkSpecifier.java
+++ b/core/java/android/net/EthernetNetworkSpecifier.java
@@ -42,15 +42,22 @@
@NonNull
private final String mInterfaceName;
+ /**
+ * Create a new EthernetNetworkSpecifier.
+ * @param interfaceName Name of the ethernet interface the specifier refers to.
+ */
public EthernetNetworkSpecifier(@NonNull String interfaceName) {
Preconditions.checkStringNotEmpty(interfaceName);
mInterfaceName = interfaceName;
}
- // This may be null in the future to support specifiers based on data other than the interface
- // name.
+ /**
+ * Get the name of the ethernet interface the specifier refers to.
+ */
@Nullable
public String getInterfaceName() {
+ // This may be null in the future to support specifiers based on data other than the
+ // interface name.
return mInterfaceName;
}
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 3f4a218..f5172cf 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -386,10 +386,9 @@
* @param uid Uid of this event. For the active state it represents the uid that was responsible
* for waking the radio, or -1 if the system was responsible for waking the radio.
* For inactive state, the UID should always be -1.
- * @throws RuntimeException if there are binder remote-invocation errors.
*/
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
- public void reportMobileRadioPowerState(boolean isActive, int uid) throws RuntimeException {
+ public void reportMobileRadioPowerState(boolean isActive, int uid) {
try {
mBatteryStats.noteMobileRadioPowerState(getDataConnectionPowerState(isActive),
SystemClock.elapsedRealtimeNanos(), uid);
@@ -405,10 +404,9 @@
* @param uid Uid of this event. For the active state it represents the uid that was responsible
* for waking the radio, or -1 if the system was responsible for waking the radio.
* For inactive state, the UID should always be -1.
- * @throws RuntimeException if there are binder remote-invocation errors.
*/
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
- public void reportWifiRadioPowerState(boolean isActive, int uid) throws RuntimeException {
+ public void reportWifiRadioPowerState(boolean isActive, int uid) {
try {
mBatteryStats.noteWifiRadioPowerState(getDataConnectionPowerState(isActive),
SystemClock.elapsedRealtimeNanos(), uid);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 03caafd..e47ffcc 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1309,10 +1309,25 @@
* Debuggable builds allow users to gain root access via local shell, attach debuggers to any
* application regardless of whether they have the "debuggable" attribute set, or downgrade
* selinux into "permissive" mode in particular.
+ * @hide
*/
public static final boolean IS_DEBUGGABLE =
SystemProperties.getInt("ro.debuggable", 0) == 1;
+ /**
+ * Returns true if the device is running a debuggable build such as "userdebug" or "eng".
+ *
+ * Debuggable builds allow users to gain root access via local shell, attach debuggers to any
+ * application regardless of whether they have the "debuggable" attribute set, or downgrade
+ * selinux into "permissive" mode in particular.
+ * @hide
+ */
+ @TestApi
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static boolean isDebuggable() {
+ return IS_DEBUGGABLE;
+ }
+
/** {@hide} */
public static final boolean IS_ENG = "eng".equals(TYPE);
/** {@hide} */
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 7b62e66..d065d7a 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -303,16 +303,15 @@
}
/**
- * Returns the uid that is composed from the userHandle and the appId.
+ * Returns the uid representing the given appId for this UserHandle.
*
- * @param userHandle the UserHandle to compose the uid
* @param appId the AppId to compose the uid
- * @return the uid that is composed from the userHandle and the appId
+ * @return the uid representing the given appId for this UserHandle
* @hide
*/
@SystemApi
- public static int getUid(@NonNull UserHandle userHandle, @AppIdInt int appId) {
- return getUid(userHandle.getIdentifier(), appId);
+ public int getUid(@AppIdInt int appId) {
+ return getUid(getIdentifier(), appId);
}
/**
diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java
index 2a9bbdf..9856553 100644
--- a/core/java/android/uwb/DistanceMeasurement.java
+++ b/core/java/android/uwb/DistanceMeasurement.java
@@ -60,6 +60,7 @@
*
* @return error of distance measurement in meters
*/
+ @FloatRange(from = 0.0)
public double getErrorMeters() {
return mErrorMeters;
}
@@ -162,7 +163,7 @@
* @throws IllegalArgumentException if error is negative or NaN
*/
@NonNull
- public Builder setErrorMeters(double errorMeters) {
+ public Builder setErrorMeters(@FloatRange(from = 0.0) double errorMeters) {
if (Double.isNaN(errorMeters) || errorMeters < 0.0) {
throw new IllegalArgumentException(
"errorMeters must be >= 0.0 and not NaN: " + errorMeters);
@@ -178,7 +179,8 @@
* @throws IllegalArgumentException if confidence level is not in the range of [0.0, 1.0]
*/
@NonNull
- public Builder setConfidenceLevel(double confidenceLevel) {
+ public Builder setConfidenceLevel(
+ @FloatRange(from = 0.0, to = 1.0) double confidenceLevel) {
if (confidenceLevel < 0.0 || confidenceLevel > 1.0) {
throw new IllegalArgumentException(
"confidenceLevel must be in the range [0.0, 1.0]: " + confidenceLevel);
diff --git a/core/java/android/uwb/IUwbAdapter.aidl b/core/java/android/uwb/IUwbAdapter.aidl
index 4036892..30da248 100644
--- a/core/java/android/uwb/IUwbAdapter.aidl
+++ b/core/java/android/uwb/IUwbAdapter.aidl
@@ -160,14 +160,4 @@
* closed.
*/
const int RANGING_SESSION_CLOSE_THRESHOLD_MS = 3000; // Value TBD
-
- /**
- * Ranging scheduling time unit (RSTU) for High Rate Pulse (HRP) PHY
- */
- const int HIGH_RATE_PULSE_CHIRPS_PER_RSTU = 416;
-
- /**
- * Ranging scheduling time unit (RSTU) for Low Rate Pulse (LRP) PHY
- */
- const int LOW_RATE_PULSE_CHIRPS_PER_RSTU = 1;
}
diff --git a/core/java/android/uwb/IUwbRangingCallbacks.aidl b/core/java/android/uwb/IUwbRangingCallbacks.aidl
index f71f3ff..f15debb 100644
--- a/core/java/android/uwb/IUwbRangingCallbacks.aidl
+++ b/core/java/android/uwb/IUwbRangingCallbacks.aidl
@@ -92,9 +92,13 @@
* Called when the ranging session has been stopped
*
* @param sessionHandle the session the callback is being invoked for
+ * @param reason the reason the session was stopped
+ * @param parameters protocol specific parameters
*/
- void onRangingStopped(in SessionHandle sessionHandle);
+ void onRangingStopped(in SessionHandle sessionHandle,
+ RangingChangeReason reason,
+ in PersistableBundle parameters);
/**
* Called when a ranging session fails to stop
diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java
index 85f2c1c..e2c64a7 100644
--- a/core/java/android/uwb/RangingManager.java
+++ b/core/java/android/uwb/RangingManager.java
@@ -165,7 +165,8 @@
}
@Override
- public void onRangingStopped(SessionHandle sessionHandle) {
+ public void onRangingStopped(SessionHandle sessionHandle, @RangingChangeReason int reason,
+ PersistableBundle params) {
synchronized (this) {
if (!hasSession(sessionHandle)) {
Log.w(TAG, "onRangingStopped - received unexpected SessionHandle: "
@@ -174,7 +175,7 @@
}
RangingSession session = mRangingSessionTable.get(sessionHandle);
- session.onRangingStopped();
+ session.onRangingStopped(convertToReason(reason), params);
}
}
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
index 52ec5bd..345b69d 100644
--- a/core/java/android/uwb/RangingSession.java
+++ b/core/java/android/uwb/RangingSession.java
@@ -191,8 +191,11 @@
/**
* Invoked when a request to stop the session succeeds
+ *
+ * @param reason reason for the session stop
+ * @param parameters protocol specific parameters related to the stop reason
*/
- void onStopped();
+ void onStopped(@Reason int reason, @NonNull PersistableBundle parameters);
/**
* Invoked when a request to stop the session fails
@@ -434,14 +437,15 @@
/**
* @hide
*/
- public void onRangingStopped() {
+ public void onRangingStopped(@Callback.Reason int reason,
+ @NonNull PersistableBundle params) {
if (mState == State.CLOSED) {
Log.w(TAG, "onRangingStopped invoked for a closed session");
return;
}
mState = State.IDLE;
- executeCallback(() -> mCallback.onStopped());
+ executeCallback(() -> mCallback.onStopped(reason, params));
}
/**
diff --git a/core/java/com/android/internal/os/ZygoteCommandBuffer.java b/core/java/com/android/internal/os/ZygoteCommandBuffer.java
index b61ae7a..83a68ca 100644
--- a/core/java/com/android/internal/os/ZygoteCommandBuffer.java
+++ b/core/java/com/android/internal/os/ZygoteCommandBuffer.java
@@ -176,7 +176,7 @@
/*
* Repeatedly fork children as above. It commonly does not return in the parent, but it may.
- * @return true in the chaild, false in the parent if we encounter a command we couldn't handle.
+ * @return true in the child, false in the parent if we encounter a command we couldn't handle.
*/
private static native boolean nativeForkRepeatedly(long /* NativeCommandBuffer* */ nbuffer,
int zygoteSocketRawFd,
diff --git a/core/java/com/android/internal/util/ScreenshotHelper.java b/core/java/com/android/internal/util/ScreenshotHelper.java
index a23fc4b..7ee846e 100644
--- a/core/java/com/android/internal/util/ScreenshotHelper.java
+++ b/core/java/com/android/internal/util/ScreenshotHelper.java
@@ -1,12 +1,15 @@
package com.android.internal.util;
+import static android.content.Intent.ACTION_USER_SWITCHED;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.graphics.Insets;
import android.graphics.Rect;
@@ -161,8 +164,21 @@
private ServiceConnection mScreenshotConnection = null;
private final Context mContext;
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mScreenshotLock) {
+ if (ACTION_USER_SWITCHED.equals(intent.getAction())) {
+ resetConnection();
+ }
+ }
+ }
+ };
+
public ScreenshotHelper(Context context) {
mContext = context;
+ IntentFilter filter = new IntentFilter(ACTION_USER_SWITCHED);
+ mContext.registerReceiver(mBroadcastReceiver, filter);
}
/**
@@ -279,9 +295,8 @@
final Runnable mScreenshotTimeout = () -> {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
- mContext.unbindService(mScreenshotConnection);
- mScreenshotConnection = null;
- mScreenshotService = null;
+ Log.e(TAG, "Timed out before getting screenshot capture response");
+ resetConnection();
notifyScreenshotError();
}
}
@@ -304,11 +319,7 @@
break;
case SCREENSHOT_MSG_PROCESS_COMPLETE:
synchronized (mScreenshotLock) {
- if (mScreenshotConnection != null) {
- mContext.unbindService(mScreenshotConnection);
- mScreenshotConnection = null;
- mScreenshotService = null;
- }
+ resetConnection();
}
break;
}
@@ -348,9 +359,7 @@
public void onServiceDisconnected(ComponentName name) {
synchronized (mScreenshotLock) {
if (mScreenshotConnection != null) {
- mContext.unbindService(mScreenshotConnection);
- mScreenshotConnection = null;
- mScreenshotService = null;
+ resetConnection();
// only log an error if we're still within the timeout period
if (handler.hasCallbacks(mScreenshotTimeout)) {
handler.removeCallbacks(mScreenshotTimeout);
@@ -383,6 +392,17 @@
}
/**
+ * Unbinds the current screenshot connection (if any).
+ */
+ private void resetConnection() {
+ if (mScreenshotConnection != null) {
+ mContext.unbindService(mScreenshotConnection);
+ mScreenshotConnection = null;
+ mScreenshotService = null;
+ }
+ }
+
+ /**
* Notifies the screenshot service to show an error.
*/
private void notifyScreenshotError() {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ed84434..855448b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -50,6 +50,7 @@
#include "jni.h"
using namespace android;
+using android::base::GetBoolProperty;
using android::base::GetProperty;
extern int register_android_os_Binder(JNIEnv* env);
@@ -727,17 +728,7 @@
ALOGI("Leaving lock profiling enabled");
}
- bool checkJni = false;
- property_get("dalvik.vm.checkjni", propBuf, "");
- if (strcmp(propBuf, "true") == 0) {
- checkJni = true;
- } else if (strcmp(propBuf, "false") != 0) {
- /* property is neither true nor false; fall back on kernel parameter */
- property_get("ro.kernel.android.checkjni", propBuf, "");
- if (propBuf[0] == '1') {
- checkJni = true;
- }
- }
+ const bool checkJni = GetBoolProperty("dalvik.vm.checkjni", false);
ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
if (checkJni) {
/* extended JNI checking */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 24ade39..cc4e2bb 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -332,7 +332,7 @@
<protected-broadcast android:name="android.nfc.handover.intent.action.HANDOVER_SEND_MULTIPLE" />
<protected-broadcast android:name="com.android.nfc.handover.action.CANCEL_HANDOVER_TRANSFER" />
- <protected-broadcast android:name="android.intent.action.CLEAR_DNS_CACHE" />
+ <protected-broadcast android:name="android.net.action.CLEAR_DNS_CACHE" />
<protected-broadcast android:name="android.intent.action.PROXY_CHANGE" />
<protected-broadcast android:name="android.os.UpdateLock.UPDATE_LOCK_CHANGED" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bfe7802..58eb93f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1834,7 +1834,7 @@
<string name="config_systemGallery" translatable="false">com.android.gallery3d</string>
<!-- The name of the package that will be allowed to change its components' label/icon. -->
- <string name="config_overrideComponentUiPackage" translatable="false"></string>
+ <string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
<!-- Enable/disable default bluetooth profiles:
HSP_AG, ObexObjectPush, Audio, NAP -->
diff --git a/core/tests/coretests/src/android/app/admin/OWNERS b/core/tests/coretests/src/android/app/admin/OWNERS
new file mode 100644
index 0000000..e95633a
--- /dev/null
+++ b/core/tests/coretests/src/android/app/admin/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/app/admin/OWNERS
diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
index e41805d..21ef083 100644
--- a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
+++ b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
@@ -123,8 +123,8 @@
rangingManager.onRangingReconfigureFailed(handle, REASON, PARAMS);
verify(callback, times(1)).onReconfigureFailed(eq(REASON), eq(PARAMS));
- rangingManager.onRangingStopped(handle);
- verify(callback, times(1)).onStopped();
+ rangingManager.onRangingStopped(handle, REASON, PARAMS);
+ verify(callback, times(1)).onStopped(eq(REASON), eq(PARAMS));
rangingManager.onRangingStopFailed(handle, REASON, PARAMS);
verify(callback, times(1)).onStopFailed(eq(REASON), eq(PARAMS));
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 43fdedc..aef68d0 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -410,6 +410,7 @@
<permission name="android.permission.LOG_COMPAT_CHANGE" />
<permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
<permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG" />
+ <permission name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD" />
<!-- Permissions required to test ambient display. -->
<permission name="android.permission.READ_DREAM_STATE" />
<permission name="android.permission.WRITE_DREAM_STATE" />
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 1f9022b..a6aa4f2 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -353,7 +353,7 @@
boolean userPresenceRequired,
byte[] attestationChallenge,
boolean devicePropertiesAttestationIncluded,
- int[] attestationIds,
+ @NonNull int[] attestationIds,
boolean uniqueIdIncluded,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
@@ -779,9 +779,8 @@
* @return integer array representing the requested device IDs to attest.
*/
@SystemApi
- @Nullable
- public int[] getAttestationIds() {
- return Utils.cloneIfNotNull(mAttestationIds);
+ public @NonNull int[] getAttestationIds() {
+ return mAttestationIds.clone();
}
/**
@@ -911,7 +910,7 @@
private boolean mUserPresenceRequired = false;
private byte[] mAttestationChallenge = null;
private boolean mDevicePropertiesAttestationIncluded = false;
- private int[] mAttestationIds = null;
+ private int[] mAttestationIds = new int[0];
private boolean mUniqueIdIncluded = false;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index c26d9f583..dc7f3dd 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -655,7 +655,7 @@
}
int[] idTypes = mSpec.getAttestationIds();
- if (idTypes == null) {
+ if (idTypes.length == 0) {
return;
}
final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 5633236..54d0659 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -4607,6 +4607,25 @@
return mType;
}
+ @Override
+ public boolean equals(Object o) {
+ if (o == null) {
+ return false;
+ }
+ if (!(o instanceof ParameterDescriptor)) {
+ return false;
+ }
+ ParameterDescriptor other = (ParameterDescriptor) o;
+ return this.mName.equals(other.mName) && this.mType == other.mType;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.asList(
+ (Object) mName,
+ (Object) Integer.valueOf(mType)).hashCode();
+ }
+
private String mName;
private @MediaFormat.Type int mType;
}
@@ -4631,7 +4650,8 @@
private native ParameterDescriptor native_getParameterDescriptor(@NonNull String name);
/**
- * Subscribe to vendor parameters, so that changes to these parameters generate
+ * Subscribe to vendor parameters, so that these parameters will be present in
+ * {@link #getOutputFormat} and changes to these parameters generate
* output format change event.
* <p>
* Unrecognized parameter names or standard (non-vendor) parameter names will be ignored.
@@ -4660,8 +4680,9 @@
private native void native_subscribeToVendorParameters(@NonNull List<String> names);
/**
- * Unsubscribe from vendor parameters, so that changes to these parameters
- * no longer generate output format change event.
+ * Unsubscribe from vendor parameters, so that these parameters will not be present in
+ * {@link #getOutputFormat} and changes to these parameters no longer generate
+ * output format change event.
* <p>
* Unrecognized parameter names, standard (non-vendor) parameter names will be ignored.
* {@link #reset} also resets the list of subscribed parameters.
@@ -4669,7 +4690,8 @@
* <p>
* This method can be called in any codec state except for released state. When called in
* running state with newly unsubscribed parameters, it takes effect no later than the
- * processing of the subsequently queued buffer.
+ * processing of the subsequently queued buffer. For the removed parameters, the codec will
+ * generate output format change event.
* <p>
* Note that any vendor parameters set in a {@link #configure} or
* {@link #setParameters} call are automatically subscribed, and with this method
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 3976086e..49ef504 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -3258,7 +3258,7 @@
if (descramblerSp == NULL) {
return (jint) Result::NOT_INITIALIZED;
}
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
+ sp<IFilter> iFilterSp = (filter == NULL) ? NULL : getFilter(env, filter)->getIFilter();
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
return (jint) result;
}
@@ -3269,7 +3269,7 @@
if (descramblerSp == NULL) {
return (jint) Result::NOT_INITIALIZED;
}
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
+ sp<IFilter> iFilterSp = (filter == NULL) ? NULL : getFilter(env, filter)->getIFilter();
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
return (jint) result;
}
diff --git a/native/android/Android.bp b/native/android/Android.bp
index d1dddbd..34b9fce 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -77,6 +77,7 @@
"libgui",
"libharfbuzz_ng", // Only for including hb.h via minikin
"libsensor",
+ "libactivitymanager_aidl",
"libandroid_runtime",
"libminikin",
"libnetd_client",
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index ea9b52c..e4e5b9f 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -31,6 +31,7 @@
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.RADIO_SCAN_WITHOUT_LOCATION"/>
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+ <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
<application
android:allowClearUserData="true"
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
index e501e12..5ac059b 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceChooserActivity.java
@@ -17,6 +17,7 @@
package com.android.companiondevicemanager;
import static android.companion.BluetoothDeviceFilterUtils.getDeviceMacAddress;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static java.util.Objects.requireNonNull;
@@ -58,6 +59,8 @@
Log.e(LOG_TAG, "About to show UI, but no devices to show");
}
+ getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+
if (getService().mRequest.isSingleDevice()) {
setContentView(R.layout.device_confirmation);
final DeviceFilterPair selectedDevice = getService().mDevicesFound.get(0);
diff --git a/packages/Connectivity/framework/api/current.txt b/packages/Connectivity/framework/api/current.txt
index ab290f9..7692e30 100644
--- a/packages/Connectivity/framework/api/current.txt
+++ b/packages/Connectivity/framework/api/current.txt
@@ -410,6 +410,8 @@
}
public class ParseException extends java.lang.RuntimeException {
+ ctor public ParseException(@NonNull String);
+ ctor public ParseException(@NonNull String, @NonNull Throwable);
field public String response;
}
diff --git a/packages/Connectivity/framework/api/module-lib-current.txt b/packages/Connectivity/framework/api/module-lib-current.txt
index 513b630..4719772 100644
--- a/packages/Connectivity/framework/api/module-lib-current.txt
+++ b/packages/Connectivity/framework/api/module-lib-current.txt
@@ -26,6 +26,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
method public void systemReady();
+ field public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE";
field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION";
field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
@@ -132,21 +133,6 @@
method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
}
- public class ParseException extends java.lang.RuntimeException {
- ctor public ParseException(@NonNull String);
- ctor public ParseException(@NonNull String, @NonNull Throwable);
- }
-
- public final class TcpRepairWindow {
- ctor public TcpRepairWindow(int, int, int, int, int, int);
- field public final int maxWindow;
- field public final int rcvWnd;
- field public final int rcvWndScale;
- field public final int rcvWup;
- field public final int sndWl1;
- field public final int sndWnd;
- }
-
public final class TestNetworkInterface implements android.os.Parcelable {
ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String);
method public int describeContents();
@@ -157,10 +143,10 @@
}
public class TestNetworkManager {
- method @NonNull public android.net.TestNetworkInterface createTapInterface();
- method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
- method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
- method public void teardownTestNetwork(@NonNull android.net.Network);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTapInterface();
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void teardownTestNetwork(@NonNull android.net.Network);
field public static final String TEST_TAP_PREFIX = "testtap";
}
diff --git a/packages/Connectivity/framework/api/system-current.txt b/packages/Connectivity/framework/api/system-current.txt
index 0a82cb7..de673ee 100644
--- a/packages/Connectivity/framework/api/system-current.txt
+++ b/packages/Connectivity/framework/api/system-current.txt
@@ -259,15 +259,15 @@
public static final class NetworkAgentConfig.Builder {
ctor public NetworkAgentConfig.Builder();
method @NonNull public android.net.NetworkAgentConfig build();
- method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection();
- method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification();
method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyExtraInfo(@NonNull String);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubType(int);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubTypeName(@NonNull String);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setNat64DetectionEnabled(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setProvisioningNotificationEnabled(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean);
}
@@ -455,14 +455,14 @@
public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
method public int describeContents();
+ method public int getIpTos();
+ method public int getIpTtl();
+ method public int getTcpAck();
+ method public int getTcpSeq();
+ method public int getTcpWindow();
+ method public int getTcpWindowScale();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
- field public final int ipTos;
- field public final int ipTtl;
- field public final int tcpAck;
- field public final int tcpSeq;
- field public final int tcpWindow;
- field public final int tcpWindowScale;
}
}
diff --git a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
index 82dbd0f..53aa1b9 100644
--- a/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
+++ b/packages/Connectivity/framework/src/android/net/CaptivePortalData.java
@@ -42,7 +42,7 @@
private final long mByteLimit;
private final long mExpiryTimeMillis;
private final boolean mCaptive;
- private final CharSequence mVenueFriendlyName;
+ private final String mVenueFriendlyName;
private final int mVenueInfoUrlSource;
private final int mUserPortalUrlSource;
@@ -73,14 +73,14 @@
mByteLimit = byteLimit;
mExpiryTimeMillis = expiryTimeMillis;
mCaptive = captive;
- mVenueFriendlyName = venueFriendlyName;
+ mVenueFriendlyName = venueFriendlyName == null ? null : venueFriendlyName.toString();
mVenueInfoUrlSource = venueInfoUrlSource;
mUserPortalUrlSource = userPortalUrlSource;
}
private CaptivePortalData(Parcel p) {
this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(),
- p.readLong(), p.readLong(), p.readBoolean(), p.readCharSequence(), p.readInt(),
+ p.readLong(), p.readLong(), p.readBoolean(), p.readString(), p.readInt(),
p.readInt());
}
@@ -98,7 +98,7 @@
dest.writeLong(mByteLimit);
dest.writeLong(mExpiryTimeMillis);
dest.writeBoolean(mCaptive);
- dest.writeCharSequence(mVenueFriendlyName);
+ dest.writeString(mVenueFriendlyName);
dest.writeInt(mVenueInfoUrlSource);
dest.writeInt(mUserPortalUrlSource);
}
diff --git a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
index 84914a1..0418450 100644
--- a/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
+++ b/packages/Connectivity/framework/src/android/net/ConnectivityManager.java
@@ -44,6 +44,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.SocketKeepalive.Callback;
import android.net.TetheringManager.StartTetheringCallback;
@@ -450,6 +451,15 @@
"android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
/**
+ * Clear DNS Cache Action: This is broadcast when networks have changed and old
+ * DNS entries should be cleared.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE";
+
+ /**
* Invalid tethering type.
* @see #startTethering(int, boolean, OnStartTetheringCallback)
* @hide
@@ -5095,10 +5105,13 @@
*
* <p>This method should only be used for tests.
*
- * <p>The caller must be the owner of the specified Network.
+ * <p>The caller must be the owner of the specified Network. This simulates a data stall to
+ * have the system behave as if it had happened, but does not actually stall connectivity.
*
* @param detectionMethod The detection method used to identify the Data Stall.
- * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds.
+ * See ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_*.
+ * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds, as per
+ * SystemClock.elapsedRealtime.
* @param network The Network for which a Data Stall is being simluated.
* @param extras The PersistableBundle of extras included in the Data Stall notification.
* @throws SecurityException if the caller is not the owner of the given network.
@@ -5107,7 +5120,7 @@
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS,
android.Manifest.permission.NETWORK_STACK})
- public void simulateDataStall(int detectionMethod, long timestampMillis,
+ public void simulateDataStall(@DetectionMethod int detectionMethod, long timestampMillis,
@NonNull Network network, @NonNull PersistableBundle extras) {
try {
mService.simulateDataStall(detectionMethod, timestampMillis, network, extras);
diff --git a/packages/Connectivity/framework/src/android/net/Network.java b/packages/Connectivity/framework/src/android/net/Network.java
index 0741414..41fad63 100644
--- a/packages/Connectivity/framework/src/android/net/Network.java
+++ b/packages/Connectivity/framework/src/android/net/Network.java
@@ -27,7 +27,6 @@
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
@@ -526,11 +525,4 @@
public String toString() {
return Integer.toString(netId);
}
-
- /** @hide */
- public void dumpDebug(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
- proto.write(NetworkProto.NET_ID, netId);
- proto.end(token);
- }
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
index 3f058d8..ad8396b 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkAgentConfig.java
@@ -311,26 +311,28 @@
}
/**
- * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power
- * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64.
+ * Enables or disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to
+ * save power and reduce idle traffic on networks that are known to be IPv6-only without a
+ * NAT64. By default, NAT64 detection is enabled.
*
* @return this builder, to facilitate chaining.
*/
@NonNull
- public Builder disableNat64Detection() {
- mConfig.skip464xlat = true;
+ public Builder setNat64DetectionEnabled(boolean enabled) {
+ mConfig.skip464xlat = !enabled;
return this;
}
/**
- * Disables the "Sign in to network" notification. Used if the network transport will
- * perform its own carrier-specific provisioning procedure.
+ * Enables or disables the "Sign in to network" notification. Used if the network transport
+ * will perform its own carrier-specific provisioning procedure. By default, the
+ * notification is enabled.
*
* @return this builder, to facilitate chaining.
*/
@NonNull
- public Builder disableProvisioningNotification() {
- mConfig.provisioningNotificationDisabled = true;
+ public Builder setProvisioningNotificationEnabled(boolean enabled) {
+ mConfig.provisioningNotificationDisabled = !enabled;
return this;
}
diff --git a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
index 9a75f0b..a43dd15 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkCapabilities.java
@@ -35,7 +35,6 @@
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Range;
-import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.CollectionUtils;
@@ -2060,34 +2059,6 @@
}
}
- /** @hide */
- public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
-
- for (int transport : getTransportTypes()) {
- proto.write(NetworkCapabilitiesProto.TRANSPORTS, transport);
- }
-
- for (int capability : getCapabilities()) {
- proto.write(NetworkCapabilitiesProto.CAPABILITIES, capability);
- }
-
- proto.write(NetworkCapabilitiesProto.LINK_UP_BANDWIDTH_KBPS, mLinkUpBandwidthKbps);
- proto.write(NetworkCapabilitiesProto.LINK_DOWN_BANDWIDTH_KBPS, mLinkDownBandwidthKbps);
-
- if (mNetworkSpecifier != null) {
- proto.write(NetworkCapabilitiesProto.NETWORK_SPECIFIER, mNetworkSpecifier.toString());
- }
- if (mTransportInfo != null) {
- // TODO b/120653863: write transport-specific info to proto?
- }
-
- proto.write(NetworkCapabilitiesProto.CAN_REPORT_SIGNAL_STRENGTH, hasSignalStrength());
- proto.write(NetworkCapabilitiesProto.SIGNAL_STRENGTH, mSignalStrength);
-
- proto.end(token);
- }
-
/**
* @hide
*/
diff --git a/packages/Connectivity/framework/src/android/net/NetworkRequest.java b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
index 5d40417..3a8a07a 100644
--- a/packages/Connectivity/framework/src/android/net/NetworkRequest.java
+++ b/packages/Connectivity/framework/src/android/net/NetworkRequest.java
@@ -47,7 +47,6 @@
import android.os.Process;
import android.text.TextUtils;
import android.util.Range;
-import android.util.proto.ProtoOutputStream;
import java.util.Arrays;
import java.util.List;
@@ -680,18 +679,6 @@
}
}
- /** @hide */
- public void dumpDebug(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
-
- proto.write(NetworkRequestProto.TYPE, typeToProtoEnum(type));
- proto.write(NetworkRequestProto.REQUEST_ID, requestId);
- proto.write(NetworkRequestProto.LEGACY_TYPE, legacyType);
- networkCapabilities.dumpDebug(proto, NetworkRequestProto.NETWORK_CAPABILITIES);
-
- proto.end(token);
- }
-
public boolean equals(@Nullable Object obj) {
if (obj instanceof NetworkRequest == false) return false;
NetworkRequest that = (NetworkRequest)obj;
diff --git a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java
index 5a76cd6..2bb006d 100644
--- a/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java
+++ b/packages/Connectivity/framework/src/android/net/OemNetworkPreferences.java
@@ -40,6 +40,23 @@
*/
@SystemApi
public final class OemNetworkPreferences implements Parcelable {
+ // Valid production preferences must be > 0, negative values reserved for testing
+ /**
+ * This preference is only to be used for testing and nothing else.
+ * Use only TRANSPORT_TEST transport networks.
+ * @hide
+ */
+ public static final int OEM_NETWORK_PREFERENCE_TEST_ONLY = -2;
+
+ /**
+ * This preference is only to be used for testing and nothing else.
+ * If an unmetered network is available, use it.
+ * Otherwise, if a network with the TRANSPORT_TEST transport is available, use it.
+ * Otherwise, use the general default network.
+ * @hide
+ */
+ public static final int OEM_NETWORK_PREFERENCE_TEST = -1;
+
/**
* Default in case this value is not set. Using it will result in an error.
*/
@@ -69,6 +86,12 @@
*/
public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4;
+ /**
+ * The max allowed value for an OEM network preference.
+ * @hide
+ */
+ public static final int OEM_NETWORK_PREFERENCE_MAX = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+
@NonNull
private final Bundle mNetworkMappings;
@@ -96,7 +119,7 @@
@Override
public String toString() {
- return "OemNetworkPreferences{" + "mNetworkMappings=" + mNetworkMappings + '}';
+ return "OemNetworkPreferences{" + "mNetworkMappings=" + getNetworkPreferences() + '}';
}
@Override
@@ -185,6 +208,8 @@
/** @hide */
@IntDef(prefix = "OEM_NETWORK_PREFERENCE_", value = {
+ OEM_NETWORK_PREFERENCE_TEST_ONLY,
+ OEM_NETWORK_PREFERENCE_TEST,
OEM_NETWORK_PREFERENCE_UNINITIALIZED,
OEM_NETWORK_PREFERENCE_OEM_PAID,
OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK,
@@ -205,6 +230,10 @@
@NonNull
public static String oemNetworkPreferenceToString(@OemNetworkPreference int value) {
switch (value) {
+ case OEM_NETWORK_PREFERENCE_TEST_ONLY:
+ return "OEM_NETWORK_PREFERENCE_TEST_ONLY";
+ case OEM_NETWORK_PREFERENCE_TEST:
+ return "OEM_NETWORK_PREFERENCE_TEST";
case OEM_NETWORK_PREFERENCE_UNINITIALIZED:
return "OEM_NETWORK_PREFERENCE_UNINITIALIZED";
case OEM_NETWORK_PREFERENCE_OEM_PAID:
diff --git a/packages/Connectivity/framework/src/android/net/ParseException.java b/packages/Connectivity/framework/src/android/net/ParseException.java
index ca6d012..9d4727a 100644
--- a/packages/Connectivity/framework/src/android/net/ParseException.java
+++ b/packages/Connectivity/framework/src/android/net/ParseException.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
/**
* Thrown when parsing failed.
@@ -26,15 +25,11 @@
public class ParseException extends RuntimeException {
public String response;
- /** @hide */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public ParseException(@NonNull String response) {
super(response);
this.response = response;
}
- /** @hide */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public ParseException(@NonNull String response, @NonNull Throwable cause) {
super(response, cause);
this.response = response;
diff --git a/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java b/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java
index ddb3a6a7..c2c4f32 100644
--- a/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java
+++ b/packages/Connectivity/framework/src/android/net/TcpKeepalivePacketData.java
@@ -32,22 +32,39 @@
public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
private static final String TAG = "TcpKeepalivePacketData";
- /** TCP sequence number. */
+ /**
+ * TCP sequence number.
+ * @hide
+ */
public final int tcpSeq;
- /** TCP ACK number. */
+ /**
+ * TCP ACK number.
+ * @hide
+ */
public final int tcpAck;
- /** TCP RCV window. */
+ /**
+ * TCP RCV window.
+ * @hide
+ */
public final int tcpWindow;
- /** TCP RCV window scale. */
+ /** TCP RCV window scale.
+ * @hide
+ */
public final int tcpWindowScale;
- /** IP TOS. */
+ /**
+ * IP TOS.
+ * @hide
+ */
public final int ipTos;
- /** IP TTL. */
+ /**
+ * IP TTL.
+ * @hide
+ */
public final int ipTtl;
public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort,
@@ -63,6 +80,56 @@
this.ipTtl = ipTtl;
}
+ /**
+ * Get the TCP sequence number.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpSeq() {
+ return tcpSeq;
+ }
+
+ /**
+ * Get the TCP ACK number.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpAck() {
+ return tcpAck;
+ }
+
+ /**
+ * Get the TCP RCV window.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpWindow() {
+ return tcpWindow;
+ }
+
+ /**
+ * Get the TCP RCV window scale.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpWindowScale() {
+ return tcpWindowScale;
+ }
+
+ /**
+ * Get the IP type of service.
+ */
+ public int getIpTos() {
+ return ipTos;
+ }
+
+ /**
+ * Get the IP TTL.
+ */
+ public int getIpTtl() {
+ return ipTtl;
+ }
+
@Override
public boolean equals(@Nullable final Object o) {
if (!(o instanceof TcpKeepalivePacketData)) return false;
diff --git a/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java
index f062fa9..86034f0 100644
--- a/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java
+++ b/packages/Connectivity/framework/src/android/net/TcpRepairWindow.java
@@ -16,15 +16,12 @@
package android.net;
-import android.annotation.SystemApi;
-
/**
* Corresponds to C's {@code struct tcp_repair_window} from
* include/uapi/linux/tcp.h
*
* @hide
*/
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TcpRepairWindow {
public final int sndWl1;
public final int sndWnd;
diff --git a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java
index a7a6235..9ddd2f5 100644
--- a/packages/Connectivity/framework/src/android/net/TestNetworkManager.java
+++ b/packages/Connectivity/framework/src/android/net/TestNetworkManager.java
@@ -15,8 +15,10 @@
*/
package android.net;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.os.IBinder;
import android.os.RemoteException;
@@ -58,6 +60,7 @@
* @param network The test network that should be torn down
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void teardownTestNetwork(@NonNull Network network) {
try {
@@ -103,6 +106,7 @@
* @param binder A binder object guarding the lifecycle of this test network.
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
setupTestNetwork(iface, null, true, new int[0], binder);
@@ -145,6 +149,7 @@
* TUN interface.
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) {
@@ -163,6 +168,7 @@
* TAP interface.
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public TestNetworkInterface createTapInterface() {
diff --git a/packages/Connectivity/framework/src/android/net/UidRange.java b/packages/Connectivity/framework/src/android/net/UidRange.java
index bc67c74..bd33292 100644
--- a/packages/Connectivity/framework/src/android/net/UidRange.java
+++ b/packages/Connectivity/framework/src/android/net/UidRange.java
@@ -46,8 +46,8 @@
/** Creates a UidRange for the specified user. */
public static UidRange createForUser(UserHandle user) {
final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1);
- final int start = UserHandle.getUid(user, 0 /* appId */);
- final int end = UserHandle.getUid(nextUser, 0) - 1;
+ final int start = user.getUid(0 /* appId */);
+ final int end = nextUser.getUid(0 /* appId */) - 1;
return new UidRange(start, end);
}
diff --git a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
index ba83a44..efd3363 100644
--- a/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
+++ b/packages/Connectivity/framework/src/android/net/VpnTransportInfo.java
@@ -22,6 +22,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.net.NetworkCapabilities.RedactionType;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -45,7 +46,7 @@
public final String sessionId;
@Override
- public long getApplicableRedactions() {
+ public @RedactionType long getApplicableRedactions() {
return REDACT_FOR_NETWORK_SETTINGS;
}
@@ -53,7 +54,7 @@
* Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary.
*/
@NonNull
- public VpnTransportInfo makeCopy(long redactions) {
+ public VpnTransportInfo makeCopy(@RedactionType long redactions) {
return new VpnTransportInfo(type,
((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : sessionId);
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index cb610fc..bcde584 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -89,7 +89,7 @@
return value == null || value.length() < MAX_LENGTH;
}
});
- VALIDATORS.put(System.FONT_SCALE, new InclusiveFloatRangeValidator(0.85f, 1.3f));
+ VALIDATORS.put(System.FONT_SCALE, new InclusiveFloatRangeValidator(0.25f, 5.0f));
VALIDATORS.put(System.DIM_SCREEN, BOOLEAN_VALIDATOR);
VALIDATORS.put(
System.DISPLAY_COLOR_MODE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d0dc987..bd5f8ab 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -251,10 +251,11 @@
<!-- permissions required for CTS test - PhoneStateListenerTest -->
<uses-permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH" />
- <!-- Permissions required for ganting and logging -->
+ <!-- Permissions required for granting and logging -->
<uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
<uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
<uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"/>
+ <uses-permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
<!-- Permission required for CTS test - BatterySaverTest -->
<uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
diff --git a/services/backup/OWNERS b/services/backup/OWNERS
index cc36b47..852c689 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,6 +1,5 @@
# Bug component: 656484
-aabhinav@google.com
bryanmawhinney@google.com
jstemmer@google.com
millmore@google.com
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5aa3e5b..efb3768 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2260,7 +2260,9 @@
netId = nai.network.getNetId();
}
boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
- if (DBG) log("requestRouteToHostAddress ok=" + ok);
+ if (DBG) {
+ log("requestRouteToHostAddress " + addr + nai.toShortString() + " ok=" + ok);
+ }
return ok;
} finally {
Binder.restoreCallingIdentity(token);
@@ -2884,13 +2886,13 @@
pw.println();
pw.println("mNetworkRequestInfoLogs (most recent first):");
pw.increaseIndent();
- mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
+ mNetworkRequestInfoLogs.reverseDump(pw);
pw.decreaseIndent();
pw.println();
pw.println("mNetworkInfoBlockingLogs (most recent first):");
pw.increaseIndent();
- mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
+ mNetworkInfoBlockingLogs.reverseDump(pw);
pw.decreaseIndent();
pw.println();
@@ -2904,7 +2906,7 @@
long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
}
- mWakelockLogs.reverseDump(fd, pw, args);
+ mWakelockLogs.reverseDump(pw);
pw.println();
pw.println("bandwidth update requests (by uid):");
@@ -2916,7 +2918,12 @@
}
}
pw.decreaseIndent();
+ pw.decreaseIndent();
+ pw.println();
+ pw.println("mOemNetworkPreferencesLogs (most recent first):");
+ pw.increaseIndent();
+ mOemNetworkPreferencesLogs.reverseDump(pw);
pw.decreaseIndent();
}
@@ -6205,6 +6212,12 @@
@NonNull
private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences();
+ // OemNetworkPreferences activity String log entries.
+ private static final int MAX_OEM_NETWORK_PREFERENCE_LOGS = 20;
+ @NonNull
+ private final LocalLog mOemNetworkPreferencesLogs =
+ new LocalLog(MAX_OEM_NETWORK_PREFERENCE_LOGS);
+
/**
* Determine whether a given package has a mapping in the current OemNetworkPreferences.
* @param packageName the package name to check existence of a mapping for.
@@ -7677,7 +7690,7 @@
}
void addRequestReassignment(@NonNull final RequestReassignment reassignment) {
- if (Build.IS_DEBUGGABLE) {
+ if (Build.isDebuggable()) {
// The code is never supposed to add two reassignments of the same request. Make
// sure this stays true, but without imposing this expensive check on all
// reassignments on all user devices.
@@ -9637,6 +9650,7 @@
return;
}
+ mOemNetworkPreferencesLogs.log("UPDATE INITIATED: " + preference);
final ArraySet<NetworkRequestInfo> nris =
new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference);
replaceDefaultNetworkRequestsForPreference(nris);
@@ -9790,7 +9804,7 @@
}
for (final UserHandle ui : users) {
// Add the rules for all users as this policy is device wide.
- uids.get(pref).add(UserHandle.getUid(ui, uid));
+ uids.get(pref).add(ui.getUid(uid));
}
} catch (PackageManager.NameNotFoundException e) {
// Although this may seem like an error scenario, it is ok that uninstalled
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 6560824..5f6d9bd 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -82,7 +82,7 @@
private static final int DEFAULT_AGE_SECONDS = 3 * 86400;
private static final int DEFAULT_MAX_FILES = 1000;
private static final int DEFAULT_MAX_FILES_LOWRAM = 300;
- private static final int DEFAULT_QUOTA_KB = 5 * 1024;
+ private static final int DEFAULT_QUOTA_KB = 10 * 1024;
private static final int DEFAULT_QUOTA_PERCENT = 10;
private static final int DEFAULT_RESERVE_PERCENT = 10;
private static final int QUOTA_RESCAN_MILLIS = 5000;
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index f7ae58c..9c10658 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.DUMP;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.vcn.VcnManager.VCN_STATUS_CODE_ACTIVE;
@@ -69,6 +70,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.net.module.util.LocationPermissionChecker;
import com.android.server.vcn.TelephonySubscriptionTracker;
import com.android.server.vcn.Vcn;
@@ -76,7 +78,9 @@
import com.android.server.vcn.VcnNetworkProvider;
import com.android.server.vcn.util.PersistableBundleUtils;
+import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -168,9 +172,6 @@
@NonNull
private final TrackingNetworkCallback mTrackingNetworkCallback = new TrackingNetworkCallback();
- /** Can only be assigned when {@link #systemReady()} is called, since it uses AppOpsManager. */
- @Nullable private LocationPermissionChecker mLocationPermissionChecker;
-
@GuardedBy("mLock")
@NonNull
private final Map<ParcelUuid, VcnConfig> mConfigs = new ArrayMap<>();
@@ -369,7 +370,6 @@
new NetworkRequest.Builder().clearCapabilities().build(),
mTrackingNetworkCallback);
mTelephonySubscriptionTracker.register();
- mLocationPermissionChecker = mDeps.newLocationPermissionChecker(mVcnContext.getContext());
}
private void enforcePrimaryUser() {
@@ -836,13 +836,6 @@
return false;
}
- if (!mLocationPermissionChecker.checkLocationPermission(
- cbInfo.mPkgName,
- "VcnStatusCallback" /* featureId */,
- cbInfo.mUid,
- null /* message */)) {
- return false;
- }
return true;
}
@@ -929,6 +922,33 @@
}
}
+ /**
+ * Dumps the state of the VcnManagementService for logging and debugging purposes.
+ *
+ * <p>PII and credentials MUST NEVER be dumped here.
+ */
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ mContext.enforceCallingOrSelfPermission(DUMP, TAG);
+
+ final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
+
+ pw.println("VcnManagementService dump:");
+ pw.increaseIndent();
+
+ mNetworkProvider.dump(pw);
+
+ synchronized (mLock) {
+ pw.println("mVcns:");
+ for (Vcn vcn : mVcns.values()) {
+ vcn.dump(pw);
+ }
+ pw.println();
+ }
+
+ pw.decreaseIndent();
+ }
+
// TODO(b/180452282): Make name more generic and implement directly with VcnManagementService
/** Callback for Vcn signals sent up to VcnManagementService. */
public interface VcnCallback {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index cc5a25a..2744f11 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -236,6 +236,7 @@
import android.hardware.display.DisplayManagerInternal;
import android.location.LocationManager;
import android.media.audiofx.AudioEffect;
+import android.net.ConnectivityManager;
import android.net.Proxy;
import android.net.Uri;
import android.os.AppZygote;
@@ -16458,7 +16459,7 @@
stats.noteCurrentTimeChangedLocked();
}
break;
- case Intent.ACTION_CLEAR_DNS_CACHE:
+ case ConnectivityManager.ACTION_CLEAR_DNS_CACHE:
mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
break;
case Proxy.PROXY_CHANGE_ACTION:
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index f2236d7..db8dc71 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3003,8 +3003,8 @@
// This is a workaround for R QPR, new API change is not allowed. We only allow the current
// voice recognizer is also the voice interactor to noteproxy op.
- final boolean isTrustVoiceServiceProxy =
- AppOpsManager.isTrustedVoiceServiceProxy(mContext, proxyPackageName, code);
+ final boolean isTrustVoiceServiceProxy = AppOpsManager.isTrustedVoiceServiceProxy(mContext,
+ proxyPackageName, code, UserHandle.getUserId(proxyUid));
final boolean isSelfBlame = Binder.getCallingUid() == proxiedUid;
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 72160c2..f4e06d3 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -52,10 +52,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.system.ErrnoException;
-import android.system.Os;
-import android.system.OsConstants;
-import android.system.VmSocketAddress;
import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
@@ -67,128 +63,9 @@
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.wm.WindowManagerInternal;
-import java.io.FileDescriptor;
-import java.io.InterruptedIOException;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
-
-// The following class is Android Emulator specific. It is used to read and
-// write contents of the host system's clipboard.
-class HostClipboardMonitor implements Runnable {
- public interface HostClipboardCallback {
- void onHostClipboardUpdated(String contents);
- }
-
- private FileDescriptor mPipe = null;
- private HostClipboardCallback mHostClipboardCallback;
- private static final String PIPE_NAME = "pipe:clipboard";
- private static final int HOST_PORT = 5000;
-
- private static byte[] createOpenHandshake() {
- // String.getBytes doesn't include the null terminator,
- // but the QEMU pipe device requires the pipe service name
- // to be null-terminated.
-
- final byte[] bits = Arrays.copyOf(PIPE_NAME.getBytes(), PIPE_NAME.length() + 1);
- bits[PIPE_NAME.length()] = 0;
- return bits;
- }
-
- private boolean openPipe() {
- try {
- final FileDescriptor fd = Os.socket(OsConstants.AF_VSOCK, OsConstants.SOCK_STREAM, 0);
-
- try {
- Os.connect(fd, new VmSocketAddress(HOST_PORT, OsConstants.VMADDR_CID_HOST));
-
- final byte[] handshake = createOpenHandshake();
- Os.write(fd, handshake, 0, handshake.length);
- mPipe = fd;
- return true;
- } catch (ErrnoException | SocketException | InterruptedIOException e) {
- Os.close(fd);
- }
- } catch (ErrnoException e) {
- }
-
- return false;
- }
-
- private void closePipe() {
- try {
- final FileDescriptor fd = mPipe;
- mPipe = null;
- if (fd != null) {
- Os.close(fd);
- }
- } catch (ErrnoException ignore) {
- }
- }
-
- private byte[] receiveMessage() throws ErrnoException, InterruptedIOException {
- final byte[] lengthBits = new byte[4];
- Os.read(mPipe, lengthBits, 0, lengthBits.length);
-
- final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
- bb.order(ByteOrder.LITTLE_ENDIAN);
- final int msgLen = bb.getInt();
-
- final byte[] msg = new byte[msgLen];
- Os.read(mPipe, msg, 0, msg.length);
-
- return msg;
- }
-
- private void sendMessage(byte[] msg) throws ErrnoException, InterruptedIOException {
- final byte[] lengthBits = new byte[4];
- final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
- bb.order(ByteOrder.LITTLE_ENDIAN);
- bb.putInt(msg.length);
-
- Os.write(mPipe, lengthBits, 0, lengthBits.length);
- Os.write(mPipe, msg, 0, msg.length);
- }
-
- public HostClipboardMonitor(HostClipboardCallback cb) {
- mHostClipboardCallback = cb;
- }
-
- @Override
- public void run() {
- while (!Thread.interrupted()) {
- try {
- // There's no guarantee that QEMU pipes will be ready at the moment
- // this method is invoked. We simply try to get the pipe open and
- // retry on failure indefinitely.
- while ((mPipe == null) && !openPipe()) {
- Thread.sleep(100);
- }
-
- final byte[] receivedData = receiveMessage();
- mHostClipboardCallback.onHostClipboardUpdated(
- new String(receivedData));
- } catch (ErrnoException | InterruptedIOException e) {
- closePipe();
- } catch (InterruptedException e) {
- }
- }
- }
-
- public void setHostClipboard(String content) {
- try {
- if (mPipe != null) {
- sendMessage(content.getBytes());
- }
- } catch (ErrnoException | InterruptedIOException e) {
- Slog.e("HostClipboardMonitor",
- "Failed to set host clipboard " + e.getMessage());
- }
- }
-}
+import java.util.function.Consumer;
/**
* Implementation of the clipboard for copy and paste.
@@ -214,8 +91,7 @@
private final ContentCaptureManagerInternal mContentCaptureInternal;
private final AutofillManagerInternal mAutofillInternal;
private final IBinder mPermissionOwner;
- private HostClipboardMonitor mHostClipboardMonitor = null;
- private Thread mHostMonitorThread = null;
+ private final Consumer<ClipData> mEmulatorClipboardMonitor;
private final SparseArray<PerUserClipboard> mClipboards = new SparseArray<>();
@@ -237,22 +113,13 @@
final IBinder permOwner = mUgmInternal.newUriPermissionOwner("clipboard");
mPermissionOwner = permOwner;
if (IS_EMULATOR) {
- mHostClipboardMonitor = new HostClipboardMonitor(
- new HostClipboardMonitor.HostClipboardCallback() {
- @Override
- public void onHostClipboardUpdated(String contents){
- ClipData clip =
- new ClipData("host clipboard",
- new String[]{"text/plain"},
- new ClipData.Item(contents));
- synchronized(mClipboards) {
- setPrimaryClipInternal(getClipboard(0), clip,
- android.os.Process.SYSTEM_UID);
- }
- }
- });
- mHostMonitorThread = new Thread(mHostClipboardMonitor);
- mHostMonitorThread.start();
+ mEmulatorClipboardMonitor = new EmulatorClipboardMonitor((clip) -> {
+ synchronized (this) {
+ setPrimaryClipInternal(getClipboard(0), clip, android.os.Process.SYSTEM_UID);
+ }
+ });
+ } else {
+ mEmulatorClipboardMonitor = (clip) -> {};
}
}
@@ -547,18 +414,7 @@
}
void setPrimaryClipInternal(@Nullable ClipData clip, int uid) {
- // Push clipboard to host, if any
- if (mHostClipboardMonitor != null) {
- if (clip == null) {
- // Someone really wants the clipboard cleared, so push empty
- mHostClipboardMonitor.setHostClipboard("");
- } else if (clip.getItemCount() > 0) {
- final CharSequence text = clip.getItemAt(0).getText();
- if (text != null) {
- mHostClipboardMonitor.setHostClipboard(text.toString());
- }
- }
- }
+ mEmulatorClipboardMonitor.accept(clip);
// Update this user
final int userId = UserHandle.getUserId(uid);
diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
new file mode 100644
index 0000000..62b701a
--- /dev/null
+++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.clipboard;
+
+import android.annotation.Nullable;
+import android.content.ClipData;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.VmSocketAddress;
+import android.util.Slog;
+
+import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+import java.util.function.Consumer;
+
+// The following class is Android Emulator specific. It is used to read and
+// write contents of the host system's clipboard.
+class EmulatorClipboardMonitor implements Consumer<ClipData> {
+ private static final String TAG = "EmulatorClipboardMonitor";
+ private static final String PIPE_NAME = "pipe:clipboard";
+ private static final int HOST_PORT = 5000;
+ private final Thread mHostMonitorThread;
+ private FileDescriptor mPipe = null;
+
+ private static byte[] createOpenHandshake() {
+ // String.getBytes doesn't include the null terminator,
+ // but the QEMU pipe device requires the pipe service name
+ // to be null-terminated.
+
+ final byte[] bits = Arrays.copyOf(PIPE_NAME.getBytes(), PIPE_NAME.length() + 1);
+ bits[PIPE_NAME.length()] = 0;
+ return bits;
+ }
+
+ private boolean isPipeOpened() {
+ return mPipe != null;
+ }
+
+ private synchronized boolean openPipe() {
+ if (mPipe != null) {
+ return true;
+ }
+
+ try {
+ final FileDescriptor fd = Os.socket(OsConstants.AF_VSOCK, OsConstants.SOCK_STREAM, 0);
+
+ try {
+ Os.connect(fd, new VmSocketAddress(HOST_PORT, OsConstants.VMADDR_CID_HOST));
+
+ final byte[] handshake = createOpenHandshake();
+ Os.write(fd, handshake, 0, handshake.length);
+ mPipe = fd;
+ return true;
+ } catch (ErrnoException | SocketException | InterruptedIOException e) {
+ Os.close(fd);
+ }
+ } catch (ErrnoException e) {
+ }
+
+ return false;
+ }
+
+ private synchronized void closePipe() {
+ try {
+ final FileDescriptor fd = mPipe;
+ mPipe = null;
+ if (fd != null) {
+ Os.close(fd);
+ }
+ } catch (ErrnoException ignore) {
+ }
+ }
+
+ private byte[] receiveMessage() throws ErrnoException, InterruptedIOException {
+ final byte[] lengthBits = new byte[4];
+ Os.read(mPipe, lengthBits, 0, lengthBits.length);
+
+ final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ final int msgLen = bb.getInt();
+
+ final byte[] msg = new byte[msgLen];
+ Os.read(mPipe, msg, 0, msg.length);
+
+ return msg;
+ }
+
+ private void sendMessage(final byte[] msg) throws ErrnoException, InterruptedIOException {
+ final byte[] lengthBits = new byte[4];
+ final ByteBuffer bb = ByteBuffer.wrap(lengthBits);
+ bb.order(ByteOrder.LITTLE_ENDIAN);
+ bb.putInt(msg.length);
+
+ Os.write(mPipe, lengthBits, 0, lengthBits.length);
+ Os.write(mPipe, msg, 0, msg.length);
+ }
+
+ EmulatorClipboardMonitor(final Consumer<ClipData> setAndroidClipboard) {
+ this.mHostMonitorThread = new Thread(() -> {
+ while (!Thread.interrupted()) {
+ try {
+ // There's no guarantee that QEMU pipes will be ready at the moment
+ // this method is invoked. We simply try to get the pipe open and
+ // retry on failure indefinitely.
+ while (!openPipe()) {
+ Thread.sleep(100);
+ }
+
+ final byte[] receivedData = receiveMessage();
+
+ final String str = new String(receivedData);
+ final ClipData clip = new ClipData("host clipboard",
+ new String[]{"text/plain"},
+ new ClipData.Item(str));
+
+ setAndroidClipboard.accept(clip);
+ } catch (ErrnoException | InterruptedIOException e) {
+ closePipe();
+ } catch (InterruptedException | IllegalArgumentException e) {
+ }
+ }
+ });
+
+ this.mHostMonitorThread.start();
+ }
+
+ @Override
+ public void accept(final @Nullable ClipData clip) {
+ if (clip == null) {
+ setHostClipboardImpl("");
+ } else if (clip.getItemCount() > 0) {
+ final CharSequence text = clip.getItemAt(0).getText();
+ if (text != null) {
+ setHostClipboardImpl(text.toString());
+ }
+ }
+ }
+
+ private void setHostClipboardImpl(final String value) {
+ try {
+ if (isPipeOpened()) {
+ sendMessage(value.getBytes());
+ }
+ } catch (ErrnoException | InterruptedIOException e) {
+ Slog.e(TAG, "Failed to set host clipboard " + e.getMessage());
+ } catch (IllegalArgumentException e) {
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/clipboard/OWNERS b/services/core/java/com/android/server/clipboard/OWNERS
new file mode 100644
index 0000000..5449df9
--- /dev/null
+++ b/services/core/java/com/android/server/clipboard/OWNERS
@@ -0,0 +1 @@
+per-file EmulatorClipboardMonitor.java = bohu@google.com,lfy@google.com,rkir@google.com
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index ffeb77d..cf4fe1e 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -420,7 +420,7 @@
/*
* Tell the VMs to toss their DNS caches
*/
- final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
+ final Intent intent = new Intent(ConnectivityManager.ACTION_CLEAR_DNS_CACHE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
/*
* Connectivity events can happen before boot has completed ...
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 3711679..7837e6e 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -286,7 +286,7 @@
for (UserHandle user : users) {
if (user == null) continue;
- list.add(UserHandle.getUid(user, app.getKey()));
+ list.add(user.getUid(app.getKey()));
}
}
try {
@@ -555,7 +555,7 @@
final UserHandle handle = UserHandle.of(userId);
if (handle == null) continue;
- final int uid = UserHandle.getUid(handle, appId);
+ final int uid = handle.getUid(appId);
if (range.contains(uid)) {
result.add(uid);
}
diff --git a/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java b/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java
index dedf2e2..049a339 100644
--- a/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java
+++ b/services/core/java/com/android/server/hdmi/ArcTerminationActionFromAvr.java
@@ -49,10 +49,7 @@
switch (cmd.getOpcode()) {
case Constants.MESSAGE_REPORT_ARC_TERMINATED:
mState = STATE_ARC_TERMINATED;
- audioSystem().setArcStatus(false);
- if (audioSystem().getLocalActivePort() == Constants.CEC_SWITCH_ARC) {
- audioSystem().routeToInputFromPortId(audioSystem().getRoutingPort());
- }
+ audioSystem().processArcTermination();
finish();
return true;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index f876e1a..39a9119 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -557,8 +557,12 @@
@ServiceThreadOnly
protected boolean handleReportArcInitiate(HdmiCecMessage message) {
assertRunOnServiceThread();
- // TODO(amyjojo): implement report arc initiate handler
- HdmiLogger.debug(TAG + "Stub handleReportArcInitiate");
+ /*
+ * Ideally, we should have got this response before the {@link ArcInitiationActionFromAvr}
+ * has timed out. Even if the response is late, {@link ArcInitiationActionFromAvr
+ * #handleInitiateArcTimeout()} would not have disabled ARC. So nothing needs to be done
+ * here.
+ */
return true;
}
@@ -566,8 +570,7 @@
@ServiceThreadOnly
protected boolean handleReportArcTermination(HdmiCecMessage message) {
assertRunOnServiceThread();
- // TODO(amyjojo): implement report arc terminate handler
- HdmiLogger.debug(TAG + "Stub handleReportArcTermination");
+ processArcTermination();
return true;
}
@@ -912,6 +915,14 @@
mArcEstablished = enabled;
}
+ void processArcTermination() {
+ setArcStatus(false);
+ // Switch away from ARC input when ARC is terminated.
+ if (getLocalActivePort() == Constants.CEC_SWITCH_ARC) {
+ routeToInputFromPortId(getRoutingPort());
+ }
+ }
+
/** Switch hardware ARC circuit in the system. */
@ServiceThreadOnly
private void enableAudioReturnChannel(boolean enabled) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 58a7025..8bb5204 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -800,7 +800,9 @@
assertRunOnServiceThread();
if (!mService.isPowerStandbyOrTransient()) {
addAndStartAction(new SystemAudioAutoInitiationAction(this, avr.getLogicalAddress()));
- if (isConnected(avr.getPortId()) && isArcFeatureEnabled(avr.getPortId())
+ if (!isDirectConnectAddress(avr.getPhysicalAddress())) {
+ startArcAction(false);
+ } else if (isConnected(avr.getPortId()) && isArcFeatureEnabled(avr.getPortId())
&& !hasAction(SetArcTransmissionStateAction.class)) {
startArcAction(true);
}
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 5bd3c57..8017a44 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -841,6 +841,9 @@
}
private void injectBestLocation(Location location) {
+ if (location.isFromMockProvider()) {
+ return;
+ }
if (DEBUG) {
Log.d(TAG, "injectBestLocation: " + location);
}
@@ -942,6 +945,9 @@
}
private void injectLocation(Location location) {
+ if (location.isFromMockProvider()) {
+ return;
+ }
if (location.hasAccuracy()) {
if (DEBUG) {
Log.d(TAG, "injectLocation: " + location);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 0e4a2ee..ca9c75f 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -267,7 +267,7 @@
mArtStatsLogger,
sessionId,
compilerFilter,
- sharedGid,
+ pkg.getUid(),
packageStats.getCompileTime(path),
dexMetadataPath,
options.getCompilationReason(),
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 58ffba2..48fee0b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -33,6 +33,8 @@
import static android.content.Intent.EXTRA_VERSION_CODE;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
+import static android.content.Intent.CATEGORY_BROWSABLE;
+import static android.content.Intent.CATEGORY_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index ae806aa..7bc6056 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -38,6 +38,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.VcnManagementService.VcnCallback;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
@@ -328,6 +329,8 @@
private void handleNetworkRequested(
@NonNull NetworkRequest request, int score, int providerId) {
+ Slog.v(getLogTag(), "Received request " + request);
+
if (score > getNetworkScore()) {
if (VDBG) {
Slog.v(
@@ -409,6 +412,26 @@
return TAG + " [" + mSubscriptionGroup.hashCode() + "]";
}
+ /**
+ * Dumps the state of this Vcn for logging and debugging purposes.
+ *
+ * <p>PII and credentials MUST NEVER be dumped here.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("Vcn (" + mSubscriptionGroup + "):");
+ pw.increaseIndent();
+
+ pw.println("mCurrentStatus: " + mCurrentStatus);
+
+ pw.println("mVcnGatewayConnections:");
+ for (VcnGatewayConnection gw : mVcnGatewayConnections.values()) {
+ gw.dump(pw);
+ }
+ pw.println();
+
+ pw.decreaseIndent();
+ }
+
/** Retrieves the network score for a VCN Network */
// Package visibility for use in VcnGatewayConnection
static int getNetworkScore() {
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 20c08eb..1d55ba4 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -23,6 +23,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
@@ -57,7 +58,6 @@
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionConfiguration;
import android.net.ipsec.ike.IkeSessionParams;
-import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
@@ -77,6 +77,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
@@ -84,6 +85,7 @@
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
+import com.android.server.vcn.util.MtuUtils;
import java.io.IOException;
import java.net.Inet4Address;
@@ -448,6 +450,44 @@
*/
private static final int EVENT_SAFE_MODE_TIMEOUT_EXCEEDED = 10;
+ /**
+ * Sent when an IKE has completed migration, and created updated transforms for application.
+ *
+ * <p>Only relevant in the Connected state.
+ *
+ * @param arg1 The session token for the IKE Session that completed migration, used to prevent
+ * out-of-date signals from propagating.
+ * @param obj @NonNull An EventMigrationCompletedInfo instance with relevant data.
+ */
+ private static final int EVENT_MIGRATION_COMPLETED = 11;
+
+ private static class EventMigrationCompletedInfo implements EventInfo {
+ @NonNull public final IpSecTransform inTransform;
+ @NonNull public final IpSecTransform outTransform;
+
+ EventMigrationCompletedInfo(
+ @NonNull IpSecTransform inTransform, @NonNull IpSecTransform outTransform) {
+ this.inTransform = Objects.requireNonNull(inTransform);
+ this.outTransform = Objects.requireNonNull(outTransform);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(inTransform, outTransform);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof EventMigrationCompletedInfo)) {
+ return false;
+ }
+
+ final EventMigrationCompletedInfo rhs = (EventMigrationCompletedInfo) other;
+ return Objects.equals(inTransform, rhs.inTransform)
+ && Objects.equals(outTransform, rhs.outTransform);
+ }
+ }
+
@VisibleForTesting(visibility = Visibility.PRIVATE)
@NonNull
final DisconnectedState mDisconnectedState = new DisconnectedState();
@@ -574,7 +614,7 @@
* <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
* otherwise.
*/
- private NetworkAgent mNetworkAgent;
+ private VcnNetworkAgent mNetworkAgent;
@Nullable private WakeupMessage mTeardownTimeoutAlarm;
@Nullable private WakeupMessage mDisconnectRequestAlarm;
@@ -1011,12 +1051,21 @@
sessionLostWithoutCallback(token, exception);
}
+ private static boolean isIkeAuthFailure(@NonNull Exception exception) {
+ if (!(exception instanceof IkeProtocolException)) {
+ return false;
+ }
+
+ return ((IkeProtocolException) exception).getErrorType()
+ == ERROR_TYPE_AUTHENTICATION_FAILED;
+ }
+
private void notifyStatusCallbackForSessionClosed(@NonNull Exception exception) {
final int errorCode;
final String exceptionClass;
final String exceptionMessage;
- if (exception instanceof AuthenticationFailedException) {
+ if (isIkeAuthFailure(exception)) {
errorCode = VCN_ERROR_CODE_CONFIG_ERROR;
exceptionClass = exception.getClass().getName();
exceptionMessage = exception.getMessage();
@@ -1053,6 +1102,14 @@
sendMessageAndAcquireWakeLock(EVENT_SESSION_CLOSED, token);
}
+ private void migrationCompleted(
+ int token, @NonNull IpSecTransform inTransform, @NonNull IpSecTransform outTransform) {
+ sendMessageAndAcquireWakeLock(
+ EVENT_MIGRATION_COMPLETED,
+ token,
+ new EventMigrationCompletedInfo(inTransform, outTransform));
+ }
+
private void childTransformCreated(
int token, @NonNull IpSecTransform transform, int direction) {
sendMessageAndAcquireWakeLock(
@@ -1148,7 +1205,9 @@
case EVENT_SETUP_COMPLETED: // Fallthrough
case EVENT_DISCONNECT_REQUESTED: // Fallthrough
case EVENT_TEARDOWN_TIMEOUT_EXPIRED: // Fallthrough
- case EVENT_SUBSCRIPTIONS_CHANGED:
+ case EVENT_SUBSCRIPTIONS_CHANGED: // Fallthrough
+ case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: // Fallthrough
+ case EVENT_MIGRATION_COMPLETED:
logUnexpectedEvent(msg.what);
break;
default:
@@ -1440,30 +1499,32 @@
private abstract class ConnectedStateBase extends ActiveBaseState {
protected void updateNetworkAgent(
@NonNull IpSecTunnelInterface tunnelIface,
- @NonNull NetworkAgent agent,
+ @NonNull VcnNetworkAgent agent,
@NonNull VcnChildSessionConfiguration childConfig) {
final NetworkCapabilities caps =
buildNetworkCapabilities(mConnectionConfig, mUnderlying);
final LinkProperties lp =
- buildConnectedLinkProperties(mConnectionConfig, tunnelIface, childConfig);
+ buildConnectedLinkProperties(
+ mConnectionConfig, tunnelIface, childConfig, mUnderlying);
agent.sendNetworkCapabilities(caps);
agent.sendLinkProperties(lp);
}
- protected NetworkAgent buildNetworkAgent(
+ protected VcnNetworkAgent buildNetworkAgent(
@NonNull IpSecTunnelInterface tunnelIface,
@NonNull VcnChildSessionConfiguration childConfig) {
final NetworkCapabilities caps =
buildNetworkCapabilities(mConnectionConfig, mUnderlying);
final LinkProperties lp =
- buildConnectedLinkProperties(mConnectionConfig, tunnelIface, childConfig);
+ buildConnectedLinkProperties(
+ mConnectionConfig, tunnelIface, childConfig, mUnderlying);
final NetworkAgentConfig nac =
new NetworkAgentConfig.Builder()
.setLegacyType(ConnectivityManager.TYPE_MOBILE)
.build();
- final NetworkAgent agent =
+ final VcnNetworkAgent agent =
mDeps.newNetworkAgent(
mVcnContext,
TAG,
@@ -1472,15 +1533,21 @@
Vcn.getNetworkScore(),
nac,
mVcnContext.getVcnNetworkProvider(),
- () -> {
- Slog.d(TAG, "NetworkAgent was unwanted");
- // If network agent has already been torn down, skip sending the
- // disconnect. Unwanted() is always called, even when networkAgents
- // are unregistered in teardownNetwork(), so prevent duplicate
- // notifications.
- if (mNetworkAgent != null) {
- teardownAsynchronously();
+ (agentRef) -> {
+ // Only trigger teardown if the NetworkAgent hasn't been replaced or
+ // changed. This guards against two cases - the first where
+ // unwanted() may be called as a result of the
+ // NetworkAgent.unregister() call, which might trigger a teardown
+ // instead of just a Network disconnect, as well as the case where a
+ // new NetworkAgent replaces an old one before the unwanted() call
+ // is processed.
+ if (mNetworkAgent != agentRef) {
+ Slog.d(TAG, "unwanted() called on stale NetworkAgent");
+ return;
}
+
+ Slog.d(TAG, "NetworkAgent was unwanted");
+ teardownAsynchronously();
} /* networkUnwantedCallback */,
(status) -> {
if (status == NetworkAgent.VALIDATION_STATUS_VALID) {
@@ -1620,12 +1687,36 @@
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED:
handleSafeModeTimeoutExceeded();
break;
+ case EVENT_MIGRATION_COMPLETED:
+ final EventMigrationCompletedInfo migrationCompletedInfo =
+ (EventMigrationCompletedInfo) msg.obj;
+
+ handleMigrationCompleted(migrationCompletedInfo);
+ break;
default:
logUnhandledMessage(msg);
break;
}
}
+ private void handleMigrationCompleted(EventMigrationCompletedInfo migrationCompletedInfo) {
+ applyTransform(
+ mCurrentToken,
+ mTunnelIface,
+ mUnderlying.network,
+ migrationCompletedInfo.inTransform,
+ IpSecManager.DIRECTION_IN);
+
+ applyTransform(
+ mCurrentToken,
+ mTunnelIface,
+ mUnderlying.network,
+ migrationCompletedInfo.outTransform,
+ IpSecManager.DIRECTION_OUT);
+
+ updateNetworkAgent(mTunnelIface, mNetworkAgent, mChildConfig);
+ }
+
private void handleUnderlyingNetworkChanged(@NonNull Message msg) {
final UnderlyingNetworkRecord oldUnderlying = mUnderlying;
mUnderlying = ((EventUnderlyingNetworkChangedInfo) msg.obj).newUnderlying;
@@ -1815,7 +1906,10 @@
private static LinkProperties buildConnectedLinkProperties(
@NonNull VcnGatewayConnectionConfig gatewayConnectionConfig,
@NonNull IpSecTunnelInterface tunnelIface,
- @NonNull VcnChildSessionConfiguration childConfig) {
+ @NonNull VcnChildSessionConfiguration childConfig,
+ @Nullable UnderlyingNetworkRecord underlying) {
+ final VcnControlPlaneIkeConfig controlPlaneConfig =
+ (VcnControlPlaneIkeConfig) gatewayConnectionConfig.getControlPlaneConfig();
final LinkProperties lp = new LinkProperties();
lp.setInterfaceName(tunnelIface.getInterfaceName());
@@ -1831,7 +1925,12 @@
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null /*gateway*/,
null /*iface*/, RouteInfo.RTN_UNICAST));
- lp.setMtu(gatewayConnectionConfig.getMaxMtu());
+ final int underlyingMtu = (underlying == null) ? 0 : underlying.linkProperties.getMtu();
+ lp.setMtu(
+ MtuUtils.getMtu(
+ controlPlaneConfig.getChildSessionParams().getSaProposals(),
+ gatewayConnectionConfig.getMaxMtu(),
+ underlyingMtu));
return lp;
}
@@ -1912,8 +2011,7 @@
@NonNull IpSecTransform inIpSecTransform,
@NonNull IpSecTransform outIpSecTransform) {
Slog.v(TAG, "ChildTransformsMigrated; token " + mToken);
- onIpSecTransformCreated(inIpSecTransform, IpSecManager.DIRECTION_IN);
- onIpSecTransformCreated(outIpSecTransform, IpSecManager.DIRECTION_OUT);
+ migrationCompleted(mToken, inIpSecTransform, outIpSecTransform);
}
@Override
@@ -1924,6 +2022,27 @@
}
}
+ /**
+ * Dumps the state of this VcnGatewayConnection for logging and debugging purposes.
+ *
+ * <p>PII and credentials MUST NEVER be dumped here.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("VcnGatewayConnection (" + mConnectionConfig.getGatewayConnectionName() + "):");
+ pw.increaseIndent();
+
+ pw.println("Current state: " + getCurrentState().getClass().getSimpleName());
+ pw.println("mIsQuitting: " + mIsQuitting);
+ pw.println("mIsInSafeMode: " + mIsInSafeMode);
+ pw.println("mCurrentToken: " + mCurrentToken);
+ pw.println("mFailedAttempts: " + mFailedAttempts);
+ pw.println(
+ "mNetworkAgent.getNetwork(): "
+ + (mNetworkAgent == null ? null : mNetworkAgent.getNetwork()));
+
+ pw.decreaseIndent();
+ }
+
@VisibleForTesting(visibility = Visibility.PRIVATE)
void setTunnelInterface(IpSecTunnelInterface tunnelIface) {
mTunnelIface = tunnelIface;
@@ -1965,12 +2084,12 @@
}
@VisibleForTesting(visibility = Visibility.PRIVATE)
- NetworkAgent getNetworkAgent() {
+ VcnNetworkAgent getNetworkAgent() {
return mNetworkAgent;
}
@VisibleForTesting(visibility = Visibility.PRIVATE)
- void setNetworkAgent(@Nullable NetworkAgent networkAgent) {
+ void setNetworkAgent(@Nullable VcnNetworkAgent networkAgent) {
mNetworkAgent = networkAgent;
}
@@ -2058,8 +2177,8 @@
return new WakeupMessage(vcnContext.getContext(), handler, tag, runnable);
}
- /** Builds a new NetworkAgent. */
- public NetworkAgent newNetworkAgent(
+ /** Builds a new VcnNetworkAgent. */
+ public VcnNetworkAgent newNetworkAgent(
@NonNull VcnContext vcnContext,
@NonNull String tag,
@NonNull NetworkCapabilities caps,
@@ -2067,27 +2186,18 @@
@NonNull int score,
@NonNull NetworkAgentConfig nac,
@NonNull NetworkProvider provider,
- @NonNull Runnable networkUnwantedCallback,
+ @NonNull Consumer<VcnNetworkAgent> networkUnwantedCallback,
@NonNull Consumer<Integer> validationStatusCallback) {
- return new NetworkAgent(
- vcnContext.getContext(),
- vcnContext.getLooper(),
+ return new VcnNetworkAgent(
+ vcnContext,
tag,
caps,
lp,
score,
nac,
- provider) {
- @Override
- public void onNetworkUnwanted() {
- networkUnwantedCallback.run();
- }
-
- @Override
- public void onValidationStatus(int status, @Nullable Uri redirectUri) {
- validationStatusCallback.accept(status);
- }
- };
+ provider,
+ networkUnwantedCallback,
+ validationStatusCallback);
}
/** Gets the elapsed real time since boot, in millis. */
@@ -2203,4 +2313,73 @@
mImpl.release();
}
}
+
+ /** Proxy Implementation of NetworkAgent, used for testing. */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class VcnNetworkAgent {
+ private final NetworkAgent mImpl;
+
+ public VcnNetworkAgent(
+ @NonNull VcnContext vcnContext,
+ @NonNull String tag,
+ @NonNull NetworkCapabilities caps,
+ @NonNull LinkProperties lp,
+ @NonNull int score,
+ @NonNull NetworkAgentConfig nac,
+ @NonNull NetworkProvider provider,
+ @NonNull Consumer<VcnNetworkAgent> networkUnwantedCallback,
+ @NonNull Consumer<Integer> validationStatusCallback) {
+ mImpl =
+ new NetworkAgent(
+ vcnContext.getContext(),
+ vcnContext.getLooper(),
+ tag,
+ caps,
+ lp,
+ score,
+ nac,
+ provider) {
+ @Override
+ public void onNetworkUnwanted() {
+ networkUnwantedCallback.accept(VcnNetworkAgent.this);
+ }
+
+ @Override
+ public void onValidationStatus(int status, @Nullable Uri redirectUri) {
+ validationStatusCallback.accept(status);
+ }
+ };
+ }
+
+ /** Registers the underlying NetworkAgent */
+ public void register() {
+ mImpl.register();
+ }
+
+ /** Marks the underlying NetworkAgent as connected */
+ public void markConnected() {
+ mImpl.markConnected();
+ }
+
+ /** Unregisters the underlying NetworkAgent */
+ public void unregister() {
+ mImpl.unregister();
+ }
+
+ /** Sends new NetworkCapabilities for the underlying NetworkAgent */
+ public void sendNetworkCapabilities(@NonNull NetworkCapabilities caps) {
+ mImpl.sendNetworkCapabilities(caps);
+ }
+
+ /** Sends new LinkProperties for the underlying NetworkAgent */
+ public void sendLinkProperties(@NonNull LinkProperties lp) {
+ mImpl.sendLinkProperties(lp);
+ }
+
+ /** Retrieves the Network for the underlying NetworkAgent */
+ @Nullable
+ public Network getNetwork() {
+ return mImpl.getNetwork();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
index a909695..be0deb5 100644
--- a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
+++ b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
@@ -29,6 +29,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
import java.util.Objects;
import java.util.Set;
@@ -129,10 +130,50 @@
mScore = score;
mProviderId = providerId;
}
+
+ /**
+ * Dumps the state of this NetworkRequestEntry for logging and debugging purposes.
+ *
+ * <p>PII and credentials MUST NEVER be dumped here.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("NetworkRequestEntry:");
+ pw.increaseIndent();
+
+ pw.println("mRequest: " + mRequest);
+ pw.println("mScore: " + mScore);
+ pw.println("mProviderId: " + mProviderId);
+
+ pw.decreaseIndent();
+ }
}
// package-private
interface NetworkRequestListener {
void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId);
}
+
+ /**
+ * Dumps the state of this VcnNetworkProvider for logging and debugging purposes.
+ *
+ * <p>PII and credentials MUST NEVER be dumped here.
+ */
+ public void dump(IndentingPrintWriter pw) {
+ pw.println("VcnNetworkProvider:");
+ pw.increaseIndent();
+
+ pw.println("mListeners:");
+ for (NetworkRequestListener listener : mListeners) {
+ pw.println(listener);
+ }
+ pw.println();
+
+ pw.println("mRequests.values:");
+ for (NetworkRequestEntry entry : mRequests.values()) {
+ entry.dump(pw);
+ }
+ pw.println();
+
+ pw.decreaseIndent();
+ }
}
diff --git a/services/core/java/com/android/server/vcn/util/MtuUtils.java b/services/core/java/com/android/server/vcn/util/MtuUtils.java
new file mode 100644
index 0000000..5d40cca
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/util/MtuUtils.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn.util;
+
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_3DES;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CTR;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_CHACHA20_POLY1305;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_CMAC_96;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_NONE;
+
+import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
+
+import static java.lang.Math.max;
+import static java.util.Collections.unmodifiableMap;
+
+import android.annotation.NonNull;
+import android.net.ipsec.ike.ChildSaProposal;
+import android.util.ArrayMap;
+import android.util.Pair;
+import android.util.Slog;
+
+import java.util.List;
+import java.util.Map;
+
+/** @hide */
+public class MtuUtils {
+ private static final String TAG = MtuUtils.class.getSimpleName();
+ /**
+ * Max ESP overhead possible
+ *
+ * <p>60 (Outer IPv4 + options) + 8 (UDP encap) + 4 (SPI) + 4 (Seq) + 2 (Pad + NextHeader)
+ */
+ private static final int GENERIC_ESP_OVERHEAD_MAX = 78;
+
+ /** Maximum overheads of authentication algorithms, keyed on IANA-defined constants */
+ private static final Map<Integer, Integer> AUTH_ALGORITHM_OVERHEAD;
+
+ static {
+ final Map<Integer, Integer> map = new ArrayMap<>();
+ map.put(INTEGRITY_ALGORITHM_NONE, 0);
+ map.put(INTEGRITY_ALGORITHM_HMAC_SHA1_96, 12);
+ map.put(INTEGRITY_ALGORITHM_AES_XCBC_96, 12);
+ map.put(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128, 32);
+ map.put(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192, 48);
+ map.put(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256, 64);
+ map.put(INTEGRITY_ALGORITHM_AES_CMAC_96, 12);
+
+ AUTH_ALGORITHM_OVERHEAD = unmodifiableMap(map);
+ }
+
+ /** Maximum overheads of encryption algorithms, keyed on IANA-defined constants */
+ private static final Map<Integer, Integer> CRYPT_ALGORITHM_OVERHEAD;
+
+ static {
+ final Map<Integer, Integer> map = new ArrayMap<>();
+ map.put(ENCRYPTION_ALGORITHM_3DES, 15); // 8 (IV) + 7 (Max pad)
+ map.put(ENCRYPTION_ALGORITHM_AES_CBC, 31); // 16 (IV) + 15 (Max pad)
+ map.put(ENCRYPTION_ALGORITHM_AES_CTR, 11); // 8 (IV) + 3 (Max pad)
+
+ CRYPT_ALGORITHM_OVERHEAD = unmodifiableMap(map);
+ }
+
+ /** Maximum overheads of combined mode algorithms, keyed on IANA-defined constants */
+ private static final Map<Integer, Integer> AUTHCRYPT_ALGORITHM_OVERHEAD;
+
+ static {
+ final Map<Integer, Integer> map = new ArrayMap<>();
+ map.put(ENCRYPTION_ALGORITHM_AES_GCM_8, 19); // 8 (IV) + 3 (Max pad) + 8 (ICV)
+ map.put(ENCRYPTION_ALGORITHM_AES_GCM_12, 23); // 8 (IV) + 3 (Max pad) + 12 (ICV)
+ map.put(ENCRYPTION_ALGORITHM_AES_GCM_16, 27); // 8 (IV) + 3 (Max pad) + 16 (ICV)
+ map.put(ENCRYPTION_ALGORITHM_CHACHA20_POLY1305, 27); // 8 (IV) + 3 (Max pad) + 16 (ICV)
+
+ AUTHCRYPT_ALGORITHM_OVERHEAD = unmodifiableMap(map);
+ }
+
+ /**
+ * Calculates the MTU of the inner interface based on the parameters provided
+ *
+ * <p>The MTU of the inner interface will be the minimum of the following:
+ *
+ * <ul>
+ * <li>The MTU of the outer interface, minus the greatest ESP overhead (based on proposed
+ * algorithms).
+ * <li>The maximum MTU as provided in the arguments.
+ * </ul>
+ */
+ public static int getMtu(
+ @NonNull List<ChildSaProposal> childProposals, int maxMtu, int underlyingMtu) {
+ if (underlyingMtu <= 0) {
+ return IPV6_MIN_MTU;
+ }
+
+ int maxAuthOverhead = 0;
+ int maxCryptOverhead = 0;
+ int maxAuthCryptOverhead = 0;
+
+ for (ChildSaProposal proposal : childProposals) {
+ for (Pair<Integer, Integer> encryptionAlgoPair : proposal.getEncryptionAlgorithms()) {
+ final int algo = encryptionAlgoPair.first;
+
+ if (AUTHCRYPT_ALGORITHM_OVERHEAD.containsKey(algo)) {
+ maxAuthCryptOverhead =
+ max(maxAuthCryptOverhead, AUTHCRYPT_ALGORITHM_OVERHEAD.get(algo));
+ continue;
+ } else if (CRYPT_ALGORITHM_OVERHEAD.containsKey(algo)) {
+ maxCryptOverhead = max(maxCryptOverhead, CRYPT_ALGORITHM_OVERHEAD.get(algo));
+ continue;
+ }
+
+ Slog.wtf(TAG, "Unknown encryption algorithm requested: " + algo);
+ return IPV6_MIN_MTU;
+ }
+
+ for (int algo : proposal.getIntegrityAlgorithms()) {
+ if (AUTH_ALGORITHM_OVERHEAD.containsKey(algo)) {
+ maxAuthOverhead = max(maxAuthOverhead, AUTH_ALGORITHM_OVERHEAD.get(algo));
+ continue;
+ }
+
+ Slog.wtf(TAG, "Unknown integrity algorithm requested: " + algo);
+ return IPV6_MIN_MTU;
+ }
+ }
+
+ // Return minimum of maxMtu, and the adjusted MTUs based on algorithms.
+ final int combinedModeMtu = underlyingMtu - maxAuthCryptOverhead - GENERIC_ESP_OVERHEAD_MAX;
+ final int normalModeMtu =
+ underlyingMtu - maxCryptOverhead - maxAuthOverhead - GENERIC_ESP_OVERHEAD_MAX;
+ return Math.min(Math.min(maxMtu, combinedModeMtu), normalModeMtu);
+ }
+}
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 5fde550..7a6d310 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -191,19 +191,18 @@
static std::array<std::atomic<HalSupport>,
static_cast<int32_t>(Boost::DISPLAY_UPDATE_IMMINENT) + 1>
boostSupportedArray = {HalSupport::UNKNOWN};
+ size_t idx = static_cast<size_t>(boost);
// Quick return if boost is not supported by HAL
- if (boost > Boost::DISPLAY_UPDATE_IMMINENT ||
- boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::OFF) {
+ if (idx >= boostSupportedArray.size() || boostSupportedArray[idx] == HalSupport::OFF) {
ALOGV("Skipped setPowerBoost %s because HAL doesn't support it", toString(boost).c_str());
return;
}
- if (boostSupportedArray[static_cast<int32_t>(boost)] == HalSupport::UNKNOWN) {
+ if (boostSupportedArray[idx] == HalSupport::UNKNOWN) {
bool isSupported = false;
handle->isBoostSupported(boost, &isSupported);
- boostSupportedArray[static_cast<int32_t>(boost)] =
- isSupported ? HalSupport::ON : HalSupport::OFF;
+ boostSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
if (!isSupported) {
ALOGV("Skipped setPowerBoost %s because HAL doesn't support it",
toString(boost).c_str());
@@ -231,19 +230,18 @@
// Need to increase the array if more mode supported.
static std::array<std::atomic<HalSupport>, static_cast<int32_t>(Mode::DISPLAY_INACTIVE) + 1>
modeSupportedArray = {HalSupport::UNKNOWN};
+ size_t idx = static_cast<size_t>(mode);
// Quick return if mode is not supported by HAL
- if (mode > Mode::DISPLAY_INACTIVE ||
- modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::OFF) {
+ if (idx >= modeSupportedArray.size() || modeSupportedArray[idx] == HalSupport::OFF) {
ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
return false;
}
- if (modeSupportedArray[static_cast<int32_t>(mode)] == HalSupport::UNKNOWN) {
+ if (modeSupportedArray[idx] == HalSupport::UNKNOWN) {
bool isSupported = false;
handle->isModeSupported(mode, &isSupported);
- modeSupportedArray[static_cast<int32_t>(mode)] =
- isSupported ? HalSupport::ON : HalSupport::OFF;
+ modeSupportedArray[idx] = isSupported ? HalSupport::ON : HalSupport::OFF;
if (!isSupported) {
ALOGV("Skipped setPowerMode %s because HAL doesn't support it", toString(mode).c_str());
return false;
diff --git a/services/net/java/android/net/util/KeepalivePacketDataUtil.java b/services/net/java/android/net/util/KeepalivePacketDataUtil.java
index 6e539bb..5666985 100644
--- a/services/net/java/android/net/util/KeepalivePacketDataUtil.java
+++ b/services/net/java/android/net/util/KeepalivePacketDataUtil.java
@@ -80,12 +80,12 @@
parcel.srcPort = pkt.getSrcPort();
parcel.dstAddress = dstAddress.getAddress();
parcel.dstPort = pkt.getDstPort();
- parcel.seq = pkt.tcpSeq;
- parcel.ack = pkt.tcpAck;
- parcel.rcvWnd = pkt.tcpWindow;
- parcel.rcvWndScale = pkt.tcpWindowScale;
- parcel.tos = pkt.ipTos;
- parcel.ttl = pkt.ipTtl;
+ parcel.seq = pkt.getTcpSeq();
+ parcel.ack = pkt.getTcpAck();
+ parcel.rcvWnd = pkt.getTcpWindow();
+ parcel.rcvWndScale = pkt.getTcpWindowScale();
+ parcel.tos = pkt.getIpTos();
+ parcel.ttl = pkt.getIpTtl();
return parcel;
}
diff --git a/services/tests/servicestests/src/com/android/server/uwb/OWNERS b/services/tests/servicestests/src/com/android/server/uwb/OWNERS
new file mode 100644
index 0000000..c31a2f1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/uwb/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/uwb/OWNERS
diff --git a/services/uwb/OWNERS b/services/uwb/OWNERS
new file mode 100644
index 0000000..c31a2f1
--- /dev/null
+++ b/services/uwb/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/uwb/OWNERS
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 38fa907..3c3df51 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -525,7 +525,7 @@
*
* @throws SecurityException if the caller does not have the required permission/privileges
*/
- public static void enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
+ public static void enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
Context context, int subId, String message) {
if (context.checkCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE)
== PERMISSION_GRANTED) {
@@ -545,7 +545,7 @@
*
* @throws SecurityException if the caller does not have the required permission/privileges
*/
- public static void enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ public static void enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Context context, int subId, String message) {
if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
== PERMISSION_GRANTED) {
@@ -567,7 +567,7 @@
*
* @throws SecurityException if the caller does not have the required permission/privileges
*/
- public static void enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ public static void enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Context context, int subId, String message) {
if (context.checkCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
== PERMISSION_GRANTED) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f027cd1..073f1e3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3222,6 +3222,14 @@
public static final String KEY_USE_CALLER_ID_USSD_BOOL = "use_caller_id_ussd_bool";
/**
+ * Call waiting uses USSD command without SS command.
+ * When {@code true}, the call waiting query/set by ussd command.
+ * When {@code false}, doesn't use USSD to query/set call waiting.
+ * @hide
+ */
+ public static final String KEY_USE_CALL_WAITING_USSD_BOOL = "use_call_waiting_ussd_bool";
+
+ /**
* Specifies the service class for call waiting service.
* Default value is
* {@link com.android.internal.telephony.CommandsInterface#SERVICE_CLASS_VOICE}.
@@ -4820,6 +4828,7 @@
sDefaults.putBoolean(KEY_SUPPORT_EMERGENCY_DIALER_SHORTCUT_BOOL, true);
sDefaults.putBoolean(KEY_USE_CALL_FORWARDING_USSD_BOOL, false);
sDefaults.putBoolean(KEY_USE_CALLER_ID_USSD_BOOL, false);
+ sDefaults.putBoolean(KEY_USE_CALL_WAITING_USSD_BOOL, false);
sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
"connected_mmwave:5G,connected:5G,not_restricted_rrc_idle:5G,"
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index fd206c1..c00c741 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -63,7 +63,7 @@
* This feature tag is being deregistered because the PDN that the IMS registration is on is
*changing.
* All open SIP dialogs need to be closed before the PDN change can proceed using
- * {@link SipDelegateConnection#closeDialog(String)}.
+ * {@link SipDelegateConnection#cleanupSession(String)}.
*/
public static final int DEREGISTERING_REASON_PDN_CHANGE = 3;
@@ -74,7 +74,7 @@
* a user triggered hange, such as data being enabled/disabled.
* <p>
* All open SIP dialogs associated with the new deprovisioned feature tag need to be closed
- * using {@link SipDelegateConnection#closeDialog(String)} before the IMS registration
+ * using {@link SipDelegateConnection#cleanupSession(String)} before the IMS registration
* modification can proceed.
*/
public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4;
@@ -84,7 +84,7 @@
* needs to change its supported feature set.
* <p>
* All open SIP Dialogs associated with this feature tag must be closed
- * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed.
+ * using {@link SipDelegateConnection#cleanupSession(String)} before this operation can proceed.
*/
public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5;
@@ -93,7 +93,7 @@
* destroyed.
* <p>
* All open SIP Dialogs associated with this feature tag must be closed
- * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed.
+ * using {@link SipDelegateConnection#cleanupSession(String)} before this operation can proceed.
*/
public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6;
diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java
index 04a772c..d7a19bc 100644
--- a/telephony/java/android/telephony/ims/SipDelegateConnection.java
+++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java
@@ -74,8 +74,30 @@
* closed.
* @param callId The call-ID header value associated with the ongoing SIP Dialog that is
* closing.
+ * @deprecated closeDialog does not capture INVITE forking. Use {@link #cleanupSession} instead.
*/
- void closeDialog(@NonNull String callId);
+ @Deprecated
+ default void closeDialog(@NonNull String callId) {
+ cleanupSession(callId);
+ }
+
+ /**
+ * The SIP session associated with the provided Call-ID is being closed and routing resources
+ * associated with the session are free to be released. Each SIP session may contain multiple
+ * dialogs due to SIP INVITE forking, so this method must be called after all SIP dialogs
+ * associated with the session has closed.
+ * <p>
+ * Calling this method is also mandatory for situations where the framework IMS stack is waiting
+ * for pending SIP sessions to be closed before it can perform a handover or apply a
+ * provisioning change. See {@link DelegateRegistrationState} for more information about
+ * the scenarios where this can occur.
+ * <p>
+ * This method will need to be called for each SIP session managed by this application when it
+ * is closed.
+ * @param callId The call-ID header value associated with the ongoing SIP Dialog that is
+ * closing.
+ */
+ default void cleanupSession(@NonNull String callId) { }
/**
* Notify the SIP delegate that the SIP message has been received from
diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java
index d21fcab..391372a 100644
--- a/telephony/java/android/telephony/ims/SipMessage.java
+++ b/telephony/java/android/telephony/ims/SipMessage.java
@@ -203,23 +203,6 @@
}
/**
- * @return the UTF-8 encoded SIP message.
- * @deprecated Use {@link #toEncodedMessage} instead
- */
- @Deprecated
- public @NonNull byte[] getEncodedMessage() {
- byte[] header = new StringBuilder()
- .append(mStartLine)
- .append(mHeaderSection)
- .append(CRLF)
- .toString().getBytes(UTF_8);
- byte[] sipMessage = new byte[header.length + mContent.length];
- System.arraycopy(header, 0, sipMessage, 0, header.length);
- System.arraycopy(mContent, 0, sipMessage, header.length, mContent.length);
- return sipMessage;
- }
-
- /**
* According RFC-3261 section 7, SIP is a text protocol and uses the UTF-8 charset. Its format
* consists of a start-line, one or more header fields, an empty line indicating the end of the
* header fields, and an optional message-body.
diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
index ad75be4..ff1a8f0 100644
--- a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl
@@ -26,5 +26,5 @@
void sendMessage(in SipMessage sipMessage, long configVersion);
void notifyMessageReceived(in String viaTransactionId);
void notifyMessageReceiveError(in String viaTransactionId, int reason);
- void closeDialog(in String callId);
+ void cleanupSession(in String callId);
}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
index 5c9ec53..6a98d80 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java
@@ -79,11 +79,11 @@
}
@Override
- public void closeDialog(String callId) {
+ public void cleanupSession(String callId) {
SipDelegate d = mDelegate;
final long token = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> d.closeDialog(callId));
+ mExecutor.execute(() -> d.cleanupSession(callId));
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
index ad02fe5..0abb495 100644
--- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java
@@ -200,13 +200,13 @@
}
@Override
- public void closeDialog(String callId) {
+ public void cleanupSession(String callId) {
try {
ISipDelegate conn = getSipDelegateBinder();
if (conn == null) {
return;
}
- conn.closeDialog(callId);
+ conn.cleanupSession(callId);
} catch (RemoteException e) {
// Nothing to do here, app will eventually get remote death callback.
}
diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java
index b036b5e..d5198a0 100644
--- a/telephony/java/android/telephony/ims/stub/SipDelegate.java
+++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java
@@ -76,8 +76,30 @@
*
* @param callId The call-ID header value associated with the ongoing SIP Dialog that the
* framework is requesting be closed.
+ * @deprecated This method does not take into account INVITE forking. Use
+ * {@link #cleanupSession(String)} instead.
*/
- void closeDialog(@NonNull String callId);
+ @Deprecated
+ default void closeDialog(@NonNull String callId) { }
+
+ /**
+ * The remote IMS application has closed a SIP session and the routing resources associated
+ * with the SIP session using the provided Call-ID may now be cleaned up.
+ * <p>
+ * Typically, a SIP session will be considered closed when all associated dialogs receive a
+ * BYE request. After the session has been closed, the IMS application will call
+ * {@link SipDelegateConnection#cleanupSession(String)} to signal to the framework that
+ * resources can be released. In some cases, the framework will request that the ImsService
+ * close the session due to the open SIP session holding up an event such as applying a
+ * provisioning change or handing over to another transport type. See
+ * {@link DelegateRegistrationState}.
+ *
+ * @param callId The call-ID header value associated with the ongoing SIP Session that the
+ * framework is requesting be cleaned up.
+ */
+ default void cleanupSession(@NonNull String callId) {
+ closeDialog(callId);
+ }
/**
* The remote application has received the SIP message and is processing it.
diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
index 1e54093..454d5b5 100644
--- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
@@ -63,8 +63,10 @@
setPartialConnectivityAcceptable(false)
setUnvalidatedConnectivityAcceptable(true)
setLegacyTypeName("TEST_NETWORK")
- disableNat64Detection()
- disableProvisioningNotification()
+ if (isAtLeastS()) {
+ setNat64DetectionEnabled(false)
+ setProvisioningNotificationEnabled(false)
+ }
}.build()
assertTrue(config.isExplicitlySelected())
@@ -73,7 +75,12 @@
assertFalse(config.isPartialConnectivityAcceptable())
assertTrue(config.isUnvalidatedConnectivityAcceptable())
assertEquals("TEST_NETWORK", config.getLegacyTypeName())
- assertFalse(config.isNat64DetectionEnabled())
- assertFalse(config.isProvisioningNotificationEnabled())
+ if (isAtLeastS()) {
+ assertFalse(config.isNat64DetectionEnabled())
+ assertFalse(config.isProvisioningNotificationEnabled())
+ } else {
+ assertTrue(config.isNat64DetectionEnabled())
+ assertTrue(config.isProvisioningNotificationEnabled())
+ }
}
}
diff --git a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
index 6770066..7a18bb0 100644
--- a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
+++ b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
@@ -92,12 +92,12 @@
assertTrue(str.contains(data.dstAddress.hostAddress))
assertTrue(str.contains(data.dstPort.toString()))
// .packet not included in toString()
- assertTrue(str.contains(data.tcpSeq.toString()))
- assertTrue(str.contains(data.tcpAck.toString()))
- assertTrue(str.contains(data.tcpWindow.toString()))
- assertTrue(str.contains(data.tcpWindowScale.toString()))
- assertTrue(str.contains(data.ipTos.toString()))
- assertTrue(str.contains(data.ipTtl.toString()))
+ assertTrue(str.contains(data.getTcpSeq().toString()))
+ assertTrue(str.contains(data.getTcpAck().toString()))
+ assertTrue(str.contains(data.getTcpWindow().toString()))
+ assertTrue(str.contains(data.getTcpWindowScale().toString()))
+ assertTrue(str.contains(data.getIpTos().toString()))
+ assertTrue(str.contains(data.getIpTtl().toString()))
// Update above assertions if field is added
assertFieldCountEquals(5, KeepalivePacketData::class.java)
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index e050495..790f3be 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -356,6 +357,8 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import kotlin.reflect.KClass;
@@ -9950,6 +9953,7 @@
@Test
public void testDumpDoesNotCrash() {
+ mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
// Filing a couple requests prior to testing the dump.
final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
@@ -11706,6 +11710,33 @@
}
@Test
+ public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
+ mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
+ @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+ OEM_NETWORK_PREFERENCE_OEM_PAID;
+ final StringWriter stringWriter = new StringWriter();
+ final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
+ final Pattern pattern = Pattern.compile(logIdentifier);
+
+ final int expectedNumLogs = 2;
+ final UidRangeParcel[] uidRanges =
+ toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
+
+ // Call twice to generate two logs.
+ setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+ setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+ mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+ final String dumpOutput = stringWriter.toString();
+ final Matcher matcher = pattern.matcher(dumpOutput);
+ int count = 0;
+ while (matcher.find()) {
+ count++;
+ }
+ assertEquals(expectedNumLogs, count);
+ }
+
+ @Test
public void testGetAllNetworkStateSnapshot() throws Exception {
verifyNoNetwork();
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index fec5ef3..d7535a9 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -197,7 +197,7 @@
} else {
pkgInfo = packageInfoWithPermissions(REQUESTED_PERMISSION_GRANTED, new String[] {}, "");
}
- pkgInfo.applicationInfo.uid = UserHandle.getUid(user, UserHandle.getAppId(uid));
+ pkgInfo.applicationInfo.uid = user.getUid(UserHandle.getAppId(uid));
return pkgInfo;
}
@@ -390,7 +390,7 @@
public void expectPermission(Boolean permission, UserHandle[] users, int[] apps) {
for (final UserHandle user : users) {
for (final int app : apps) {
- final int uid = UserHandle.getUid(user, app);
+ final int uid = user.getUid(app);
if (!mApps.containsKey(uid)) {
fail("uid " + uid + " does not exist.");
}
@@ -404,7 +404,7 @@
public void expectNoPermission(UserHandle[] users, int[] apps) {
for (final UserHandle user : users) {
for (final int app : apps) {
- final int uid = UserHandle.getUid(user, app);
+ final int uid = user.getUid(app);
if (mApps.containsKey(uid)) {
fail("uid " + uid + " has listed permissions, expected none.");
}
@@ -502,9 +502,9 @@
// When MOCK_UID1 package is uninstalled and reinstalled, expect Netd to be updated
mPermissionMonitor.onPackageRemoved(
- MOCK_PACKAGE1, UserHandle.getUid(MOCK_USER1, MOCK_UID1));
+ MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1}));
- mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, UserHandle.getUid(MOCK_USER1, MOCK_UID1));
+ mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"),
aryEq(new int[] {MOCK_UID1}));
@@ -541,13 +541,13 @@
mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange, VPN_UID);
// Newly-installed package should have uid rules added
- mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, UserHandle.getUid(MOCK_USER1, MOCK_UID1));
+ mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"),
aryEq(new int[] {MOCK_UID1}));
// Removed package should have its uid rules removed
mPermissionMonitor.onPackageRemoved(
- MOCK_PACKAGE1, UserHandle.getUid(MOCK_USER1, MOCK_UID1));
+ MOCK_PACKAGE1, MOCK_USER1.getUid(MOCK_UID1));
verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID1}));
}
@@ -557,13 +557,13 @@
// called multiple times with the uid corresponding to each user.
private void addPackageForUsers(UserHandle[] users, String packageName, int uid) {
for (final UserHandle user : users) {
- mPermissionMonitor.onPackageAdded(packageName, UserHandle.getUid(user, uid));
+ mPermissionMonitor.onPackageAdded(packageName, user.getUid(uid));
}
}
private void removePackageForUsers(UserHandle[] users, String packageName, int uid) {
for (final UserHandle user : users) {
- mPermissionMonitor.onPackageRemoved(packageName, UserHandle.getUid(user, uid));
+ mPermissionMonitor.onPackageRemoved(packageName, user.getUid(uid));
}
}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 43e6676..bbc9bb6 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -81,7 +81,6 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.net.module.util.LocationPermissionChecker;
import com.android.server.VcnManagementService.VcnCallback;
import com.android.server.VcnManagementService.VcnStatusCallbackInfo;
import com.android.server.vcn.TelephonySubscriptionTracker;
@@ -162,8 +161,6 @@
mock(PersistableBundleUtils.LockingReadWriteHelper.class);
private final TelephonySubscriptionTracker mSubscriptionTracker =
mock(TelephonySubscriptionTracker.class);
- private final LocationPermissionChecker mLocationPermissionChecker =
- mock(LocationPermissionChecker.class);
private final ArgumentCaptor<VcnCallback> mVcnCallbackCaptor =
ArgumentCaptor.forClass(VcnCallback.class);
@@ -207,9 +204,6 @@
doReturn(mConfigReadWriteHelper)
.when(mMockDeps)
.newPersistableBundleLockingReadWriteHelper(any());
- doReturn(mLocationPermissionChecker)
- .when(mMockDeps)
- .newLocationPermissionChecker(eq(mMockContext));
// Setup VCN instance generation
doAnswer((invocation) -> {
@@ -521,10 +515,6 @@
@Test
public void testSetVcnConfigNotifiesStatusCallback() throws Exception {
- mVcnMgmtSvc.systemReady();
- doReturn(true)
- .when(mLocationPermissionChecker)
- .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any());
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2));
mVcnMgmtSvc.registerVcnStatusCallback(TEST_UUID_2, mMockStatusCallback, TEST_PACKAGE_NAME);
@@ -697,10 +687,6 @@
doReturn(isVcnActive ? VCN_STATUS_CODE_ACTIVE : VCN_STATUS_CODE_SAFE_MODE)
.when(vcn)
.getStatus();
-
- doReturn(true)
- .when(mLocationPermissionChecker)
- .checkLocationPermission(eq(TEST_PACKAGE_NAME), any(), eq(TEST_UID), any());
}
private NetworkCapabilities.Builder getNetworkCapabilitiesBuilderForTransport(
@@ -933,8 +919,7 @@
@NonNull ParcelUuid subGroup,
@NonNull String pkgName,
int uid,
- boolean hasPermissionsforSubGroup,
- boolean hasLocationPermission)
+ boolean hasPermissionsforSubGroup)
throws Exception {
TelephonySubscriptionSnapshot snapshot =
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(subGroup));
@@ -946,10 +931,6 @@
.when(snapshot)
.packageHasPermissionsForSubscriptionGroup(eq(subGroup), eq(pkgName));
- doReturn(hasLocationPermission)
- .when(mLocationPermissionChecker)
- .checkLocationPermission(eq(pkgName), any(), eq(uid), any());
-
mVcnMgmtSvc.registerVcnStatusCallback(subGroup, mMockStatusCallback, pkgName);
triggerVcnSafeMode(subGroup, snapshot, true /* enterSafeMode */);
@@ -959,11 +940,7 @@
public void testVcnStatusCallbackOnSafeModeStatusChangedWithCarrierPrivileges()
throws Exception {
triggerVcnStatusCallbackOnSafeModeStatusChanged(
- TEST_UUID_1,
- TEST_PACKAGE_NAME,
- TEST_UID,
- true /* hasPermissionsforSubGroup */,
- true /* hasLocationPermission */);
+ TEST_UUID_1, TEST_PACKAGE_NAME, TEST_UID, true /* hasPermissionsforSubGroup */);
verify(mMockStatusCallback).onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
}
@@ -972,25 +949,7 @@
public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutCarrierPrivileges()
throws Exception {
triggerVcnStatusCallbackOnSafeModeStatusChanged(
- TEST_UUID_1,
- TEST_PACKAGE_NAME,
- TEST_UID,
- false /* hasPermissionsforSubGroup */,
- true /* hasLocationPermission */);
-
- verify(mMockStatusCallback, never())
- .onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
- }
-
- @Test
- public void testVcnStatusCallbackOnSafeModeStatusChangedWithoutLocationPermission()
- throws Exception {
- triggerVcnStatusCallbackOnSafeModeStatusChanged(
- TEST_UUID_1,
- TEST_PACKAGE_NAME,
- TEST_UID,
- true /* hasPermissionsforSubGroup */,
- false /* hasLocationPermission */);
+ TEST_UUID_1, TEST_PACKAGE_NAME, TEST_UID, false /* hasPermissionsforSubGroup */);
verify(mMockStatusCallback, never())
.onVcnStatusChanged(VcnManager.VCN_STATUS_CODE_SAFE_MODE);
@@ -1052,9 +1011,6 @@
.when(snapshot)
.packageHasPermissionsForSubscriptionGroup(
eq(TEST_UUID_1), eq(TEST_CB_PACKAGE_NAME));
- doReturn(true)
- .when(mLocationPermissionChecker)
- .checkLocationPermission(eq(TEST_CB_PACKAGE_NAME), any(), eq(TEST_UID), any());
mVcnMgmtSvc.registerVcnStatusCallback(
TEST_UUID_1, mMockStatusCallback, TEST_CB_PACKAGE_NAME);
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 34c0018..a2223e8 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -20,12 +20,15 @@
import static android.net.IpSecManager.DIRECTION_OUT;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
+import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_TEMPORARY_FAILURE;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
+import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -40,21 +43,25 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
-import android.net.ipsec.ike.exceptions.AuthenticationFailedException;
+import android.net.ipsec.ike.ChildSaProposal;
import android.net.ipsec.ike.exceptions.IkeException;
import android.net.ipsec.ike.exceptions.IkeInternalException;
-import android.net.ipsec.ike.exceptions.TemporaryFailureException;
+import android.net.ipsec.ike.exceptions.IkeProtocolException;
+import android.net.vcn.VcnControlPlaneIkeConfig;
import android.net.vcn.VcnManager.VcnErrorCode;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.vcn.util.MtuUtils;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -73,13 +80,13 @@
@SmallTest
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
private VcnIkeSession mIkeSession;
- private NetworkAgent mNetworkAgent;
+ private VcnNetworkAgent mNetworkAgent;
@Before
public void setUp() throws Exception {
super.setUp();
- mNetworkAgent = mock(NetworkAgent.class);
+ mNetworkAgent = mock(VcnNetworkAgent.class);
doReturn(mNetworkAgent)
.when(mDeps)
.newNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), any(), any());
@@ -152,7 +159,9 @@
}
@Test
- public void testMigratedTransformsAreApplied() throws Exception {
+ public void testMigration() throws Exception {
+ triggerChildOpened();
+
getChildSessionCallback()
.onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform());
mTestLooper.dispatchAll();
@@ -170,6 +179,17 @@
}
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
+
+ final List<ChildSaProposal> saProposals =
+ ((VcnControlPlaneIkeConfig) mConfig.getControlPlaneConfig())
+ .getChildSessionParams()
+ .getSaProposals();
+ final int expectedMtu =
+ MtuUtils.getMtu(
+ saProposals,
+ mConfig.getMaxMtu(),
+ TEST_UNDERLYING_NETWORK_RECORD_1.linkProperties.getMtu());
+ verify(mNetworkAgent).sendLinkProperties(argThat(lp -> expectedMtu == lp.getMtu()));
}
private void triggerChildOpened() {
@@ -299,8 +319,9 @@
.removeAddressFromTunnelInterface(
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());
- // TODO(b/184579891): Also verify link properties updated and sent when sendLinkProperties
- // is mockable
+ verify(mNetworkAgent).sendLinkProperties(argThat(
+ lp -> newInternalAddrs.equals(lp.getLinkAddresses())
+ && Collections.singletonList(TEST_DNS_ADDR_2).equals(lp.getDnsServers())));
// Verify that IpSecTunnelInterface only created once
verify(mIpSecSvc).createTunnelInterface(any(), any(), any(), any(), any());
@@ -323,6 +344,66 @@
assertFalse(mGatewayConnection.isInSafeMode());
}
+ private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() {
+ triggerChildOpened();
+ mTestLooper.dispatchAll();
+
+ final ArgumentCaptor<Consumer<VcnNetworkAgent>> unwantedCallbackCaptor =
+ ArgumentCaptor.forClass(Consumer.class);
+ verify(mDeps)
+ .newNetworkAgent(
+ any(),
+ any(),
+ any(),
+ any(),
+ anyInt(),
+ any(),
+ any(),
+ unwantedCallbackCaptor.capture(),
+ any());
+
+ return unwantedCallbackCaptor.getValue();
+ }
+
+ @Test
+ public void testUnwantedNetworkAgentTriggersTeardown() throws Exception {
+ final Consumer<VcnNetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
+
+ unwantedCallback.accept(mNetworkAgent);
+ mTestLooper.dispatchAll();
+
+ assertTrue(mGatewayConnection.isQuitting());
+ assertEquals(mGatewayConnection.mDisconnectingState, mGatewayConnection.getCurrentState());
+ }
+
+ @Test
+ public void testUnwantedNetworkAgentWithDisconnectedNetworkAgent() throws Exception {
+ final Consumer<VcnNetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
+
+ mGatewayConnection.setNetworkAgent(null);
+ unwantedCallback.accept(mNetworkAgent);
+ mTestLooper.dispatchAll();
+
+ // Verify that the call was ignored; the state machine is still running, and the state has
+ // not changed.
+ assertFalse(mGatewayConnection.isQuitting());
+ assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
+ }
+
+ @Test
+ public void testUnwantedNetworkAgentWithNewNetworkAgent() throws Exception {
+ final Consumer<VcnNetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
+ final VcnNetworkAgent testAgent = mock(VcnNetworkAgent.class);
+
+ mGatewayConnection.setNetworkAgent(testAgent);
+ unwantedCallback.accept(mNetworkAgent);
+ mTestLooper.dispatchAll();
+
+ assertFalse(mGatewayConnection.isQuitting());
+ assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
+ assertEquals(testAgent, mGatewayConnection.getNetworkAgent());
+ }
+
@Test
public void testChildSessionClosedTriggersDisconnect() throws Exception {
// Verify scheduled but not canceled when entering ConnectedState
@@ -391,10 +472,17 @@
any());
}
+ private static IkeProtocolException buildMockIkeProtocolException(int errorCode) {
+ final IkeProtocolException exception = mock(IkeProtocolException.class);
+ when(exception.getErrorType()).thenReturn(errorCode);
+ return exception;
+ }
+
@Test
public void testIkeSessionClosedExceptionallyAuthenticationFailure() throws Exception {
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
- new AuthenticationFailedException("vcn test"), VCN_ERROR_CODE_CONFIG_ERROR);
+ buildMockIkeProtocolException(ERROR_TYPE_AUTHENTICATION_FAILED),
+ VCN_ERROR_CODE_CONFIG_ERROR);
}
@Test
@@ -406,7 +494,8 @@
@Test
public void testIkeSessionClosedExceptionallyInternalFailure() throws Exception {
verifyIkeSessionClosedExceptionalltyNotifiesStatusCallback(
- new TemporaryFailureException("vcn test"), VCN_ERROR_CODE_INTERNAL_ERROR);
+ buildMockIkeProtocolException(ERROR_TYPE_TEMPORARY_FAILURE),
+ VCN_ERROR_CODE_INTERNAL_ERROR);
}
@Test
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index c5ed8f6..dc73be2 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -18,6 +18,7 @@
import static com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
+import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
import static org.junit.Assert.assertEquals;
@@ -44,7 +45,6 @@
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.IkeSessionCallback;
@@ -90,12 +90,18 @@
protected static final int TEST_SUB_ID = 5;
protected static final long ELAPSED_REAL_TIME = 123456789L;
protected static final String TEST_IPSEC_TUNNEL_IFACE = "IPSEC_IFACE";
+
protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_1 =
new UnderlyingNetworkRecord(
new Network(0),
new NetworkCapabilities(),
new LinkProperties(),
false /* blocked */);
+
+ static {
+ TEST_UNDERLYING_NETWORK_RECORD_1.linkProperties.setMtu(1500);
+ }
+
protected static final UnderlyingNetworkRecord TEST_UNDERLYING_NETWORK_RECORD_2 =
new UnderlyingNetworkRecord(
new Network(1),
@@ -103,6 +109,10 @@
new LinkProperties(),
false /* blocked */);
+ static {
+ TEST_UNDERLYING_NETWORK_RECORD_2.linkProperties.setMtu(1460);
+ }
+
protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT =
new TelephonySubscriptionSnapshot(
Collections.singletonMap(TEST_SUB_ID, TEST_SUB_GRP), Collections.EMPTY_MAP);
@@ -278,8 +288,8 @@
protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
@NonNull State expectedState) {
- // Set a NetworkAgent, and expect it to be unregistered and cleared
- final NetworkAgent mockNetworkAgent = mock(NetworkAgent.class);
+ // Set a VcnNetworkAgent, and expect it to be unregistered and cleared
+ final VcnNetworkAgent mockNetworkAgent = mock(VcnNetworkAgent.class);
mGatewayConnection.setNetworkAgent(mockNetworkAgent);
// SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial
diff --git a/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java b/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java
new file mode 100644
index 0000000..29511f7
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/util/MtuUtilsTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.server.vcn.util;
+
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
+import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256;
+
+import static com.android.net.module.util.NetworkStackConstants.ETHER_MTU;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
+import static com.android.server.vcn.util.MtuUtils.getMtu;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import static java.util.Collections.emptyList;
+
+import android.net.ipsec.ike.ChildSaProposal;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class MtuUtilsTest {
+ @Test
+ public void testUnderlyingMtuZero() {
+ assertEquals(
+ IPV6_MIN_MTU, getMtu(emptyList(), ETHER_MTU /* maxMtu */, 0 /* underlyingMtu */));
+ }
+
+ @Test
+ public void testClampsToMaxMtu() {
+ assertEquals(0, getMtu(emptyList(), 0 /* maxMtu */, IPV6_MIN_MTU /* underlyingMtu */));
+ }
+
+ @Test
+ public void testNormalModeAlgorithmLessThanUnderlyingMtu() {
+ final List<ChildSaProposal> saProposals =
+ Arrays.asList(
+ new ChildSaProposal.Builder()
+ .addEncryptionAlgorithm(
+ ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256)
+ .addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128)
+ .build());
+
+ final int actualMtu =
+ getMtu(saProposals, ETHER_MTU /* maxMtu */, ETHER_MTU /* underlyingMtu */);
+ assertTrue(ETHER_MTU > actualMtu);
+ }
+
+ @Test
+ public void testCombinedModeAlgorithmLessThanUnderlyingMtu() {
+ final List<ChildSaProposal> saProposals =
+ Arrays.asList(
+ new ChildSaProposal.Builder()
+ .addEncryptionAlgorithm(
+ ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256)
+ .addEncryptionAlgorithm(
+ ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256)
+ .addEncryptionAlgorithm(
+ ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256)
+ .build());
+
+ final int actualMtu =
+ getMtu(saProposals, ETHER_MTU /* maxMtu */, ETHER_MTU /* underlyingMtu */);
+ assertTrue(ETHER_MTU > actualMtu);
+ }
+}
diff --git a/tools/fonts/Android.bp b/tools/fonts/Android.bp
new file mode 100644
index 0000000..bf50661
--- /dev/null
+++ b/tools/fonts/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2021 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.
+
+python_defaults {
+ name: "fonts_python_defaults",
+ version: {
+ py2: {
+ enabled: false,
+ embedded_launcher: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: true,
+ },
+ },
+}
+
+python_binary_host {
+ name: "fontchain_linter",
+ defaults: ["fonts_python_defaults"],
+ main: "fontchain_linter.py",
+ srcs: [
+ "fontchain_linter.py",
+ ],
+ libs: [
+ "fontTools",
+ ],
+}
diff --git a/tools/hiddenapi/checksorted_sha.sh b/tools/hiddenapi/checksorted_sha.sh
index ceb705f..451fed6 100755
--- a/tools/hiddenapi/checksorted_sha.sh
+++ b/tools/hiddenapi/checksorted_sha.sh
@@ -1,7 +1,7 @@
#!/bin/bash
set -e
LOCAL_DIR="$( dirname ${BASH_SOURCE} )"
-git show --name-only --pretty=format: $1 | grep "config/hiddenapi-.*txt" | while read file; do
+git show --name-only --pretty=format: $1 | grep "boot/hiddenapi/hiddenapi-.*txt" | while read file; do
diff <(git show $1:$file) <(git show $1:$file | $LOCAL_DIR/sort_api.sh ) || {
echo -e "\e[1m\e[31m$file $1 is not sorted or contains duplicates. To sort it correctly:\e[0m"
echo -e "\e[33m${LOCAL_DIR}/sort_api.sh $2/frameworks/base/$file\e[0m"
diff --git a/tools/hiddenapi/exclude.sh b/tools/hiddenapi/exclude.sh
index 2924e01..822aba4 100755
--- a/tools/hiddenapi/exclude.sh
+++ b/tools/hiddenapi/exclude.sh
@@ -48,7 +48,7 @@
PACKAGES=$(for t in $TEAMS; do echo $(eval echo \${${t}_PACKAGES}); done)
RE=$(echo ${PACKAGES} | sed "s/ /|/g")
EXIT_CODE=0
-for file in $(git show --name-only --pretty=format: $SHA | grep "config/hiddenapi-.*txt"); do
+for file in $(git show --name-only --pretty=format: $SHA | grep "boot/hiddenapi/hiddenapi-.*txt"); do
ENTRIES=$(grep -E "^\+L(${RE})/" <(git diff ${SHA}~1 ${SHA} $file) | sed "s|^\+||" || echo)
if [[ -n "${ENTRIES}" ]]; then
echo -e "\e[1m\e[31m$file $SHA contains the following entries\e[0m"