Merge "Fix BatteryStats counts foreground activity time."
diff --git a/Android.bp b/Android.bp
index 6260683..ab85a0a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -65,7 +65,6 @@
// Java/AIDL sources under frameworks/base
":framework-annotations",
":framework-blobstore-sources",
- ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
":framework-connectivity-tiramisu-sources",
":framework-core-sources",
":framework-drm-sources",
@@ -141,20 +140,8 @@
name: "framework-all",
installable: false,
static_libs: [
- "android.net.ipsec.ike.impl",
+ "all-framework-module-impl",
"framework-minus-apex",
- "framework-appsearch.impl",
- "framework-connectivity.impl",
- "framework-graphics.impl",
- "framework-mediaprovider.impl",
- "framework-permission.impl",
- "framework-permission-s.impl",
- "framework-scheduling.impl",
- "framework-sdkextensions.impl",
- "framework-statsd.impl",
- "framework-tethering.impl",
- "framework-wifi.impl",
- "updatable-media",
],
apex_available: ["//apex_available:platform"],
sdk_version: "core_platform",
@@ -272,6 +259,7 @@
defaults: ["framework-aidl-export-defaults"],
srcs: [
":framework-non-updatable-sources",
+ ":framework-bluetooth-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready
"core/java/**/*.logtags",
":apex-info-list",
],
@@ -408,7 +396,6 @@
// TODO: remove these annotations as soon as we can use andoid.support.annotations.*
":framework-annotations",
":modules-utils-preconditions-srcs",
- "core/java/android/net/DhcpResults.java",
"core/java/android/util/IndentingPrintWriter.java",
"core/java/android/util/LocalLog.java",
"core/java/com/android/internal/util/HexDump.java",
@@ -502,7 +489,9 @@
visibility: ["//visibility:private"],
}
-// These defaults are used for both the jar stubs and the doc stubs.
+// Defaults for all stubs that include the non-updatable framework. These defaults do not include
+// module symbols, so will not compile correctly on their own. Users must add module APIs to the
+// classpath (or sources) somehow.
stubs_defaults {
name: "android-non-updatable-stubs-defaults",
srcs: [":android-non-updatable-stub-sources"],
@@ -510,17 +499,14 @@
system_modules: "none",
java_version: "1.8",
arg_files: ["core/res/AndroidManifest.xml"],
- // TODO(b/147699819): remove below aidl includes.
aidl: {
local_include_dirs: [
- "apex/media/aidl/stable",
"media/aidl",
"telephony/java",
],
include_dirs: [
"frameworks/av/aidl",
"frameworks/native/libs/permission/aidl",
- "packages/modules/Connectivity/framework/aidl-export",
],
},
// These are libs from framework-internal-utils that are required (i.e. being referenced)
@@ -542,15 +528,6 @@
"android.hardware.usb.gadget-V1.0-java",
"android.hardware.vibrator-V1.3-java",
"framework-protos",
- "art.module.public.api",
- "sdk_module-lib_current_framework-tethering",
- // There are a few classes from modules used by the core that
- // need to be resolved by metalava. We use a prebuilt stub of the
- // full sdk to ensure we can resolve them. If a new class gets added,
- // the prebuilts/sdk/current needs to be updated.
- "sdk_system_current_android",
- // NOTE: The below can be removed once the prebuilt stub contains IKE.
- "sdk_system_current_android.net.ipsec.ike",
],
filter_packages: packages_to_document,
high_mem: true, // Lots of sources => high memory use, see b/170701554
@@ -562,6 +539,33 @@
visibility: ["//frameworks/base/api"],
}
+// Defaults with module APIs in the classpath (mostly from prebuilts).
+// Suitable for compiling android-non-updatable.
+stubs_defaults {
+ name: "module-classpath-stubs-defaults",
+ aidl: {
+ local_include_dirs: [
+ "apex/media/aidl/stable",
+ ],
+ include_dirs: [
+ "packages/modules/Connectivity/framework/aidl-export",
+ ],
+ },
+ libs: [
+ "art.module.public.api",
+ "sdk_module-lib_current_framework-tethering",
+ "sdk_public_current_framework-bluetooth",
+ // There are a few classes from modules used by the core that
+ // need to be resolved by metalava. We use a prebuilt stub of the
+ // full sdk to ensure we can resolve them. If a new class gets added,
+ // the prebuilts/sdk/current needs to be updated.
+ "sdk_system_current_android",
+ // NOTE: The below can be removed once the prebuilt stub contains IKE.
+ "sdk_system_current_android.net.ipsec.ike",
+ ],
+ defaults_visibility: ["//visibility:private"],
+}
+
build = [
"StubLibraries.bp",
"ApiDocs.bp",
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 4b5f473..5595e95 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -55,6 +55,7 @@
"android-support-multidex-instrumentation",
]
+// These defaults enable doc-stub generation, api lint database generation and sdk value generation.
stubs_defaults {
name: "android-non-updatable-doc-stubs-defaults",
defaults: ["android-non-updatable-stubs-defaults"],
@@ -69,47 +70,10 @@
write_sdk_values: true,
}
-stubs_defaults {
- name: "framework-doc-stubs-default",
- srcs: [
- ":android-non-updatable-stub-sources",
-
- // No longer part of the stubs, but are included in the docs.
- ":android-test-base-sources",
- ":android-test-mock-sources",
- ":android-test-runner-sources",
- ],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- libs: framework_docs_only_libs,
- create_doc_stubs: true,
- annotations_enabled: true,
- filter_packages: packages_to_document,
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
- previous_api: ":android.api.public.latest",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
- write_sdk_values: true,
- // TODO(b/169090544): remove below aidl includes.
- aidl: {
- local_include_dirs: ["media/aidl"],
- include_dirs: [
- "frameworks/av/aidl",
- "frameworks/native/libs/permission/aidl",
- ],
- },
-}
-
// Defaults module for doc-stubs targets that use module source code as input.
stubs_defaults {
name: "framework-doc-stubs-sources-default",
- defaults: ["framework-doc-stubs-default"],
+ defaults: ["android-non-updatable-doc-stubs-defaults"],
srcs: [
":art.module.public.api{.public.stubs.source}",
":conscrypt.module.public.api{.public.stubs.source}",
@@ -117,6 +81,8 @@
":framework-appsearch-sources",
":framework-connectivity-sources",
+ ":framework-bluetooth-sources",
+ ":framework-connectivity-tiramisu-updatable-sources",
":framework-graphics-srcs",
":framework-mediaprovider-sources",
":framework-permission-sources",
@@ -133,13 +99,19 @@
droidstubs {
name: "android-non-updatable-doc-stubs",
- defaults: ["android-non-updatable-doc-stubs-defaults"],
+ defaults: [
+ "android-non-updatable-doc-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args,
}
droidstubs {
name: "android-non-updatable-doc-stubs-system",
- defaults: ["android-non-updatable-doc-stubs-defaults"],
+ defaults: [
+ "android-non-updatable-doc-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args +
" --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
}
@@ -149,14 +121,24 @@
defaults: ["framework-doc-stubs-sources-default"],
args: metalava_framework_docs_args +
" --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
api_levels_sdk_type: "system",
}
droidstubs {
name: "framework-doc-stubs",
- defaults: ["framework-doc-stubs-default"],
+ defaults: ["android-non-updatable-doc-stubs-defaults"],
srcs: [":all-modules-public-stubs-source"],
args: metalava_framework_docs_args,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
aidl: {
local_include_dirs: [
"apex/media/aidl/stable",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 14da6fb..5cb0a78 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -24,23 +24,15 @@
// with the latest frozen API signature.
/////////////////////////////////////////////////////////////////////
-// Common metalava configs
-/////////////////////////////////////////////////////////////////////
-
-stubs_defaults {
- name: "metalava-non-updatable-api-stubs-default",
- defaults: ["android-non-updatable-stubs-defaults"],
- api_levels_annotations_enabled: false,
- defaults_visibility: ["//visibility:private"],
-}
-
-/////////////////////////////////////////////////////////////////////
// These modules provide source files for the stub libraries
/////////////////////////////////////////////////////////////////////
droidstubs {
name: "api-stubs-docs-non-updatable",
- defaults: ["metalava-non-updatable-api-stubs-default"],
+ defaults: [
+ "android-non-updatable-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args,
check_api: {
current: {
@@ -89,7 +81,10 @@
droidstubs {
name: "system-api-stubs-docs-non-updatable",
- defaults: ["metalava-non-updatable-api-stubs-default"],
+ defaults: [
+ "android-non-updatable-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args + priv_apps,
check_api: {
current: {
@@ -125,7 +120,10 @@
droidstubs {
name: "test-api-stubs-docs-non-updatable",
- defaults: ["metalava-non-updatable-api-stubs-default"],
+ defaults: [
+ "android-non-updatable-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args + test + priv_apps_in_stubs,
check_api: {
current: {
@@ -167,7 +165,10 @@
droidstubs {
name: "module-lib-api-stubs-docs-non-updatable",
- defaults: ["metalava-non-updatable-api-stubs-default"],
+ defaults: [
+ "android-non-updatable-stubs-defaults",
+ "module-classpath-stubs-defaults",
+ ],
args: metalava_framework_docs_args + priv_apps_in_stubs + module_libs,
check_api: {
current: {
@@ -206,44 +207,6 @@
// from stub sources
/////////////////////////////////////////////////////////////////////
-modules_public_stubs = [
- "android.net.ipsec.ike.stubs",
- "art.module.public.api.stubs",
- "conscrypt.module.public.api.stubs",
- "framework-appsearch.stubs",
- "framework-connectivity.stubs",
- "framework-graphics.stubs",
- "framework-media.stubs",
- "framework-mediaprovider.stubs",
- "framework-permission.stubs",
- "framework-permission-s.stubs",
- "framework-scheduling.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.system",
- "conscrypt.module.public.api.stubs", // Only has public stubs
- "framework-appsearch.stubs.system",
- "framework-connectivity.stubs.system",
- "framework-graphics.stubs.system",
- "framework-media.stubs.system",
- "framework-mediaprovider.stubs.system",
- "framework-permission.stubs.system",
- "framework-permission-s.stubs.system",
- "framework-scheduling.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"],
@@ -265,7 +228,7 @@
name: "android-non-updatable.stubs",
defaults: ["android-non-updatable_defaults_stubs_current"],
srcs: [":api-stubs-docs-non-updatable"],
- libs: modules_public_stubs,
+ libs: ["all-modules-public-stubs"],
dist: {
dir: "apistubs/android/public",
},
@@ -275,7 +238,7 @@
name: "android-non-updatable.stubs.system",
defaults: ["android-non-updatable_defaults_stubs_current"],
srcs: [":system-api-stubs-docs-non-updatable"],
- libs: modules_system_stubs,
+ libs: ["all-modules-system-stubs"],
dist: {
dir: "apistubs/android/system",
},
@@ -287,6 +250,8 @@
srcs: [":module-lib-api-stubs-docs-non-updatable"],
libs: [
"sdk_module-lib_current_framework-tethering",
+ "sdk_public_current_framework-bluetooth",
+ // NOTE: The below can be removed once the prebuilt stub contains bluetooth.
"sdk_system_current_android",
// NOTE: The below can be removed once the prebuilt stub contains IKE.
"sdk_system_current_android.net.ipsec.ike",
@@ -300,7 +265,7 @@
name: "android-non-updatable.stubs.test",
defaults: ["android-non-updatable_defaults_stubs_current"],
srcs: [":test-api-stubs-docs-non-updatable"],
- libs: modules_system_stubs,
+ libs: ["all-modules-system-stubs"],
dist: {
dir: "apistubs/android/test",
},
@@ -318,7 +283,8 @@
java_library {
name: "android_stubs_current",
- static_libs: modules_public_stubs + [
+ static_libs: [
+ "all-modules-public-stubs",
"android-non-updatable.stubs",
"private-stub-annotations-jar",
],
@@ -327,7 +293,8 @@
java_library {
name: "android_system_stubs_current",
- static_libs: modules_system_stubs + [
+ static_libs: [
+ "all-modules-system-stubs",
"android-non-updatable.stubs.system",
"private-stub-annotations-jar",
],
@@ -352,7 +319,8 @@
name: "android_test_stubs_current",
// 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 + [
+ static_libs: [
+ "all-modules-system-stubs",
"android-non-updatable.stubs.test",
"private-stub-annotations-jar",
],
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index d963e68..6195f257e 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -63,8 +63,8 @@
min_sdk_version: "29",
visibility: [
"//frameworks/av/apex:__subpackages__",
- "//frameworks/base", // For framework-all
"//frameworks/base/apex/media/service",
+ "//frameworks/base/api", // For framework-all
],
}
diff --git a/api/Android.bp b/api/Android.bp
index d5d2105..15356bd 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -110,7 +110,9 @@
"art.module.public.api",
"conscrypt.module.public.api",
"framework-appsearch",
+ "framework-bluetooth",
"framework-connectivity",
+ "framework-connectivity-tiramisu",
"framework-graphics",
"framework-media",
"framework-mediaprovider",
diff --git a/api/OWNERS b/api/OWNERS
index a027270..4d8ed03 100644
--- a/api/OWNERS
+++ b/api/OWNERS
@@ -4,3 +4,6 @@
file:platform/packages/modules/common:/OWNERS
per-file Android.bp = file:platform/build/soong:/OWNERS
+
+# For metalava team to disable lint checks in platform
+per-file Android.bp = aurimas@google.com,emberrose@google.com,sjgilbert@google.com
\ No newline at end of file
diff --git a/api/api.go b/api/api.go
index 4b6ebc1..5e5f60e 100644
--- a/api/api.go
+++ b/api/api.go
@@ -27,6 +27,7 @@
const art = "art.module.public.api"
const conscrypt = "conscrypt.module.public.api"
const i18n = "i18n.module.public.api"
+var core_libraries_modules = []string{art, conscrypt, i18n}
// The intention behind this soong plugin is to generate a number of "merged"
// API-related modules that would otherwise require a large amount of very
@@ -148,8 +149,6 @@
// This produces the same annotations.zip as framework-doc-stubs, but by using
// outputs from individual modules instead of all the source code.
func createMergedAnnotations(ctx android.LoadHookContext, modules []string) {
- // Conscrypt and i18n currently do not enable annotations
- modules = removeAll(modules, []string{conscrypt, i18n})
props := genruleProps{}
props.Name = proptools.StringPtr("sdk-annotations.zip")
props.Tools = []string{"merge_annotation_zips", "soong_zip"}
@@ -183,9 +182,46 @@
ctx.CreateModule(genrule.GenRuleFactory, &props)
}
-func createMergedModuleLibStubs(ctx android.LoadHookContext, modules []string) {
+func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-modules-public-stubs")
+ props.Static_libs = transformArray(modules, "", ".stubs")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-modules-system-stubs")
+ props.Static_libs = transformArray(modules, "", ".stubs.system")
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedFrameworkImpl(ctx android.LoadHookContext, modules []string) {
+ // This module is for the "framework-all" module, which should not include the core libraries.
+ modules = removeAll(modules, core_libraries_modules)
+ // TODO(b/214988855): remove the line below when framework-bluetooth has an impl jar.
+ modules = remove(modules, "framework-bluetooth")
+ props := libraryProps{}
+ props.Name = proptools.StringPtr("all-framework-module-impl")
+ props.Static_libs = transformArray(modules, "", ".impl")
+ // Media module's impl jar is called "updatable-media"
+ for i, v := range props.Static_libs {
+ if v == "framework-media.impl" {
+ props.Static_libs[i] = "updatable-media"
+ }
+ }
+ props.Sdk_version = proptools.StringPtr("module_current")
+ props.Visibility = []string{"//frameworks/base"}
+ ctx.CreateModule(java.LibraryFactory, &props)
+}
+
+func createMergedFrameworkModuleLibStubs(ctx android.LoadHookContext, modules []string) {
// The user of this module compiles against the "core" SDK, so remove core libraries to avoid dupes.
- modules = removeAll(modules, []string{art, conscrypt, i18n})
+ modules = removeAll(modules, core_libraries_modules)
props := libraryProps{}
props.Name = proptools.StringPtr("framework-updatable-stubs-module_libs_api")
props.Static_libs = transformArray(modules, "", ".stubs.module_lib")
@@ -204,8 +240,6 @@
func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
var textFiles []MergedTxtDefinition
- // Two module libraries currently do not support @SystemApi so only have the public scope.
- bcpWithSystemApi := removeAll(bootclasspath, []string{conscrypt, i18n})
tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
for i, f := range []string{"current.txt", "removed.txt"} {
@@ -219,14 +253,14 @@
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
BaseTxt: ":non-updatable-system-" + f,
- Modules: bcpWithSystemApi,
+ Modules: bootclasspath,
ModuleTag: "{.system" + tagSuffix[i],
Scope: "system",
})
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
BaseTxt: ":non-updatable-module-lib-" + f,
- Modules: bcpWithSystemApi,
+ Modules: bootclasspath,
ModuleTag: "{.module-lib" + tagSuffix[i],
Scope: "module-lib",
})
@@ -253,7 +287,10 @@
createMergedStubsSrcjar(ctx, bootclasspath)
- createMergedModuleLibStubs(ctx, bootclasspath)
+ createMergedPublicStubs(ctx, bootclasspath)
+ createMergedSystemStubs(ctx, bootclasspath)
+ createMergedFrameworkModuleLibStubs(ctx, bootclasspath)
+ createMergedFrameworkImpl(ctx, bootclasspath)
createMergedAnnotations(ctx, bootclasspath)
diff --git a/boot/hiddenapi/hiddenapi-max-target-o.txt b/boot/hiddenapi/hiddenapi-max-target-o.txt
index 0ec918b..9153426 100644
--- a/boot/hiddenapi/hiddenapi-max-target-o.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-o.txt
@@ -36441,93 +36441,6 @@
Landroid/net/MobileLinkQualityInfo;->mLteSignalStrength:I
Landroid/net/MobileLinkQualityInfo;->mMobileNetworkType:I
Landroid/net/MobileLinkQualityInfo;->mRssi:I
-Landroid/net/nsd/DnsSdTxtRecord;-><init>()V
-Landroid/net/nsd/DnsSdTxtRecord;-><init>(Landroid/net/nsd/DnsSdTxtRecord;)V
-Landroid/net/nsd/DnsSdTxtRecord;-><init>([B)V
-Landroid/net/nsd/DnsSdTxtRecord;->contains(Ljava/lang/String;)Z
-Landroid/net/nsd/DnsSdTxtRecord;->CREATOR:Landroid/os/Parcelable$Creator;
-Landroid/net/nsd/DnsSdTxtRecord;->get(Ljava/lang/String;)Ljava/lang/String;
-Landroid/net/nsd/DnsSdTxtRecord;->getKey(I)Ljava/lang/String;
-Landroid/net/nsd/DnsSdTxtRecord;->getRawData()[B
-Landroid/net/nsd/DnsSdTxtRecord;->getValue(I)[B
-Landroid/net/nsd/DnsSdTxtRecord;->getValue(Ljava/lang/String;)[B
-Landroid/net/nsd/DnsSdTxtRecord;->getValueAsString(I)Ljava/lang/String;
-Landroid/net/nsd/DnsSdTxtRecord;->insert([B[BI)V
-Landroid/net/nsd/DnsSdTxtRecord;->keyCount()I
-Landroid/net/nsd/DnsSdTxtRecord;->mData:[B
-Landroid/net/nsd/DnsSdTxtRecord;->mSeperator:B
-Landroid/net/nsd/DnsSdTxtRecord;->remove(Ljava/lang/String;)I
-Landroid/net/nsd/DnsSdTxtRecord;->set(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/net/nsd/DnsSdTxtRecord;->size()I
-Landroid/net/nsd/INsdManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
-Landroid/net/nsd/INsdManager$Stub$Proxy;->getInterfaceDescriptor()Ljava/lang/String;
-Landroid/net/nsd/INsdManager$Stub$Proxy;->getMessenger()Landroid/os/Messenger;
-Landroid/net/nsd/INsdManager$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Landroid/net/nsd/INsdManager$Stub$Proxy;->setEnabled(Z)V
-Landroid/net/nsd/INsdManager$Stub;-><init>()V
-Landroid/net/nsd/INsdManager$Stub;->DESCRIPTOR:Ljava/lang/String;
-Landroid/net/nsd/INsdManager$Stub;->TRANSACTION_getMessenger:I
-Landroid/net/nsd/INsdManager$Stub;->TRANSACTION_setEnabled:I
-Landroid/net/nsd/INsdManager;->setEnabled(Z)V
-Landroid/net/nsd/NsdManager;-><init>(Landroid/content/Context;Landroid/net/nsd/INsdManager;)V
-Landroid/net/nsd/NsdManager;->BASE:I
-Landroid/net/nsd/NsdManager;->checkListener(Ljava/lang/Object;)V
-Landroid/net/nsd/NsdManager;->checkProtocol(I)V
-Landroid/net/nsd/NsdManager;->checkServiceInfo(Landroid/net/nsd/NsdServiceInfo;)V
-Landroid/net/nsd/NsdManager;->DBG:Z
-Landroid/net/nsd/NsdManager;->DISABLE:I
-Landroid/net/nsd/NsdManager;->disconnect()V
-Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES:I
-Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES_FAILED:I
-Landroid/net/nsd/NsdManager;->DISCOVER_SERVICES_STARTED:I
-Landroid/net/nsd/NsdManager;->ENABLE:I
-Landroid/net/nsd/NsdManager;->EVENT_NAMES:Landroid/util/SparseArray;
-Landroid/net/nsd/NsdManager;->fatal(Ljava/lang/String;)V
-Landroid/net/nsd/NsdManager;->FIRST_LISTENER_KEY:I
-Landroid/net/nsd/NsdManager;->getListenerKey(Ljava/lang/Object;)I
-Landroid/net/nsd/NsdManager;->getMessenger()Landroid/os/Messenger;
-Landroid/net/nsd/NsdManager;->getNsdServiceInfoType(Landroid/net/nsd/NsdServiceInfo;)Ljava/lang/String;
-Landroid/net/nsd/NsdManager;->init()V
-Landroid/net/nsd/NsdManager;->mAsyncChannel:Lcom/android/internal/util/AsyncChannel;
-Landroid/net/nsd/NsdManager;->mConnected:Ljava/util/concurrent/CountDownLatch;
-Landroid/net/nsd/NsdManager;->mContext:Landroid/content/Context;
-Landroid/net/nsd/NsdManager;->mHandler:Landroid/net/nsd/NsdManager$ServiceHandler;
-Landroid/net/nsd/NsdManager;->mListenerKey:I
-Landroid/net/nsd/NsdManager;->mListenerMap:Landroid/util/SparseArray;
-Landroid/net/nsd/NsdManager;->mMapLock:Ljava/lang/Object;
-Landroid/net/nsd/NsdManager;->mService:Landroid/net/nsd/INsdManager;
-Landroid/net/nsd/NsdManager;->mServiceMap:Landroid/util/SparseArray;
-Landroid/net/nsd/NsdManager;->nameOf(I)Ljava/lang/String;
-Landroid/net/nsd/NsdManager;->NATIVE_DAEMON_EVENT:I
-Landroid/net/nsd/NsdManager;->nextListenerKey()I
-Landroid/net/nsd/NsdManager;->putListener(Ljava/lang/Object;Landroid/net/nsd/NsdServiceInfo;)I
-Landroid/net/nsd/NsdManager;->REGISTER_SERVICE:I
-Landroid/net/nsd/NsdManager;->REGISTER_SERVICE_FAILED:I
-Landroid/net/nsd/NsdManager;->REGISTER_SERVICE_SUCCEEDED:I
-Landroid/net/nsd/NsdManager;->removeListener(I)V
-Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE:I
-Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE_FAILED:I
-Landroid/net/nsd/NsdManager;->RESOLVE_SERVICE_SUCCEEDED:I
-Landroid/net/nsd/NsdManager;->SERVICE_FOUND:I
-Landroid/net/nsd/NsdManager;->SERVICE_LOST:I
-Landroid/net/nsd/NsdManager;->setEnabled(Z)V
-Landroid/net/nsd/NsdManager;->STOP_DISCOVERY:I
-Landroid/net/nsd/NsdManager;->STOP_DISCOVERY_FAILED:I
-Landroid/net/nsd/NsdManager;->STOP_DISCOVERY_SUCCEEDED:I
-Landroid/net/nsd/NsdManager;->TAG:Ljava/lang/String;
-Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE:I
-Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE_FAILED:I
-Landroid/net/nsd/NsdManager;->UNREGISTER_SERVICE_SUCCEEDED:I
-Landroid/net/nsd/NsdServiceInfo;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/net/nsd/NsdServiceInfo;->getTxtRecord()[B
-Landroid/net/nsd/NsdServiceInfo;->getTxtRecordSize()I
-Landroid/net/nsd/NsdServiceInfo;->mHost:Ljava/net/InetAddress;
-Landroid/net/nsd/NsdServiceInfo;->mPort:I
-Landroid/net/nsd/NsdServiceInfo;->mServiceName:Ljava/lang/String;
-Landroid/net/nsd/NsdServiceInfo;->mServiceType:Ljava/lang/String;
-Landroid/net/nsd/NsdServiceInfo;->mTxtRecord:Landroid/util/ArrayMap;
-Landroid/net/nsd/NsdServiceInfo;->setTxtRecords(Ljava/lang/String;)V
-Landroid/net/nsd/NsdServiceInfo;->TAG:Ljava/lang/String;
Landroid/net/PacProxySelector;-><init>()V
Landroid/net/PacProxySelector;->mDefaultList:Ljava/util/List;
Landroid/net/PacProxySelector;->mProxyService:Lcom/android/net/IProxyService;
diff --git a/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
index 79d2521..20d7cc0 100644
--- a/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
@@ -21,7 +21,6 @@
Landroid/Manifest$permission;->READ_FRAME_BUFFER:Ljava/lang/String;
Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
Landroid/net/INetworkPolicyListener$Stub;-><init>()V
-Landroid/net/nsd/INsdManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/nsd/INsdManager;
Landroid/net/sip/ISipSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/net/sip/ISipSession;
Landroid/nfc/INfcAdapter$Stub;->TRANSACTION_enable:I
Landroid/os/IPowerManager$Stub;->TRANSACTION_acquireWakeLock:I
diff --git a/cmds/app_process/Android.bp b/cmds/app_process/Android.bp
index a157517..6a685a79 100644
--- a/cmds/app_process/Android.bp
+++ b/cmds/app_process/Android.bp
@@ -64,6 +64,8 @@
"libwilhelm",
],
+ header_libs: ["bionic_libc_platform_headers"],
+
compile_multilib: "both",
cflags: [
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 12083b6..815f945 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,6 +15,7 @@
#include <android-base/macros.h>
#include <binder/IPCThreadState.h>
+#include <bionic/pac.h>
#include <hwbinder/IPCThreadState.h>
#include <utils/Log.h>
#include <cutils/memory.h>
@@ -182,6 +183,10 @@
ALOGV("app_process main with argv: %s", argv_String.string());
}
+ // Because of applications that are using PAC instructions incorrectly, PAC
+ // is disabled in application processes for now.
+ ScopedDisablePAC x;
+
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp
index 23d80d7..0d8bd40 100644
--- a/cmds/incidentd/src/WorkDirectory.cpp
+++ b/cmds/incidentd/src/WorkDirectory.cpp
@@ -280,7 +280,7 @@
// Lower privacy policy (less restrictive) wins.
report->set_privacy_policy(args.getPrivacyPolicy());
}
- report->set_all_sections(report->all_sections() | args.all());
+ report->set_all_sections(report->all_sections() || args.all());
for (int section: args.sections()) {
if (!has_section(*report, section)) {
report->add_section(section);
diff --git a/core/api/current.txt b/core/api/current.txt
index d696bc7..235c496 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -7185,6 +7185,7 @@
method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
method @Nullable public java.util.List<java.lang.String> getPermittedInputMethods(@NonNull android.content.ComponentName);
method public int getPersonalAppsSuspendedReasons(@NonNull android.content.ComponentName);
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig();
method public int getRequiredPasswordComplexity();
method public long getRequiredStrongAuthTimeout(@Nullable android.content.ComponentName);
method public boolean getScreenCaptureDisabled(@Nullable android.content.ComponentName);
@@ -7327,6 +7328,7 @@
method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
method public boolean setPermittedInputMethods(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
method public void setPersonalAppsSuspended(@NonNull android.content.ComponentName, boolean);
+ method public void setPreferentialNetworkServiceConfig(@NonNull android.app.admin.PreferentialNetworkServiceConfig);
method public void setPreferentialNetworkServiceEnabled(boolean);
method public void setProfileEnabled(@NonNull android.content.ComponentName);
method public void setProfileName(@NonNull android.content.ComponentName, String);
@@ -7572,6 +7574,32 @@
field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.NetworkEvent> CREATOR;
}
+ public final class PreferentialNetworkServiceConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public int[] getExcludedUids();
+ method @NonNull public int[] getIncludedUids();
+ method public int getNetworkId();
+ method public boolean isEnabled();
+ method public boolean isFallbackToDefaultConnectionAllowed();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.admin.PreferentialNetworkServiceConfig> CREATOR;
+ field public static final int PREFERENTIAL_NETWORK_ID_1 = 1; // 0x1
+ field public static final int PREFERENTIAL_NETWORK_ID_2 = 2; // 0x2
+ field public static final int PREFERENTIAL_NETWORK_ID_3 = 3; // 0x3
+ field public static final int PREFERENTIAL_NETWORK_ID_4 = 4; // 0x4
+ field public static final int PREFERENTIAL_NETWORK_ID_5 = 5; // 0x5
+ }
+
+ public static final class PreferentialNetworkServiceConfig.Builder {
+ ctor public PreferentialNetworkServiceConfig.Builder();
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig build();
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setEnabled(boolean);
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setExcludedUids(@NonNull int[]);
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(boolean);
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setIncludedUids(@NonNull int[]);
+ method @NonNull public android.app.admin.PreferentialNetworkServiceConfig.Builder setNetworkId(int);
+ }
+
public class SecurityLog {
ctor public SecurityLog();
field public static final int LEVEL_ERROR = 3; // 0x3
@@ -8616,1317 +8644,6 @@
}
-package android.bluetooth {
-
- public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
- method public void finalize();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isA2dpPlaying(android.bluetooth.BluetoothDevice);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.CONNECTION_STATE_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PLAYING_STATE_CHANGED = "android.bluetooth.a2dp.profile.action.PLAYING_STATE_CHANGED";
- field public static final int STATE_NOT_PLAYING = 11; // 0xb
- field public static final int STATE_PLAYING = 10; // 0xa
- }
-
- public final class BluetoothAdapter {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean cancelDiscovery();
- method public static boolean checkBluetoothAddress(String);
- method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disable();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enable();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, "android.permission.LOCAL_MAC_ADDRESS"}) public String getAddress();
- method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser();
- method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
- method @Deprecated public static android.bluetooth.BluetoothAdapter getDefaultAdapter();
- method public int getLeMaximumAdvertisingDataLength();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getProfileConnectionState(int);
- method public boolean getProfileProxy(android.content.Context, android.bluetooth.BluetoothProfile.ServiceListener, int);
- method public android.bluetooth.BluetoothDevice getRemoteDevice(String);
- method public android.bluetooth.BluetoothDevice getRemoteDevice(byte[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int getScanMode();
- method public int getState();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean isDiscovering();
- method public boolean isEnabled();
- method public boolean isLe2MPhySupported();
- method public int isLeAudioSupported();
- method public boolean isLeCodedPhySupported();
- method public boolean isLeExtendedAdvertisingSupported();
- method public boolean isLePeriodicAdvertisingSupported();
- method public int isLePeriodicAdvertisingSyncTransferSenderSupported();
- method public boolean isMultipleAdvertisementSupported();
- method public boolean isOffloadedFilteringSupported();
- method public boolean isOffloadedScanBatchingSupported();
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setName(String);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startDiscovery();
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public static final String ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
- field public static final String ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
- field public static final int ERROR = -2147483648; // 0x80000000
- field public static final String EXTRA_CONNECTION_STATE = "android.bluetooth.adapter.extra.CONNECTION_STATE";
- field public static final String EXTRA_DISCOVERABLE_DURATION = "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
- field public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
- field public static final String EXTRA_PREVIOUS_CONNECTION_STATE = "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
- field public static final String EXTRA_PREVIOUS_SCAN_MODE = "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
- field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.adapter.extra.PREVIOUS_STATE";
- field public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
- field public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
- field public static final int SCAN_MODE_CONNECTABLE = 21; // 0x15
- field public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; // 0x17
- field public static final int SCAN_MODE_NONE = 20; // 0x14
- field public static final int STATE_CONNECTED = 2; // 0x2
- field public static final int STATE_CONNECTING = 1; // 0x1
- field public static final int STATE_DISCONNECTED = 0; // 0x0
- field public static final int STATE_DISCONNECTING = 3; // 0x3
- field public static final int STATE_OFF = 10; // 0xa
- field public static final int STATE_ON = 12; // 0xc
- field public static final int STATE_TURNING_OFF = 13; // 0xd
- field public static final int STATE_TURNING_ON = 11; // 0xb
- }
-
- public static interface BluetoothAdapter.LeScanCallback {
- method public void onLeScan(android.bluetooth.BluetoothDevice, int, byte[]);
- }
-
- public class BluetoothAssignedNumbers {
- field public static final int AAMP_OF_AMERICA = 190; // 0xbe
- field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a
- field public static final int ACE_SENSOR = 188; // 0xbc
- field public static final int ADIDAS = 195; // 0xc3
- field public static final int ADVANCED_PANMOBIL_SYSTEMS = 145; // 0x91
- field public static final int AIROHA_TECHNOLOGY = 148; // 0x94
- field public static final int ALCATEL = 36; // 0x24
- field public static final int ALPWISE = 154; // 0x9a
- field public static final int AMICCOM_ELECTRONICS = 192; // 0xc0
- field public static final int APLIX = 189; // 0xbd
- field public static final int APPLE = 76; // 0x4c
- field public static final int APT_LICENSING = 79; // 0x4f
- field public static final int ARCHOS = 207; // 0xcf
- field public static final int ARP_DEVICES = 168; // 0xa8
- field public static final int ATHEROS_COMMUNICATIONS = 69; // 0x45
- field public static final int ATMEL = 19; // 0x13
- field public static final int AUSTCO_COMMUNICATION_SYSTEMS = 213; // 0xd5
- field public static final int AUTONET_MOBILE = 127; // 0x7f
- field public static final int AVAGO = 78; // 0x4e
- field public static final int AVM_BERLIN = 31; // 0x1f
- field public static final int A_AND_D_ENGINEERING = 105; // 0x69
- field public static final int A_AND_R_CAMBRIDGE = 124; // 0x7c
- field public static final int BANDSPEED = 32; // 0x20
- field public static final int BAND_XI_INTERNATIONAL = 100; // 0x64
- field public static final int BDE_TECHNOLOGY = 180; // 0xb4
- field public static final int BEATS_ELECTRONICS = 204; // 0xcc
- field public static final int BEAUTIFUL_ENTERPRISE = 108; // 0x6c
- field public static final int BEKEY = 178; // 0xb2
- field public static final int BELKIN_INTERNATIONAL = 92; // 0x5c
- field public static final int BINAURIC = 203; // 0xcb
- field public static final int BIOSENTRONICS = 219; // 0xdb
- field public static final int BLUEGIGA = 71; // 0x47
- field public static final int BLUERADIOS = 133; // 0x85
- field public static final int BLUETOOTH_SIG = 63; // 0x3f
- field public static final int BLUETREK_TECHNOLOGIES = 151; // 0x97
- field public static final int BOSE = 158; // 0x9e
- field public static final int BRIARTEK = 109; // 0x6d
- field public static final int BROADCOM = 15; // 0xf
- field public static final int CAEN_RFID = 170; // 0xaa
- field public static final int CAMBRIDGE_SILICON_RADIO = 10; // 0xa
- field public static final int CATC = 52; // 0x34
- field public static final int CINETIX = 175; // 0xaf
- field public static final int CLARINOX_TECHNOLOGIES = 179; // 0xb3
- field public static final int COLORFY = 156; // 0x9c
- field public static final int COMMIL = 51; // 0x33
- field public static final int CONEXANT_SYSTEMS = 28; // 0x1c
- field public static final int CONNECTBLUE = 113; // 0x71
- field public static final int CONTINENTAL_AUTOMOTIVE = 75; // 0x4b
- field public static final int CONWISE_TECHNOLOGY = 66; // 0x42
- field public static final int CREATIVE_TECHNOLOGY = 118; // 0x76
- field public static final int C_TECHNOLOGIES = 38; // 0x26
- field public static final int DANLERS = 225; // 0xe1
- field public static final int DELORME_PUBLISHING_COMPANY = 128; // 0x80
- field public static final int DEXCOM = 208; // 0xd0
- field public static final int DIALOG_SEMICONDUCTOR = 210; // 0xd2
- field public static final int DIGIANSWER = 12; // 0xc
- field public static final int ECLIPSE = 53; // 0x35
- field public static final int ECOTEST = 136; // 0x88
- field public static final int ELGATO_SYSTEMS = 206; // 0xce
- field public static final int EM_MICROELECTRONIC_MARIN = 90; // 0x5a
- field public static final int EQUINOX_AG = 134; // 0x86
- field public static final int ERICSSON_TECHNOLOGY = 0; // 0x0
- field public static final int EVLUMA = 201; // 0xc9
- field public static final int FREE2MOVE = 83; // 0x53
- field public static final int FUNAI_ELECTRIC = 144; // 0x90
- field public static final int GARMIN_INTERNATIONAL = 135; // 0x87
- field public static final int GCT_SEMICONDUCTOR = 45; // 0x2d
- field public static final int GELO = 200; // 0xc8
- field public static final int GENEQ = 194; // 0xc2
- field public static final int GENERAL_MOTORS = 104; // 0x68
- field public static final int GENNUM = 59; // 0x3b
- field public static final int GEOFORCE = 157; // 0x9d
- field public static final int GIBSON_GUITARS = 98; // 0x62
- field public static final int GN_NETCOM = 103; // 0x67
- field public static final int GN_RESOUND = 137; // 0x89
- field public static final int GOOGLE = 224; // 0xe0
- field public static final int GREEN_THROTTLE_GAMES = 172; // 0xac
- field public static final int GROUP_SENSE = 115; // 0x73
- field public static final int HANLYNN_TECHNOLOGIES = 123; // 0x7b
- field public static final int HARMAN_INTERNATIONAL = 87; // 0x57
- field public static final int HEWLETT_PACKARD = 101; // 0x65
- field public static final int HITACHI = 41; // 0x29
- field public static final int HOSIDEN = 221; // 0xdd
- field public static final int IBM = 3; // 0x3
- field public static final int INFINEON_TECHNOLOGIES = 9; // 0x9
- field public static final int INGENIEUR_SYSTEMGRUPPE_ZAHN = 171; // 0xab
- field public static final int INTEGRATED_SILICON_SOLUTION = 65; // 0x41
- field public static final int INTEGRATED_SYSTEM_SOLUTION = 57; // 0x39
- field public static final int INTEL = 2; // 0x2
- field public static final int INVENTEL = 30; // 0x1e
- field public static final int IPEXTREME = 61; // 0x3d
- field public static final int I_TECH_DYNAMIC_GLOBAL_DISTRIBUTION = 153; // 0x99
- field public static final int JAWBONE = 138; // 0x8a
- field public static final int JIANGSU_TOPPOWER_AUTOMOTIVE_ELECTRONICS = 155; // 0x9b
- field public static final int JOHNSON_CONTROLS = 185; // 0xb9
- field public static final int J_AND_M = 82; // 0x52
- field public static final int KAWANTECH = 212; // 0xd4
- field public static final int KC_TECHNOLOGY = 22; // 0x16
- field public static final int KENSINGTON_COMPUTER_PRODUCTS_GROUP = 160; // 0xa0
- field public static final int LAIRD_TECHNOLOGIES = 119; // 0x77
- field public static final int LESSWIRE = 121; // 0x79
- field public static final int LG_ELECTRONICS = 196; // 0xc4
- field public static final int LINAK = 164; // 0xa4
- field public static final int LUCENT = 7; // 0x7
- field public static final int LUDUS_HELSINKI = 132; // 0x84
- field public static final int MACRONIX = 44; // 0x2c
- field public static final int MAGNETI_MARELLI = 169; // 0xa9
- field public static final int MANSELLA = 33; // 0x21
- field public static final int MARVELL = 72; // 0x48
- field public static final int MATSUSHITA_ELECTRIC = 58; // 0x3a
- field public static final int MC10 = 202; // 0xca
- field public static final int MEDIATEK = 70; // 0x46
- field public static final int MESO_INTERNATIONAL = 182; // 0xb6
- field public static final int META_WATCH = 163; // 0xa3
- field public static final int MEWTEL_TECHNOLOGY = 47; // 0x2f
- field public static final int MICOMMAND = 99; // 0x63
- field public static final int MICROCHIP_TECHNOLOGY = 205; // 0xcd
- field public static final int MICROSOFT = 6; // 0x6
- field public static final int MINDTREE = 106; // 0x6a
- field public static final int MISFIT_WEARABLES = 223; // 0xdf
- field public static final int MITEL_SEMICONDUCTOR = 16; // 0x10
- field public static final int MITSUBISHI_ELECTRIC = 20; // 0x14
- field public static final int MOBILIAN_CORPORATION = 55; // 0x37
- field public static final int MONSTER = 112; // 0x70
- field public static final int MOTOROLA = 8; // 0x8
- field public static final int MSTAR_SEMICONDUCTOR = 122; // 0x7a
- field public static final int MUZIK = 222; // 0xde
- field public static final int NEC = 34; // 0x22
- field public static final int NEC_LIGHTING = 149; // 0x95
- field public static final int NEWLOGIC = 23; // 0x17
- field public static final int NIKE = 120; // 0x78
- field public static final int NINE_SOLUTIONS = 102; // 0x66
- field public static final int NOKIA_MOBILE_PHONES = 1; // 0x1
- field public static final int NORDIC_SEMICONDUCTOR = 89; // 0x59
- field public static final int NORWOOD_SYSTEMS = 46; // 0x2e
- field public static final int ODM_TECHNOLOGY = 150; // 0x96
- field public static final int OMEGAWAVE = 174; // 0xae
- field public static final int ONSET_COMPUTER = 197; // 0xc5
- field public static final int OPEN_INTERFACE = 39; // 0x27
- field public static final int OTL_DYNAMICS = 165; // 0xa5
- field public static final int PANDA_OCEAN = 166; // 0xa6
- field public static final int PARROT = 67; // 0x43
- field public static final int PARTHUS_TECHNOLOGIES = 14; // 0xe
- field public static final int PASSIF_SEMICONDUCTOR = 176; // 0xb0
- field public static final int PETER_SYSTEMTECHNIK = 173; // 0xad
- field public static final int PHILIPS_SEMICONDUCTORS = 37; // 0x25
- field public static final int PLANTRONICS = 85; // 0x55
- field public static final int POLAR_ELECTRO = 107; // 0x6b
- field public static final int POLAR_ELECTRO_EUROPE = 209; // 0xd1
- field public static final int PROCTER_AND_GAMBLE = 220; // 0xdc
- field public static final int QUALCOMM = 29; // 0x1d
- field public static final int QUALCOMM_CONNECTED_EXPERIENCES = 216; // 0xd8
- field public static final int QUALCOMM_INNOVATION_CENTER = 184; // 0xb8
- field public static final int QUALCOMM_LABS = 140; // 0x8c
- field public static final int QUALCOMM_TECHNOLOGIES = 215; // 0xd7
- field public static final int QUINTIC = 142; // 0x8e
- field public static final int QUUPPA = 199; // 0xc7
- field public static final int RALINK_TECHNOLOGY = 91; // 0x5b
- field public static final int RDA_MICROELECTRONICS = 97; // 0x61
- field public static final int REALTEK_SEMICONDUCTOR = 93; // 0x5d
- field public static final int RED_M = 50; // 0x32
- field public static final int RENESAS_TECHNOLOGY = 54; // 0x36
- field public static final int RESEARCH_IN_MOTION = 60; // 0x3c
- field public static final int RF_MICRO_DEVICES = 40; // 0x28
- field public static final int RIVIERAWAVES = 96; // 0x60
- field public static final int ROHDE_AND_SCHWARZ = 25; // 0x19
- field public static final int RTX_TELECOM = 21; // 0x15
- field public static final int SAMSUNG_ELECTRONICS = 117; // 0x75
- field public static final int SARIS_CYCLING_GROUP = 177; // 0xb1
- field public static final int SEERS_TECHNOLOGY = 125; // 0x7d
- field public static final int SEIKO_EPSON = 64; // 0x40
- field public static final int SELFLY = 198; // 0xc6
- field public static final int SEMILINK = 226; // 0xe2
- field public static final int SENNHEISER_COMMUNICATIONS = 130; // 0x82
- field public static final int SHANGHAI_SUPER_SMART_ELECTRONICS = 114; // 0x72
- field public static final int SHENZHEN_EXCELSECU_DATA_TECHNOLOGY = 193; // 0xc1
- field public static final int SIGNIA_TECHNOLOGIES = 27; // 0x1b
- field public static final int SILICON_WAVE = 11; // 0xb
- field public static final int SIRF_TECHNOLOGY = 80; // 0x50
- field public static final int SOCKET_MOBILE = 68; // 0x44
- field public static final int SONY_ERICSSON = 86; // 0x56
- field public static final int SOUND_ID = 111; // 0x6f
- field public static final int SPORTS_TRACKING_TECHNOLOGIES = 126; // 0x7e
- field public static final int SR_MEDIZINELEKTRONIK = 161; // 0xa1
- field public static final int STACCATO_COMMUNICATIONS = 77; // 0x4d
- field public static final int STALMART_TECHNOLOGY = 191; // 0xbf
- field public static final int STARKEY_LABORATORIES = 186; // 0xba
- field public static final int STOLLMAN_E_PLUS_V = 143; // 0x8f
- field public static final int STONESTREET_ONE = 94; // 0x5e
- field public static final int ST_MICROELECTRONICS = 48; // 0x30
- field public static final int SUMMIT_DATA_COMMUNICATIONS = 110; // 0x6e
- field public static final int SUUNTO = 159; // 0x9f
- field public static final int SWIRL_NETWORKS = 181; // 0xb5
- field public static final int SYMBOL_TECHNOLOGIES = 42; // 0x2a
- field public static final int SYNOPSYS = 49; // 0x31
- field public static final int SYSTEMS_AND_CHIPS = 62; // 0x3e
- field public static final int S_POWER_ELECTRONICS = 187; // 0xbb
- field public static final int TAIXINGBANG_TECHNOLOGY = 211; // 0xd3
- field public static final int TENOVIS = 43; // 0x2b
- field public static final int TERAX = 56; // 0x38
- field public static final int TEXAS_INSTRUMENTS = 13; // 0xd
- field public static final int THINKOPTICS = 146; // 0x92
- field public static final int THREECOM = 5; // 0x5
- field public static final int THREE_DIJOY = 84; // 0x54
- field public static final int THREE_DSP = 73; // 0x49
- field public static final int TIMEKEEPING_SYSTEMS = 131; // 0x83
- field public static final int TIMEX_GROUP_USA = 214; // 0xd6
- field public static final int TOPCORN_POSITIONING_SYSTEMS = 139; // 0x8b
- field public static final int TOSHIBA = 4; // 0x4
- field public static final int TRANSILICA = 24; // 0x18
- field public static final int TRELAB = 183; // 0xb7
- field public static final int TTPCOM = 26; // 0x1a
- field public static final int TXTR = 218; // 0xda
- field public static final int TZERO_TECHNOLOGIES = 81; // 0x51
- field public static final int UNIVERSAL_ELECTRONICS = 147; // 0x93
- field public static final int VERTU = 162; // 0xa2
- field public static final int VISTEON = 167; // 0xa7
- field public static final int VIZIO = 88; // 0x58
- field public static final int VOYETRA_TURTLE_BEACH = 217; // 0xd9
- field public static final int WAVEPLUS_TECHNOLOGY = 35; // 0x23
- field public static final int WICENTRIC = 95; // 0x5f
- field public static final int WIDCOMM = 17; // 0x11
- field public static final int WUXI_VIMICRO = 129; // 0x81
- field public static final int ZEEVO = 18; // 0x12
- field public static final int ZER01_TV = 152; // 0x98
- field public static final int ZOMM = 116; // 0x74
- field public static final int ZSCAN_SOFTWARE = 141; // 0x8d
- }
-
- public final class BluetoothClass implements android.os.Parcelable {
- method public int describeContents();
- method public int getDeviceClass();
- method public int getMajorDeviceClass();
- method public boolean hasService(int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothClass> CREATOR;
- }
-
- public static class BluetoothClass.Device {
- ctor public BluetoothClass.Device();
- field public static final int AUDIO_VIDEO_CAMCORDER = 1076; // 0x434
- field public static final int AUDIO_VIDEO_CAR_AUDIO = 1056; // 0x420
- field public static final int AUDIO_VIDEO_HANDSFREE = 1032; // 0x408
- field public static final int AUDIO_VIDEO_HEADPHONES = 1048; // 0x418
- field public static final int AUDIO_VIDEO_HIFI_AUDIO = 1064; // 0x428
- field public static final int AUDIO_VIDEO_LOUDSPEAKER = 1044; // 0x414
- field public static final int AUDIO_VIDEO_MICROPHONE = 1040; // 0x410
- field public static final int AUDIO_VIDEO_PORTABLE_AUDIO = 1052; // 0x41c
- field public static final int AUDIO_VIDEO_SET_TOP_BOX = 1060; // 0x424
- field public static final int AUDIO_VIDEO_UNCATEGORIZED = 1024; // 0x400
- field public static final int AUDIO_VIDEO_VCR = 1068; // 0x42c
- field public static final int AUDIO_VIDEO_VIDEO_CAMERA = 1072; // 0x430
- field public static final int AUDIO_VIDEO_VIDEO_CONFERENCING = 1088; // 0x440
- field public static final int AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER = 1084; // 0x43c
- field public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 1096; // 0x448
- field public static final int AUDIO_VIDEO_VIDEO_MONITOR = 1080; // 0x438
- field public static final int AUDIO_VIDEO_WEARABLE_HEADSET = 1028; // 0x404
- field public static final int COMPUTER_DESKTOP = 260; // 0x104
- field public static final int COMPUTER_HANDHELD_PC_PDA = 272; // 0x110
- field public static final int COMPUTER_LAPTOP = 268; // 0x10c
- field public static final int COMPUTER_PALM_SIZE_PC_PDA = 276; // 0x114
- field public static final int COMPUTER_SERVER = 264; // 0x108
- field public static final int COMPUTER_UNCATEGORIZED = 256; // 0x100
- field public static final int COMPUTER_WEARABLE = 280; // 0x118
- field public static final int HEALTH_BLOOD_PRESSURE = 2308; // 0x904
- field public static final int HEALTH_DATA_DISPLAY = 2332; // 0x91c
- field public static final int HEALTH_GLUCOSE = 2320; // 0x910
- field public static final int HEALTH_PULSE_OXIMETER = 2324; // 0x914
- field public static final int HEALTH_PULSE_RATE = 2328; // 0x918
- field public static final int HEALTH_THERMOMETER = 2312; // 0x908
- field public static final int HEALTH_UNCATEGORIZED = 2304; // 0x900
- field public static final int HEALTH_WEIGHING = 2316; // 0x90c
- field public static final int PHONE_CELLULAR = 516; // 0x204
- field public static final int PHONE_CORDLESS = 520; // 0x208
- field public static final int PHONE_ISDN = 532; // 0x214
- field public static final int PHONE_MODEM_OR_GATEWAY = 528; // 0x210
- field public static final int PHONE_SMART = 524; // 0x20c
- field public static final int PHONE_UNCATEGORIZED = 512; // 0x200
- field public static final int TOY_CONTROLLER = 2064; // 0x810
- field public static final int TOY_DOLL_ACTION_FIGURE = 2060; // 0x80c
- field public static final int TOY_GAME = 2068; // 0x814
- field public static final int TOY_ROBOT = 2052; // 0x804
- field public static final int TOY_UNCATEGORIZED = 2048; // 0x800
- field public static final int TOY_VEHICLE = 2056; // 0x808
- field public static final int WEARABLE_GLASSES = 1812; // 0x714
- field public static final int WEARABLE_HELMET = 1808; // 0x710
- field public static final int WEARABLE_JACKET = 1804; // 0x70c
- field public static final int WEARABLE_PAGER = 1800; // 0x708
- field public static final int WEARABLE_UNCATEGORIZED = 1792; // 0x700
- field public static final int WEARABLE_WRIST_WATCH = 1796; // 0x704
- }
-
- public static class BluetoothClass.Device.Major {
- ctor public BluetoothClass.Device.Major();
- field public static final int AUDIO_VIDEO = 1024; // 0x400
- field public static final int COMPUTER = 256; // 0x100
- field public static final int HEALTH = 2304; // 0x900
- field public static final int IMAGING = 1536; // 0x600
- field public static final int MISC = 0; // 0x0
- field public static final int NETWORKING = 768; // 0x300
- field public static final int PERIPHERAL = 1280; // 0x500
- field public static final int PHONE = 512; // 0x200
- field public static final int TOY = 2048; // 0x800
- field public static final int UNCATEGORIZED = 7936; // 0x1f00
- field public static final int WEARABLE = 1792; // 0x700
- }
-
- public static final class BluetoothClass.Service {
- ctor public BluetoothClass.Service();
- field public static final int AUDIO = 2097152; // 0x200000
- field public static final int CAPTURE = 524288; // 0x80000
- field public static final int INFORMATION = 8388608; // 0x800000
- field public static final int LE_AUDIO = 16384; // 0x4000
- field public static final int LIMITED_DISCOVERABILITY = 8192; // 0x2000
- field public static final int NETWORKING = 131072; // 0x20000
- field public static final int OBJECT_TRANSFER = 1048576; // 0x100000
- field public static final int POSITIONING = 65536; // 0x10000
- field public static final int RENDER = 262144; // 0x40000
- field public static final int TELEPHONY = 4194304; // 0x400000
- }
-
- public final class BluetoothCodecConfig implements android.os.Parcelable {
- ctor public BluetoothCodecConfig(int);
- method public int describeContents();
- method public int getBitsPerSample();
- method public int getChannelMode();
- method public int getCodecPriority();
- method public long getCodecSpecific1();
- method public long getCodecSpecific2();
- method public long getCodecSpecific3();
- method public long getCodecSpecific4();
- method public int getCodecType();
- method public static int getMaxCodecType();
- method public int getSampleRate();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int BITS_PER_SAMPLE_16 = 1; // 0x1
- field public static final int BITS_PER_SAMPLE_24 = 2; // 0x2
- field public static final int BITS_PER_SAMPLE_32 = 4; // 0x4
- field public static final int BITS_PER_SAMPLE_NONE = 0; // 0x0
- field public static final int CHANNEL_MODE_MONO = 1; // 0x1
- field public static final int CHANNEL_MODE_NONE = 0; // 0x0
- field public static final int CHANNEL_MODE_STEREO = 2; // 0x2
- field public static final int CODEC_PRIORITY_DEFAULT = 0; // 0x0
- field public static final int CODEC_PRIORITY_DISABLED = -1; // 0xffffffff
- field public static final int CODEC_PRIORITY_HIGHEST = 1000000; // 0xf4240
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecConfig> CREATOR;
- field public static final int SAMPLE_RATE_176400 = 16; // 0x10
- field public static final int SAMPLE_RATE_192000 = 32; // 0x20
- field public static final int SAMPLE_RATE_44100 = 1; // 0x1
- field public static final int SAMPLE_RATE_48000 = 2; // 0x2
- field public static final int SAMPLE_RATE_88200 = 4; // 0x4
- field public static final int SAMPLE_RATE_96000 = 8; // 0x8
- field public static final int SAMPLE_RATE_NONE = 0; // 0x0
- field public static final int SOURCE_CODEC_TYPE_AAC = 1; // 0x1
- field public static final int SOURCE_CODEC_TYPE_APTX = 2; // 0x2
- field public static final int SOURCE_CODEC_TYPE_APTX_HD = 3; // 0x3
- field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
- field public static final int SOURCE_CODEC_TYPE_LDAC = 4; // 0x4
- field public static final int SOURCE_CODEC_TYPE_SBC = 0; // 0x0
- }
-
- public static final class BluetoothCodecConfig.Builder {
- ctor public BluetoothCodecConfig.Builder();
- method @NonNull public android.bluetooth.BluetoothCodecConfig build();
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setBitsPerSample(int);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setChannelMode(int);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecPriority(int);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific1(long);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific2(long);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific3(long);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecSpecific4(long);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setCodecType(int);
- method @NonNull public android.bluetooth.BluetoothCodecConfig.Builder setSampleRate(int);
- }
-
- public final class BluetoothCodecStatus implements android.os.Parcelable {
- ctor public BluetoothCodecStatus(@Nullable android.bluetooth.BluetoothCodecConfig, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>, @Nullable java.util.List<android.bluetooth.BluetoothCodecConfig>);
- method public int describeContents();
- method @Nullable public android.bluetooth.BluetoothCodecConfig getCodecConfig();
- method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsLocalCapabilities();
- method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getCodecsSelectableCapabilities();
- method public boolean isCodecConfigSelectable(@Nullable android.bluetooth.BluetoothCodecConfig);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothCodecStatus> CREATOR;
- field public static final String EXTRA_CODEC_STATUS = "android.bluetooth.extra.CODEC_STATUS";
- }
-
- public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
- method public void close();
- method protected void finalize();
- method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(@Nullable android.bluetooth.BluetoothDevice);
- method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CSIS_CONNECTION_STATE_CHANGED = "android.bluetooth.action.CSIS_CONNECTION_STATE_CHANGED";
- }
-
- public final class BluetoothDevice implements android.os.Parcelable {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond();
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
- method public int describeContents();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean fetchUuidsWithSdp();
- method public String getAddress();
- method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getAlias();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothClass getBluetoothClass();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getBondState();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getType();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelUuid[] getUuids();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int setAlias(@Nullable String);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPairingConfirmation(boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setPin(byte[]);
- method public void writeToParcel(android.os.Parcel, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECTED = "android.bluetooth.device.action.ACL_DISCONNECTED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_ALIAS_CHANGED = "android.bluetooth.device.action.ALIAS_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_PAIRING_REQUEST = "android.bluetooth.device.action.PAIRING_REQUEST";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_UUID = "android.bluetooth.device.action.UUID";
- field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
- field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
- field public static final int BOND_BONDED = 12; // 0xc
- field public static final int BOND_BONDING = 11; // 0xb
- field public static final int BOND_NONE = 10; // 0xa
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothDevice> CREATOR;
- field public static final int DEVICE_TYPE_CLASSIC = 1; // 0x1
- field public static final int DEVICE_TYPE_DUAL = 3; // 0x3
- field public static final int DEVICE_TYPE_LE = 2; // 0x2
- field public static final int DEVICE_TYPE_UNKNOWN = 0; // 0x0
- field public static final int ERROR = -2147483648; // 0x80000000
- field public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
- field public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
- field public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
- field public static final String EXTRA_IS_COORDINATED_SET_MEMBER = "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER";
- field public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
- field public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
- field public static final String EXTRA_PAIRING_VARIANT = "android.bluetooth.device.extra.PAIRING_VARIANT";
- field public static final String EXTRA_PREVIOUS_BOND_STATE = "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
- field public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
- field public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
- field public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; // 0x2
- field public static final int PAIRING_VARIANT_PIN = 0; // 0x0
- field public static final int PHY_LE_1M = 1; // 0x1
- field public static final int PHY_LE_1M_MASK = 1; // 0x1
- field public static final int PHY_LE_2M = 2; // 0x2
- field public static final int PHY_LE_2M_MASK = 2; // 0x2
- field public static final int PHY_LE_CODED = 3; // 0x3
- field public static final int PHY_LE_CODED_MASK = 4; // 0x4
- field public static final int PHY_OPTION_NO_PREFERRED = 0; // 0x0
- field public static final int PHY_OPTION_S2 = 1; // 0x1
- field public static final int PHY_OPTION_S8 = 2; // 0x2
- field public static final int TRANSPORT_AUTO = 0; // 0x0
- field public static final int TRANSPORT_BREDR = 1; // 0x1
- field public static final int TRANSPORT_LE = 2; // 0x2
- }
-
- public final class BluetoothGatt implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite();
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void abortReliableWrite(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean beginReliableWrite();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void disconnect();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean discoverServices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean executeReliableWrite();
- method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @Deprecated public int getConnectionState(android.bluetooth.BluetoothDevice);
- method public android.bluetooth.BluetoothDevice getDevice();
- method @Deprecated public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
- method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean readRemoteRssi();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestConnectionPriority(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean requestMtu(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(int, int, int);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeCharacteristic(@NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int writeDescriptor(@NonNull android.bluetooth.BluetoothGattDescriptor, @NonNull byte[]);
- field public static final int CONNECTION_PRIORITY_BALANCED = 0; // 0x0
- field public static final int CONNECTION_PRIORITY_HIGH = 1; // 0x1
- field public static final int CONNECTION_PRIORITY_LOW_POWER = 2; // 0x2
- field public static final int GATT_CONNECTION_CONGESTED = 143; // 0x8f
- field public static final int GATT_FAILURE = 257; // 0x101
- field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
- field public static final int GATT_INSUFFICIENT_AUTHORIZATION = 8; // 0x8
- field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
- field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd
- field public static final int GATT_INVALID_OFFSET = 7; // 0x7
- field public static final int GATT_READ_NOT_PERMITTED = 2; // 0x2
- field public static final int GATT_REQUEST_NOT_SUPPORTED = 6; // 0x6
- field public static final int GATT_SUCCESS = 0; // 0x0
- field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
- }
-
- public abstract class BluetoothGattCallback {
- ctor public BluetoothGattCallback();
- method @Deprecated public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
- method public void onCharacteristicChanged(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[]);
- method @Deprecated public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
- method public void onCharacteristicRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattCharacteristic, @NonNull byte[], int);
- method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
- method public void onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int);
- method @Deprecated public void onDescriptorRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
- method public void onDescriptorRead(@NonNull android.bluetooth.BluetoothGatt, @NonNull android.bluetooth.BluetoothGattDescriptor, int, @NonNull byte[]);
- method public void onDescriptorWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattDescriptor, int);
- method public void onMtuChanged(android.bluetooth.BluetoothGatt, int, int);
- method public void onPhyRead(android.bluetooth.BluetoothGatt, int, int, int);
- method public void onPhyUpdate(android.bluetooth.BluetoothGatt, int, int, int);
- method public void onReadRemoteRssi(android.bluetooth.BluetoothGatt, int, int);
- method public void onReliableWriteCompleted(android.bluetooth.BluetoothGatt, int);
- method public void onServiceChanged(@NonNull android.bluetooth.BluetoothGatt);
- method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
- }
-
- public class BluetoothGattCharacteristic implements android.os.Parcelable {
- ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
- method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
- method public int describeContents();
- method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
- method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
- method @Deprecated public Float getFloatValue(int, int);
- method public int getInstanceId();
- method @Deprecated public Integer getIntValue(int, int);
- method public int getPermissions();
- method public int getProperties();
- method public android.bluetooth.BluetoothGattService getService();
- method @Deprecated public String getStringValue(int);
- method public java.util.UUID getUuid();
- method @Deprecated public byte[] getValue();
- method public int getWriteType();
- method @Deprecated public boolean setValue(byte[]);
- method @Deprecated public boolean setValue(int, int, int);
- method @Deprecated public boolean setValue(int, int, int, int);
- method @Deprecated public boolean setValue(String);
- method public void setWriteType(int);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
- field public static final int FORMAT_FLOAT = 52; // 0x34
- field public static final int FORMAT_SFLOAT = 50; // 0x32
- field public static final int FORMAT_SINT16 = 34; // 0x22
- field public static final int FORMAT_SINT32 = 36; // 0x24
- field public static final int FORMAT_SINT8 = 33; // 0x21
- field public static final int FORMAT_UINT16 = 18; // 0x12
- field public static final int FORMAT_UINT32 = 20; // 0x14
- field public static final int FORMAT_UINT8 = 17; // 0x11
- field public static final int PERMISSION_READ = 1; // 0x1
- field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
- field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
- field public static final int PERMISSION_WRITE = 16; // 0x10
- field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
- field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
- field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
- field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
- field public static final int PROPERTY_BROADCAST = 1; // 0x1
- field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
- field public static final int PROPERTY_INDICATE = 32; // 0x20
- field public static final int PROPERTY_NOTIFY = 16; // 0x10
- field public static final int PROPERTY_READ = 2; // 0x2
- field public static final int PROPERTY_SIGNED_WRITE = 64; // 0x40
- field public static final int PROPERTY_WRITE = 8; // 0x8
- field public static final int PROPERTY_WRITE_NO_RESPONSE = 4; // 0x4
- field public static final int WRITE_TYPE_DEFAULT = 2; // 0x2
- field public static final int WRITE_TYPE_NO_RESPONSE = 1; // 0x1
- field public static final int WRITE_TYPE_SIGNED = 4; // 0x4
- field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors;
- }
-
- public class BluetoothGattDescriptor implements android.os.Parcelable {
- ctor public BluetoothGattDescriptor(java.util.UUID, int);
- method public int describeContents();
- method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
- method public int getPermissions();
- method public java.util.UUID getUuid();
- method @Deprecated public byte[] getValue();
- method @Deprecated public boolean setValue(byte[]);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
- field public static final byte[] DISABLE_NOTIFICATION_VALUE;
- field public static final byte[] ENABLE_INDICATION_VALUE;
- field public static final byte[] ENABLE_NOTIFICATION_VALUE;
- field public static final int PERMISSION_READ = 1; // 0x1
- field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
- field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
- field public static final int PERMISSION_WRITE = 16; // 0x10
- field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
- field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
- field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
- field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
- }
-
- public final class BluetoothGattServer implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean addService(android.bluetooth.BluetoothGattService);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void cancelConnection(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void clearServices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void close();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice, boolean);
- method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(android.bluetooth.BluetoothDevice);
- method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
- method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
- }
-
- public abstract class BluetoothGattServerCallback {
- ctor public BluetoothGattServerCallback();
- method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
- method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
- method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
- method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor);
- method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]);
- method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
- method public void onMtuChanged(android.bluetooth.BluetoothDevice, int);
- method public void onNotificationSent(android.bluetooth.BluetoothDevice, int);
- method public void onPhyRead(android.bluetooth.BluetoothDevice, int, int, int);
- method public void onPhyUpdate(android.bluetooth.BluetoothDevice, int, int, int);
- method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
- }
-
- public class BluetoothGattService implements android.os.Parcelable {
- ctor public BluetoothGattService(java.util.UUID, int);
- method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
- method public boolean addService(android.bluetooth.BluetoothGattService);
- method public int describeContents();
- method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
- method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
- method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
- method public int getInstanceId();
- method public int getType();
- method public java.util.UUID getUuid();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR;
- field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
- field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
- field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics;
- field protected java.util.List<android.bluetooth.BluetoothGattService> mIncludedServices;
- }
-
- public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isAudioConnected(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isNoiseReductionSupported(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isVoiceRecognitionSupported(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendVendorSpecificResultCode(android.bluetooth.BluetoothDevice, String, String);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startVoiceRecognition(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean stopVoiceRecognition(android.bluetooth.BluetoothDevice);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_AUDIO_STATE_CHANGED = "android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT = "android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
- field public static final int AT_CMD_TYPE_ACTION = 4; // 0x4
- field public static final int AT_CMD_TYPE_BASIC = 3; // 0x3
- field public static final int AT_CMD_TYPE_READ = 0; // 0x0
- field public static final int AT_CMD_TYPE_SET = 2; // 0x2
- field public static final int AT_CMD_TYPE_TEST = 1; // 0x1
- field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_ARGS";
- field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD";
- field public static final String EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = "android.bluetooth.headset.extra.VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE";
- field public static final int STATE_AUDIO_CONNECTED = 12; // 0xc
- field public static final int STATE_AUDIO_CONNECTING = 11; // 0xb
- field public static final int STATE_AUDIO_DISCONNECTED = 10; // 0xa
- field public static final String VENDOR_RESULT_CODE_COMMAND_ANDROID = "+ANDROID";
- field public static final String VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY = "android.bluetooth.headset.intent.category.companyid";
- }
-
- @Deprecated public final class BluetoothHealth implements android.bluetooth.BluetoothProfile {
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connectChannelToSource(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnectChannel(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration, int);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.os.ParcelFileDescriptor getMainChannelFd(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothHealthAppConfiguration);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerSinkAppConfiguration(String, int, android.bluetooth.BluetoothHealthCallback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterAppConfiguration(android.bluetooth.BluetoothHealthAppConfiguration);
- field @Deprecated public static final int APP_CONFIG_REGISTRATION_FAILURE = 1; // 0x1
- field @Deprecated public static final int APP_CONFIG_REGISTRATION_SUCCESS = 0; // 0x0
- field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_FAILURE = 3; // 0x3
- field @Deprecated public static final int APP_CONFIG_UNREGISTRATION_SUCCESS = 2; // 0x2
- field @Deprecated public static final int CHANNEL_TYPE_RELIABLE = 10; // 0xa
- field @Deprecated public static final int CHANNEL_TYPE_STREAMING = 11; // 0xb
- field @Deprecated public static final int SINK_ROLE = 2; // 0x2
- field @Deprecated public static final int SOURCE_ROLE = 1; // 0x1
- field @Deprecated public static final int STATE_CHANNEL_CONNECTED = 2; // 0x2
- field @Deprecated public static final int STATE_CHANNEL_CONNECTING = 1; // 0x1
- field @Deprecated public static final int STATE_CHANNEL_DISCONNECTED = 0; // 0x0
- field @Deprecated public static final int STATE_CHANNEL_DISCONNECTING = 3; // 0x3
- }
-
- @Deprecated public final class BluetoothHealthAppConfiguration implements android.os.Parcelable {
- method @Deprecated public int describeContents();
- method @Deprecated public int getDataType();
- method @Deprecated public String getName();
- method @Deprecated public int getRole();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHealthAppConfiguration> CREATOR;
- }
-
- @Deprecated public abstract class BluetoothHealthCallback {
- ctor @Deprecated public BluetoothHealthCallback();
- method @Deprecated @BinderThread public void onHealthAppConfigurationStatusChange(android.bluetooth.BluetoothHealthAppConfiguration, int);
- method @Deprecated @BinderThread public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
- }
-
- public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
- }
-
- public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean connect(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean registerApp(android.bluetooth.BluetoothHidDeviceAppSdpSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, android.bluetooth.BluetoothHidDeviceAppQosSettings, java.util.concurrent.Executor, android.bluetooth.BluetoothHidDevice.Callback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean replyReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean reportError(android.bluetooth.BluetoothDevice, byte);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendReport(android.bluetooth.BluetoothDevice, int, byte[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean unregisterApp();
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hiddevice.profile.action.CONNECTION_STATE_CHANGED";
- field public static final byte ERROR_RSP_INVALID_PARAM = 4; // 0x4
- field public static final byte ERROR_RSP_INVALID_RPT_ID = 2; // 0x2
- field public static final byte ERROR_RSP_NOT_READY = 1; // 0x1
- field public static final byte ERROR_RSP_SUCCESS = 0; // 0x0
- field public static final byte ERROR_RSP_UNKNOWN = 14; // 0xe
- field public static final byte ERROR_RSP_UNSUPPORTED_REQ = 3; // 0x3
- field public static final byte PROTOCOL_BOOT_MODE = 0; // 0x0
- field public static final byte PROTOCOL_REPORT_MODE = 1; // 0x1
- field public static final byte REPORT_TYPE_FEATURE = 3; // 0x3
- field public static final byte REPORT_TYPE_INPUT = 1; // 0x1
- field public static final byte REPORT_TYPE_OUTPUT = 2; // 0x2
- field public static final byte SUBCLASS1_COMBO = -64; // 0xffffffc0
- field public static final byte SUBCLASS1_KEYBOARD = 64; // 0x40
- field public static final byte SUBCLASS1_MOUSE = -128; // 0xffffff80
- field public static final byte SUBCLASS1_NONE = 0; // 0x0
- field public static final byte SUBCLASS2_CARD_READER = 6; // 0x6
- field public static final byte SUBCLASS2_DIGITIZER_TABLET = 5; // 0x5
- field public static final byte SUBCLASS2_GAMEPAD = 2; // 0x2
- field public static final byte SUBCLASS2_JOYSTICK = 1; // 0x1
- field public static final byte SUBCLASS2_REMOTE_CONTROL = 3; // 0x3
- field public static final byte SUBCLASS2_SENSING_DEVICE = 4; // 0x4
- field public static final byte SUBCLASS2_UNCATEGORIZED = 0; // 0x0
- }
-
- public abstract static class BluetoothHidDevice.Callback {
- ctor public BluetoothHidDevice.Callback();
- method public void onAppStatusChanged(android.bluetooth.BluetoothDevice, boolean);
- method public void onConnectionStateChanged(android.bluetooth.BluetoothDevice, int);
- method public void onGetReport(android.bluetooth.BluetoothDevice, byte, byte, int);
- method public void onInterruptData(android.bluetooth.BluetoothDevice, byte, byte[]);
- method public void onSetProtocol(android.bluetooth.BluetoothDevice, byte);
- method public void onSetReport(android.bluetooth.BluetoothDevice, byte, byte, byte[]);
- method public void onVirtualCableUnplug(android.bluetooth.BluetoothDevice);
- }
-
- public final class BluetoothHidDeviceAppQosSettings implements android.os.Parcelable {
- ctor public BluetoothHidDeviceAppQosSettings(int, int, int, int, int, int);
- method public int describeContents();
- method public int getDelayVariation();
- method public int getLatency();
- method public int getPeakBandwidth();
- method public int getServiceType();
- method public int getTokenBucketSize();
- method public int getTokenRate();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppQosSettings> CREATOR;
- field public static final int MAX = -1; // 0xffffffff
- field public static final int SERVICE_BEST_EFFORT = 1; // 0x1
- field public static final int SERVICE_GUARANTEED = 2; // 0x2
- field public static final int SERVICE_NO_TRAFFIC = 0; // 0x0
- }
-
- public final class BluetoothHidDeviceAppSdpSettings implements android.os.Parcelable {
- ctor public BluetoothHidDeviceAppSdpSettings(String, String, String, byte, byte[]);
- method public int describeContents();
- method public String getDescription();
- method public byte[] getDescriptors();
- method public String getName();
- method public String getProvider();
- method public byte getSubclass();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
- }
-
- public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
- method public void close();
- method protected void finalize();
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getGroupId(@NonNull android.bluetooth.BluetoothDevice);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
- }
-
- public final class BluetoothLeAudioCodecConfig {
- method @NonNull public String getCodecName();
- method public int getCodecType();
- method public static int getMaxCodecType();
- field public static final int SOURCE_CODEC_TYPE_INVALID = 1000000; // 0xf4240
- field public static final int SOURCE_CODEC_TYPE_LC3 = 0; // 0x0
- }
-
- public static final class BluetoothLeAudioCodecConfig.Builder {
- ctor public BluetoothLeAudioCodecConfig.Builder();
- method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig build();
- method @NonNull public android.bluetooth.BluetoothLeAudioCodecConfig.Builder setCodecType(int);
- }
-
- public final class BluetoothManager {
- method public android.bluetooth.BluetoothAdapter getAdapter();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(android.bluetooth.BluetoothDevice, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int, int[]);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public android.bluetooth.BluetoothGattServer openGattServer(android.content.Context, android.bluetooth.BluetoothGattServerCallback);
- }
-
- public interface BluetoothProfile {
- method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method public int getConnectionState(android.bluetooth.BluetoothDevice);
- method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
- field public static final int A2DP = 2; // 0x2
- field public static final int CSIP_SET_COORDINATOR = 25; // 0x19
- field public static final String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE";
- field public static final String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
- field public static final int GATT = 7; // 0x7
- field public static final int GATT_SERVER = 8; // 0x8
- field public static final int HEADSET = 1; // 0x1
- field @Deprecated public static final int HEALTH = 3; // 0x3
- field public static final int HEARING_AID = 21; // 0x15
- field public static final int HID_DEVICE = 19; // 0x13
- field public static final int LE_AUDIO = 22; // 0x16
- field public static final int SAP = 10; // 0xa
- field public static final int STATE_CONNECTED = 2; // 0x2
- field public static final int STATE_CONNECTING = 1; // 0x1
- field public static final int STATE_DISCONNECTED = 0; // 0x0
- field public static final int STATE_DISCONNECTING = 3; // 0x3
- }
-
- public static interface BluetoothProfile.ServiceListener {
- method public void onServiceConnected(int, android.bluetooth.BluetoothProfile);
- method public void onServiceDisconnected(int);
- }
-
- public final class BluetoothServerSocket implements java.io.Closeable {
- method public android.bluetooth.BluetoothSocket accept() throws java.io.IOException;
- method public android.bluetooth.BluetoothSocket accept(int) throws java.io.IOException;
- method public void close() throws java.io.IOException;
- method public int getPsm();
- }
-
- public final class BluetoothSocket implements java.io.Closeable {
- method public void close() throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void connect() throws java.io.IOException;
- method public int getConnectionType();
- method public java.io.InputStream getInputStream() throws java.io.IOException;
- method public int getMaxReceivePacketSize();
- method public int getMaxTransmitPacketSize();
- method public java.io.OutputStream getOutputStream() throws java.io.IOException;
- method public android.bluetooth.BluetoothDevice getRemoteDevice();
- method public boolean isConnected();
- field public static final int TYPE_L2CAP = 3; // 0x3
- field public static final int TYPE_RFCOMM = 1; // 0x1
- field public static final int TYPE_SCO = 2; // 0x2
- }
-
- public final class BluetoothStatusCodes {
- field public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2; // 0x2
- field public static final int ERROR_BLUETOOTH_NOT_ENABLED = 1; // 0x1
- field public static final int ERROR_DEVICE_NOT_BONDED = 3; // 0x3
- field public static final int ERROR_FEATURE_NOT_SUPPORTED = 10; // 0xa
- field public static final int ERROR_GATT_WRITE_NOT_ALLOWED = 101; // 0x65
- field public static final int ERROR_GATT_WRITE_REQUEST_BUSY = 102; // 0x66
- field public static final int ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION = 6; // 0x6
- field public static final int ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION = 8; // 0x8
- field public static final int ERROR_PROFILE_SERVICE_NOT_BOUND = 9; // 0x9
- field public static final int ERROR_UNKNOWN = 2147483647; // 0x7fffffff
- field public static final int SUCCESS = 0; // 0x0
- }
-
-}
-
-package android.bluetooth.le {
-
- public abstract class AdvertiseCallback {
- ctor public AdvertiseCallback();
- method public void onStartFailure(int);
- method public void onStartSuccess(android.bluetooth.le.AdvertiseSettings);
- field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
- field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
- field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
- field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
- field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
- }
-
- public final class AdvertiseData implements android.os.Parcelable {
- method public int describeContents();
- method public boolean getIncludeDeviceName();
- method public boolean getIncludeTxPowerLevel();
- method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
- method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
- method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
- method public java.util.List<android.os.ParcelUuid> getServiceUuids();
- method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR;
- }
-
- public static final class AdvertiseData.Builder {
- ctor public AdvertiseData.Builder();
- method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]);
- method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
- method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid);
- method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
- method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData);
- method public android.bluetooth.le.AdvertiseData build();
- method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
- method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean);
- }
-
- public final class AdvertiseSettings implements android.os.Parcelable {
- method public int describeContents();
- method public int getMode();
- method public int getTimeout();
- method public int getTxPowerLevel();
- method public boolean isConnectable();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ADVERTISE_MODE_BALANCED = 1; // 0x1
- field public static final int ADVERTISE_MODE_LOW_LATENCY = 2; // 0x2
- field public static final int ADVERTISE_MODE_LOW_POWER = 0; // 0x0
- field public static final int ADVERTISE_TX_POWER_HIGH = 3; // 0x3
- field public static final int ADVERTISE_TX_POWER_LOW = 1; // 0x1
- field public static final int ADVERTISE_TX_POWER_MEDIUM = 2; // 0x2
- field public static final int ADVERTISE_TX_POWER_ULTRA_LOW = 0; // 0x0
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseSettings> CREATOR;
- }
-
- public static final class AdvertiseSettings.Builder {
- ctor public AdvertiseSettings.Builder();
- method public android.bluetooth.le.AdvertiseSettings build();
- method public android.bluetooth.le.AdvertiseSettings.Builder setAdvertiseMode(int);
- method public android.bluetooth.le.AdvertiseSettings.Builder setConnectable(boolean);
- method public android.bluetooth.le.AdvertiseSettings.Builder setTimeout(int);
- method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int);
- }
-
- public final class AdvertisingSet {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void enableAdvertising(boolean, int, int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void setScanResponseData(android.bluetooth.le.AdvertiseData);
- }
-
- public abstract class AdvertisingSetCallback {
- ctor public AdvertisingSetCallback();
- method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
- method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
- method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
- method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
- method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
- method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
- method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
- method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
- method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
- field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
- field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1
- field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5
- field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4
- field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2
- field public static final int ADVERTISE_SUCCESS = 0; // 0x0
- }
-
- public final class AdvertisingSetParameters implements android.os.Parcelable {
- method public int describeContents();
- method public int getInterval();
- method public int getPrimaryPhy();
- method public int getSecondaryPhy();
- method public int getTxPowerLevel();
- method public boolean includeTxPower();
- method public boolean isAnonymous();
- method public boolean isConnectable();
- method public boolean isLegacy();
- method public boolean isScannable();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
- field public static final int INTERVAL_HIGH = 1600; // 0x640
- field public static final int INTERVAL_LOW = 160; // 0xa0
- field public static final int INTERVAL_MAX = 16777215; // 0xffffff
- field public static final int INTERVAL_MEDIUM = 400; // 0x190
- field public static final int INTERVAL_MIN = 160; // 0xa0
- field public static final int TX_POWER_HIGH = 1; // 0x1
- field public static final int TX_POWER_LOW = -15; // 0xfffffff1
- field public static final int TX_POWER_MAX = 1; // 0x1
- field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9
- field public static final int TX_POWER_MIN = -127; // 0xffffff81
- field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb
- }
-
- public static final class AdvertisingSetParameters.Builder {
- ctor public AdvertisingSetParameters.Builder();
- method public android.bluetooth.le.AdvertisingSetParameters build();
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
- method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
- }
-
- public final class BluetoothLeAdvertiser {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
- }
-
- public final class BluetoothLeScanner {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(android.bluetooth.le.ScanCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public int startScan(@Nullable java.util.List<android.bluetooth.le.ScanFilter>, @Nullable android.bluetooth.le.ScanSettings, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.bluetooth.le.ScanCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void stopScan(android.app.PendingIntent);
- field public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
- field public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
- field public static final String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
- }
-
- public final class PeriodicAdvertisingParameters implements android.os.Parcelable {
- method public int describeContents();
- method public boolean getIncludeTxPower();
- method public int getInterval();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR;
- }
-
- public static final class PeriodicAdvertisingParameters.Builder {
- ctor public PeriodicAdvertisingParameters.Builder();
- method public android.bluetooth.le.PeriodicAdvertisingParameters build();
- method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean);
- method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int);
- }
-
- public abstract class ScanCallback {
- ctor public ScanCallback();
- method public void onBatchScanResults(java.util.List<android.bluetooth.le.ScanResult>);
- method public void onScanFailed(int);
- method public void onScanResult(int, android.bluetooth.le.ScanResult);
- field public static final int SCAN_FAILED_ALREADY_STARTED = 1; // 0x1
- field public static final int SCAN_FAILED_APPLICATION_REGISTRATION_FAILED = 2; // 0x2
- field public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; // 0x4
- field public static final int SCAN_FAILED_INTERNAL_ERROR = 3; // 0x3
- }
-
- public final class ScanFilter implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public String getDeviceAddress();
- method @Nullable public String getDeviceName();
- method @Nullable public byte[] getManufacturerData();
- method @Nullable public byte[] getManufacturerDataMask();
- method public int getManufacturerId();
- method @Nullable public byte[] getServiceData();
- method @Nullable public byte[] getServiceDataMask();
- method @Nullable public android.os.ParcelUuid getServiceDataUuid();
- method @Nullable public android.os.ParcelUuid getServiceSolicitationUuid();
- method @Nullable public android.os.ParcelUuid getServiceSolicitationUuidMask();
- method @Nullable public android.os.ParcelUuid getServiceUuid();
- method @Nullable public android.os.ParcelUuid getServiceUuidMask();
- method public boolean matches(android.bluetooth.le.ScanResult);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanFilter> CREATOR;
- }
-
- public static final class ScanFilter.Builder {
- ctor public ScanFilter.Builder();
- method public android.bluetooth.le.ScanFilter build();
- method public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(String);
- method public android.bluetooth.le.ScanFilter.Builder setDeviceName(String);
- method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[]);
- method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]);
- method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]);
- method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]);
- method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid);
- method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid, @Nullable android.os.ParcelUuid);
- method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid);
- method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
- }
-
- public final class ScanRecord {
- method public int getAdvertiseFlags();
- method public byte[] getBytes();
- method @Nullable public String getDeviceName();
- method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
- method @Nullable public byte[] getManufacturerSpecificData(int);
- method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
- method @Nullable public byte[] getServiceData(android.os.ParcelUuid);
- method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
- method public java.util.List<android.os.ParcelUuid> getServiceUuids();
- method public int getTxPowerLevel();
- }
-
- public final class ScanResult implements android.os.Parcelable {
- ctor @Deprecated public ScanResult(android.bluetooth.BluetoothDevice, android.bluetooth.le.ScanRecord, int, long);
- ctor public ScanResult(android.bluetooth.BluetoothDevice, int, int, int, int, int, int, int, android.bluetooth.le.ScanRecord, long);
- method public int describeContents();
- method public int getAdvertisingSid();
- method public int getDataStatus();
- method public android.bluetooth.BluetoothDevice getDevice();
- method public int getPeriodicAdvertisingInterval();
- method public int getPrimaryPhy();
- method public int getRssi();
- method @Nullable public android.bluetooth.le.ScanRecord getScanRecord();
- method public int getSecondaryPhy();
- method public long getTimestampNanos();
- method public int getTxPower();
- method public boolean isConnectable();
- method public boolean isLegacy();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanResult> CREATOR;
- field public static final int DATA_COMPLETE = 0; // 0x0
- field public static final int DATA_TRUNCATED = 2; // 0x2
- field public static final int PERIODIC_INTERVAL_NOT_PRESENT = 0; // 0x0
- field public static final int PHY_UNUSED = 0; // 0x0
- field public static final int SID_NOT_PRESENT = 255; // 0xff
- field public static final int TX_POWER_NOT_PRESENT = 127; // 0x7f
- }
-
- public final class ScanSettings implements android.os.Parcelable {
- method public int describeContents();
- method public int getCallbackType();
- method public boolean getLegacy();
- method public int getPhy();
- method public long getReportDelayMillis();
- method public int getScanMode();
- method public int getScanResultType();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int CALLBACK_TYPE_ALL_MATCHES = 1; // 0x1
- field public static final int CALLBACK_TYPE_FIRST_MATCH = 2; // 0x2
- field public static final int CALLBACK_TYPE_MATCH_LOST = 4; // 0x4
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ScanSettings> CREATOR;
- field public static final int MATCH_MODE_AGGRESSIVE = 1; // 0x1
- field public static final int MATCH_MODE_STICKY = 2; // 0x2
- field public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; // 0x2
- field public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; // 0x3
- field public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; // 0x1
- field public static final int PHY_LE_ALL_SUPPORTED = 255; // 0xff
- field public static final int SCAN_MODE_BALANCED = 1; // 0x1
- field public static final int SCAN_MODE_LOW_LATENCY = 2; // 0x2
- field public static final int SCAN_MODE_LOW_POWER = 0; // 0x0
- field public static final int SCAN_MODE_OPPORTUNISTIC = -1; // 0xffffffff
- }
-
- public static final class ScanSettings.Builder {
- ctor public ScanSettings.Builder();
- method public android.bluetooth.le.ScanSettings build();
- method public android.bluetooth.le.ScanSettings.Builder setCallbackType(int);
- method public android.bluetooth.le.ScanSettings.Builder setLegacy(boolean);
- method public android.bluetooth.le.ScanSettings.Builder setMatchMode(int);
- method public android.bluetooth.le.ScanSettings.Builder setNumOfMatches(int);
- method public android.bluetooth.le.ScanSettings.Builder setPhy(int);
- method public android.bluetooth.le.ScanSettings.Builder setReportDelay(long);
- method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
- }
-
- public final class TransportBlock implements android.os.Parcelable {
- ctor public TransportBlock(int, int, int, @Nullable byte[]);
- method public int describeContents();
- method public int getOrgId();
- method public int getTdsFlags();
- method @Nullable public byte[] getTransportData();
- method public int getTransportDataLength();
- method @Nullable public byte[] toByteArray();
- method public int totalBytes();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR;
- }
-
- public final class TransportDiscoveryData implements android.os.Parcelable {
- ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>);
- ctor public TransportDiscoveryData(@NonNull byte[]);
- method public int describeContents();
- method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks();
- method public int getTransportDataType();
- method @Nullable public byte[] toByteArray();
- method public int totalBytes();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR;
- }
-
-}
-
package android.companion {
public final class AssociationRequest implements android.os.Parcelable {
@@ -21881,9 +20598,11 @@
field public static final int COLOR_Format24bitBGR888 = 12; // 0xc
field @Deprecated public static final int COLOR_Format24bitRGB888 = 11; // 0xb
field @Deprecated public static final int COLOR_Format25bitARGB1888 = 14; // 0xe
+ field public static final int COLOR_Format32bitABGR2101010 = 2130750114; // 0x7f00aaa2
field public static final int COLOR_Format32bitABGR8888 = 2130747392; // 0x7f00a000
field @Deprecated public static final int COLOR_Format32bitARGB8888 = 16; // 0x10
field @Deprecated public static final int COLOR_Format32bitBGRA8888 = 15; // 0xf
+ field public static final int COLOR_Format64bitABGRFloat = 2130710294; // 0x7f000f16
field @Deprecated public static final int COLOR_Format8bitRGB332 = 2; // 0x2
field @Deprecated public static final int COLOR_FormatCbYCrY = 27; // 0x1b
field @Deprecated public static final int COLOR_FormatCrYCbY = 28; // 0x1c
@@ -21916,10 +20635,12 @@
field @Deprecated public static final int COLOR_FormatYUV422SemiPlanar = 24; // 0x18
field public static final int COLOR_FormatYUV444Flexible = 2135181448; // 0x7f444888
field @Deprecated public static final int COLOR_FormatYUV444Interleaved = 29; // 0x1d
+ field public static final int COLOR_FormatYUVP010 = 54; // 0x36
field @Deprecated public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00
field @Deprecated public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100
field public static final String FEATURE_AdaptivePlayback = "adaptive-playback";
field public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp";
+ field public static final String FEATURE_EncodingStatistics = "encoding-statistics";
field public static final String FEATURE_FrameParsing = "frame-parsing";
field public static final String FEATURE_IntraRefresh = "intra-refresh";
field public static final String FEATURE_LowLatency = "low-latency";
@@ -22003,11 +20724,14 @@
field public static final int AVCProfileHigh422 = 32; // 0x20
field public static final int AVCProfileHigh444 = 64; // 0x40
field public static final int AVCProfileMain = 2; // 0x2
+ field public static final int DolbyVisionLevel8k30 = 1024; // 0x400
+ field public static final int DolbyVisionLevel8k60 = 2048; // 0x800
field public static final int DolbyVisionLevelFhd24 = 4; // 0x4
field public static final int DolbyVisionLevelFhd30 = 8; // 0x8
field public static final int DolbyVisionLevelFhd60 = 16; // 0x10
field public static final int DolbyVisionLevelHd24 = 1; // 0x1
field public static final int DolbyVisionLevelHd30 = 2; // 0x2
+ field public static final int DolbyVisionLevelUhd120 = 512; // 0x200
field public static final int DolbyVisionLevelUhd24 = 32; // 0x20
field public static final int DolbyVisionLevelUhd30 = 64; // 0x40
field public static final int DolbyVisionLevelUhd48 = 128; // 0x80
@@ -22693,6 +21417,7 @@
field public static final String KEY_OPERATING_RATE = "operating-rate";
field public static final String KEY_OUTPUT_REORDER_DEPTH = "output-reorder-depth";
field public static final String KEY_PCM_ENCODING = "pcm-encoding";
+ field public static final String KEY_PICTURE_TYPE = "picture-type";
field public static final String KEY_PIXEL_ASPECT_RATIO_HEIGHT = "sar-height";
field public static final String KEY_PIXEL_ASPECT_RATIO_WIDTH = "sar-width";
field public static final String KEY_PREPEND_HEADER_TO_SYNC_FRAMES = "prepend-sps-pps-to-idr-frames";
@@ -22710,6 +21435,8 @@
field public static final String KEY_TILE_HEIGHT = "tile-height";
field public static final String KEY_TILE_WIDTH = "tile-width";
field public static final String KEY_TRACK_ID = "track-id";
+ field public static final String KEY_VIDEO_ENCODING_STATISTICS_LEVEL = "video-encoding-statistics-level";
+ field public static final String KEY_VIDEO_QP_AVERAGE = "video-qp-average";
field public static final String KEY_VIDEO_QP_B_MAX = "video-qp-b-max";
field public static final String KEY_VIDEO_QP_B_MIN = "video-qp-b-min";
field public static final String KEY_VIDEO_QP_I_MAX = "video-qp-i-max";
@@ -22754,12 +21481,18 @@
field public static final String MIMETYPE_VIDEO_SCRAMBLED = "video/scrambled";
field public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8";
field public static final String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9";
+ field public static final int PICTURE_TYPE_B = 3; // 0x3
+ field public static final int PICTURE_TYPE_I = 1; // 0x1
+ field public static final int PICTURE_TYPE_P = 2; // 0x2
+ field public static final int PICTURE_TYPE_UNKNOWN = 0; // 0x0
field public static final int TYPE_BYTE_BUFFER = 5; // 0x5
field public static final int TYPE_FLOAT = 3; // 0x3
field public static final int TYPE_INTEGER = 1; // 0x1
field public static final int TYPE_LONG = 2; // 0x2
field public static final int TYPE_NULL = 0; // 0x0
field public static final int TYPE_STRING = 4; // 0x4
+ field public static final int VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1; // 0x1
+ field public static final int VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0; // 0x0
}
public final class MediaMetadata implements android.os.Parcelable {
@@ -26483,15 +25216,18 @@
public static final class Ikev2VpnProfile.Builder {
ctor public Ikev2VpnProfile.Builder(@NonNull String, @NonNull String);
+ ctor public Ikev2VpnProfile.Builder(@NonNull android.net.ipsec.ike.IkeTunnelConnectionParams);
method @NonNull public android.net.Ikev2VpnProfile build();
method @NonNull public android.net.Ikev2VpnProfile.Builder setAllowedAlgorithms(@NonNull java.util.List<java.lang.String>);
method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthDigitalSignature(@NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey, @Nullable java.security.cert.X509Certificate);
method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthPsk(@NonNull byte[]);
method @NonNull public android.net.Ikev2VpnProfile.Builder setAuthUsernamePassword(@NonNull String, @NonNull String, @Nullable java.security.cert.X509Certificate);
method @NonNull public android.net.Ikev2VpnProfile.Builder setBypassable(boolean);
+ method @NonNull public android.net.Ikev2VpnProfile.Builder setExcludeLocalRoutes(boolean);
method @NonNull public android.net.Ikev2VpnProfile.Builder setMaxMtu(int);
method @NonNull public android.net.Ikev2VpnProfile.Builder setMetered(boolean);
method @NonNull public android.net.Ikev2VpnProfile.Builder setProxy(@Nullable android.net.ProxyInfo);
+ method @NonNull public android.net.Ikev2VpnProfile.Builder setRequiresInternetValidation(boolean);
}
public final class IpSecAlgorithm implements android.os.Parcelable {
@@ -26634,6 +25370,8 @@
}
public abstract class PlatformVpnProfile {
+ method public final boolean getExcludeLocalRoutes();
+ method public final boolean getRequiresInternetValidation();
method public final int getType();
method @NonNull public final String getTypeString();
field public static final int TYPE_IKEV2_IPSEC_PSK = 7; // 0x7
@@ -26870,7 +25608,8 @@
public class VpnManager {
method public void deleteProvisionedVpnProfile();
method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
- method public void startProvisionedVpnProfile();
+ method @Deprecated public void startProvisionedVpnProfile();
+ method @NonNull public String startProvisionedVpnProfileSession();
method public void stopProvisionedVpnProfile();
}
@@ -26984,65 +25723,6 @@
}
-package android.net.nsd {
-
- public final class NsdManager {
- method public void discoverServices(String, int, android.net.nsd.NsdManager.DiscoveryListener);
- method public void registerService(android.net.nsd.NsdServiceInfo, int, android.net.nsd.NsdManager.RegistrationListener);
- method public void resolveService(android.net.nsd.NsdServiceInfo, android.net.nsd.NsdManager.ResolveListener);
- method public void stopServiceDiscovery(android.net.nsd.NsdManager.DiscoveryListener);
- method public void unregisterService(android.net.nsd.NsdManager.RegistrationListener);
- field public static final String ACTION_NSD_STATE_CHANGED = "android.net.nsd.STATE_CHANGED";
- field public static final String EXTRA_NSD_STATE = "nsd_state";
- field public static final int FAILURE_ALREADY_ACTIVE = 3; // 0x3
- field public static final int FAILURE_INTERNAL_ERROR = 0; // 0x0
- field public static final int FAILURE_MAX_LIMIT = 4; // 0x4
- field public static final int NSD_STATE_DISABLED = 1; // 0x1
- field public static final int NSD_STATE_ENABLED = 2; // 0x2
- field public static final int PROTOCOL_DNS_SD = 1; // 0x1
- }
-
- public static interface NsdManager.DiscoveryListener {
- method public void onDiscoveryStarted(String);
- method public void onDiscoveryStopped(String);
- method public void onServiceFound(android.net.nsd.NsdServiceInfo);
- method public void onServiceLost(android.net.nsd.NsdServiceInfo);
- method public void onStartDiscoveryFailed(String, int);
- method public void onStopDiscoveryFailed(String, int);
- }
-
- public static interface NsdManager.RegistrationListener {
- method public void onRegistrationFailed(android.net.nsd.NsdServiceInfo, int);
- method public void onServiceRegistered(android.net.nsd.NsdServiceInfo);
- method public void onServiceUnregistered(android.net.nsd.NsdServiceInfo);
- method public void onUnregistrationFailed(android.net.nsd.NsdServiceInfo, int);
- }
-
- public static interface NsdManager.ResolveListener {
- method public void onResolveFailed(android.net.nsd.NsdServiceInfo, int);
- method public void onServiceResolved(android.net.nsd.NsdServiceInfo);
- }
-
- public final class NsdServiceInfo implements android.os.Parcelable {
- ctor public NsdServiceInfo();
- method public int describeContents();
- method public java.util.Map<java.lang.String,byte[]> getAttributes();
- method public java.net.InetAddress getHost();
- method public int getPort();
- method public String getServiceName();
- method public String getServiceType();
- method public void removeAttribute(String);
- method public void setAttribute(String, String);
- method public void setHost(java.net.InetAddress);
- method public void setPort(int);
- method public void setServiceName(String);
- method public void setServiceType(String);
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.net.nsd.NsdServiceInfo> CREATOR;
- }
-
-}
-
package android.net.rtp {
@Deprecated public class AudioCodec {
@@ -30998,6 +29678,7 @@
field public static final int Q = 29; // 0x1d
field public static final int R = 30; // 0x1e
field public static final int S = 31; // 0x1f
+ field public static final int S_V2 = 32; // 0x20
field public static final int TIRAMISU = 10000; // 0x2710
}
@@ -31592,6 +30273,9 @@
method @Nullable public byte[] createByteArray();
method @Nullable public char[] createCharArray();
method @Nullable public double[] createDoubleArray();
+ method @Nullable public <T> T createFixedArray(@NonNull Class<T>, @NonNull int...);
+ method @Nullable public <T, S extends android.os.IInterface> T createFixedArray(@NonNull Class<T>, @NonNull java.util.function.Function<android.os.IBinder,S>, @NonNull int...);
+ method @Nullable public <T, S extends android.os.Parcelable> T createFixedArray(@NonNull Class<T>, @NonNull android.os.Parcelable.Creator<S>, @NonNull int...);
method @Nullable public float[] createFloatArray();
method @Nullable public int[] createIntArray();
method @Nullable public <T extends android.os.IInterface> T[] createInterfaceArray(@NonNull java.util.function.IntFunction<T[]>, @NonNull java.util.function.Function<android.os.IBinder,T>);
@@ -31632,6 +30316,9 @@
method public void readException();
method public void readException(int, String);
method public android.os.ParcelFileDescriptor readFileDescriptor();
+ method public <T> void readFixedArray(@NonNull T);
+ method public <T, S extends android.os.IInterface> void readFixedArray(@NonNull T, @NonNull java.util.function.Function<android.os.IBinder,S>);
+ method public <T, S extends android.os.Parcelable> void readFixedArray(@NonNull T, @NonNull android.os.Parcelable.Creator<S>);
method public float readFloat();
method public void readFloatArray(@NonNull float[]);
method @Deprecated @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
@@ -31675,6 +30362,7 @@
method public void setDataCapacity(int);
method public void setDataPosition(int);
method public void setDataSize(int);
+ method public void setPropagateAllowBlocking();
method public void unmarshall(@NonNull byte[], int, int);
method public void writeArray(@Nullable Object[]);
method public void writeBinderArray(@Nullable android.os.IBinder[]);
@@ -31690,6 +30378,7 @@
method public void writeDoubleArray(@Nullable double[]);
method public void writeException(@NonNull Exception);
method public void writeFileDescriptor(@NonNull java.io.FileDescriptor);
+ method public <T> void writeFixedArray(@Nullable T, int, @NonNull int...);
method public void writeFloat(float);
method public void writeFloatArray(@Nullable float[]);
method public void writeInt(int);
@@ -37506,6 +36195,28 @@
method @Deprecated @NonNull public android.security.KeyPairGeneratorSpec.Builder setSubject(@NonNull javax.security.auth.x500.X500Principal);
}
+ public class KeyStoreException extends java.lang.Exception {
+ method public int getNumericErrorCode();
+ method public boolean isSystemError();
+ method public boolean isTransientFailure();
+ method public boolean requiresUserAuthentication();
+ field public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9; // 0x9
+ field public static final int ERROR_ID_ATTESTATION_FAILURE = 8; // 0x8
+ field public static final int ERROR_INCORRECT_USAGE = 13; // 0xd
+ field public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4; // 0x4
+ field public static final int ERROR_KEYMINT_FAILURE = 10; // 0xa
+ field public static final int ERROR_KEYSTORE_FAILURE = 11; // 0xb
+ field public static final int ERROR_KEYSTORE_UNINITIALIZED = 3; // 0x3
+ field public static final int ERROR_KEY_CORRUPTED = 7; // 0x7
+ field public static final int ERROR_KEY_DOES_NOT_EXIST = 6; // 0x6
+ field public static final int ERROR_KEY_NOT_TEMPORALLY_VALID = 14; // 0xe
+ field public static final int ERROR_KEY_OPERATION_EXPIRED = 15; // 0xf
+ field public static final int ERROR_OTHER = 1; // 0x1
+ field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5
+ field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc
+ field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2
+ }
+
@Deprecated public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
method @Deprecated public boolean isEncryptionRequired();
}
@@ -41059,13 +39770,14 @@
field public static final String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
field public static final String KEY_CARRIER_SUPPORTS_OPP_DATA_AUTO_PROVISIONING_BOOL = "carrier_supports_opp_data_auto_provisioning_bool";
field public static final String KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL = "carrier_supports_ss_over_ut_bool";
+ field public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL = "carrier_supports_tethering_bool";
field public static final String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
field public static final String KEY_CARRIER_USSD_METHOD_INT = "carrier_ussd_method_int";
- field public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
+ field @Deprecated public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL = "carrier_ut_provisioning_required_bool";
field public static final String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
field public static final String KEY_CARRIER_VOLTE_OVERRIDE_WFC_PROVISIONING_BOOL = "carrier_volte_override_wfc_provisioning_bool";
- field public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
- field public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
+ field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
+ field @Deprecated public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL = "carrier_volte_provisioning_required_bool";
field public static final String KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL = "carrier_volte_tty_supported_bool";
field public static final String KEY_CARRIER_VT_AVAILABLE_BOOL = "carrier_vt_available_bool";
field @Deprecated public static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING = "carrier_vvm_package_name_string";
@@ -41141,6 +39853,7 @@
field public static final String KEY_IMS_CONFERENCE_SIZE_LIMIT_INT = "ims_conference_size_limit_int";
field public static final String KEY_IMS_DTMF_TONE_DELAY_INT = "ims_dtmf_tone_delay_int";
field public static final String KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL = "is_ims_conference_size_enforced_bool";
+ field public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL = "is_opportunistic_subscription_bool";
field public static final String KEY_LTE_ENABLED_BOOL = "lte_enabled_bool";
field public static final String KEY_LTE_RSRQ_THRESHOLDS_INT_ARRAY = "lte_rsrq_thresholds_int_array";
field public static final String KEY_LTE_RSSNR_THRESHOLDS_INT_ARRAY = "lte_rssnr_thresholds_int_array";
@@ -41225,6 +39938,7 @@
field public static final String KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL = "sim_network_unlock_allow_dismiss_bool";
field public static final String KEY_SMDP_SERVER_ADDRESS_STRING = "smdp_server_address_string";
field public static final String KEY_SMS_REQUIRES_DESTINATION_NUMBER_CONVERSION_BOOL = "sms_requires_destination_number_conversion_bool";
+ field public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING = "subscription_group_uuid_string";
field public static final String KEY_SUPPORTS_CALL_COMPOSER_BOOL = "supports_call_composer_bool";
field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_DTMF_BOOL = "supports_device_to_device_communication_using_dtmf_bool";
field public static final String KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_RTP_BOOL = "supports_device_to_device_communication_using_rtp_bool";
@@ -41268,6 +39982,7 @@
field public static final String KEY_WFC_EMERGENCY_ADDRESS_CARRIER_APP_STRING = "wfc_emergency_address_carrier_app_string";
field public static final String KEY_WORLD_MODE_ENABLED_BOOL = "world_mode_enabled_bool";
field public static final String KEY_WORLD_PHONE_BOOL = "world_phone_bool";
+ field public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000";
field public static final int SERVICE_CLASS_NONE = 0; // 0x0
field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
field public static final int USSD_OVER_CS_ONLY = 2; // 0x2
@@ -41291,14 +40006,23 @@
}
public static final class CarrierConfigManager.Ims {
+ field public static final String KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY = "ims.key_capability_type_call_composer_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY = "ims.key_capability_type_options_uce_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY = "ims.key_capability_type_presence_uce_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY = "ims.key_capability_type_sms_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY = "ims.key_capability_type_ut_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY = "ims.key_capability_type_video_int_array";
+ field public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY = "ims.key_capability_type_voice_int_array";
field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool";
field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool";
field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
+ field public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE = "ims.mmtel_requires_provisioning_bundle";
field public static final String KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT = "ims.non_rcs_capabilities_cache_expiration_sec_int";
field public static final String KEY_PREFIX = "ims.";
field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
field public static final String KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY = "ims.rcs_feature_tag_allowed_string_array";
+ field public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE = "ims.rcs_requires_provisioning_bundle";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
@@ -41349,6 +40073,7 @@
field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
+ field public static final String KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL = "iwlan.supports_eap_aka_fast_reauth_bool";
}
public abstract class CellIdentity implements android.os.Parcelable {
@@ -42920,6 +41645,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
method public int getActiveModemCount();
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getAllowedNetworkTypesForReason(int);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
method @Deprecated @RequiresPermission(value=android.Manifest.permission.READ_PHONE_STATE, conditional=true) public int getCallState();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getCallStateForSubscription();
@@ -42980,6 +41706,7 @@
method public int getSubscriptionId();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubscriptionId(@NonNull android.telecom.PhoneAccountHandle);
method public int getSupportedModemCount();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public long getSupportedRadioAccessFamily();
method @Nullable public String getTypeAllocationCode();
method @Nullable public String getTypeAllocationCode(int);
method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
@@ -43025,6 +41752,7 @@
method public String sendEnvelopeWithStatus(String);
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean);
@@ -43061,6 +41789,8 @@
field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
field public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
field public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
+ field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2
+ field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0
field public static final int APPTYPE_CSIM = 4; // 0x4
field public static final int APPTYPE_ISIM = 5; // 0x5
field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -43131,6 +41861,26 @@
field public static final int NETWORK_SELECTION_MODE_MANUAL = 2; // 0x2
field public static final int NETWORK_SELECTION_MODE_UNKNOWN = 0; // 0x0
field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
+ field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
+ field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
+ field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
+ field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
+ field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
+ field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
+ field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
+ field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
+ field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
+ field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
+ field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
+ field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
+ field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
+ field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
+ field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
+ field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
+ field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
+ field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
+ field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
+ field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
field public static final int NETWORK_TYPE_EHRPD = 14; // 0xe
@@ -43712,6 +42462,7 @@
public class ImsManager {
method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
+ method @NonNull public android.telephony.ims.ProvisioningManager getProvisioningManager(int);
field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
@@ -43962,6 +42713,23 @@
field public static final int REASON_UNKNOWN_TEMPORARY_ERROR = 1; // 0x1
}
+ public class ProvisioningManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isProvisioningRequiredForCapability(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public boolean isRcsProvisioningRequiredForCapability(int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerFeatureProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, int, boolean);
+ method public void unregisterFeatureProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback);
+ }
+
+ public static class ProvisioningManager.FeatureProvisioningCallback {
+ ctor public ProvisioningManager.FeatureProvisioningCallback();
+ method public void onFeatureProvisioningChanged(int, int, boolean);
+ method public void onRcsFeatureProvisioningChanged(int, int, boolean);
+ }
+
public class RcsUceAdapter {
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
}
@@ -44002,6 +42770,27 @@
field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
}
+ public class RcsFeature {
+ }
+
+ public static class RcsFeature.RcsImsCapabilities {
+ field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0
+ field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1
+ field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
+ }
+
+}
+
+package android.telephony.ims.stub {
+
+ public class ImsRegistrationImplBase {
+ field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2
+ field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+ field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+ field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+ field public static final int REGISTRATION_TECH_NR = 3; // 0x3
+ }
+
}
package android.telephony.mbms {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index b380e6d..1e4e787 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -54,7 +54,24 @@
package android.app.usage {
public class NetworkStatsManager {
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void forceUpdate();
+ method public static int getCollapsedRatType(int);
method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyNetworkStatus(@NonNull java.util.List<android.net.Network>, @NonNull java.util.List<android.net.NetworkStateSnapshot>, @Nullable String, @NonNull java.util.List<android.net.UnderlyingNetworkInfo>);
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForDevice(@NonNull android.net.NetworkTemplate, long, long);
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats queryDetailsForUidTagState(@NonNull android.net.NetworkTemplate, long, long, int, int, int) throws java.lang.SecurityException;
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats querySummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats.Bucket querySummaryForDevice(@NonNull android.net.NetworkTemplate, long, long);
+ method @NonNull @WorkerThread public android.app.usage.NetworkStats queryTaggedSummary(@NonNull android.net.NetworkTemplate, long, long) throws java.lang.SecurityException;
+ method public void registerUsageCallback(@NonNull android.net.NetworkTemplate, long, @NonNull java.util.concurrent.Executor, @NonNull android.app.usage.NetworkStatsManager.UsageCallback);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setDefaultGlobalAlert(long);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setPollOnOpen(boolean);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setStatsProviderWarningAndLimitAsync(@NonNull String, long, long);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void setUidForeground(int, boolean);
+ field public static final int NETWORK_TYPE_5G_NSA = -2; // 0xfffffffe
+ }
+
+ public abstract static class NetworkStatsManager.UsageCallback {
+ method public void onThresholdReached(@NonNull android.net.NetworkTemplate);
}
}
@@ -123,7 +140,7 @@
method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
method @NonNull public java.util.List<android.bluetooth.BluetoothCodecConfig> getHwOffloadFormatsSupportedForA2dp();
method @NonNull public java.util.List<android.bluetooth.BluetoothLeAudioCodecConfig> getHwOffloadFormatsSupportedForLeAudio();
- method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BtProfileConnectionInfo);
+ method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void handleBluetoothActiveDeviceChanged(@Nullable android.bluetooth.BluetoothDevice, @Nullable android.bluetooth.BluetoothDevice, @NonNull android.media.BluetoothProfileConnectionInfo);
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setA2dpSuspended(boolean);
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setBluetoothHeadsetProperties(@NonNull String, boolean, boolean);
method @RequiresPermission("android.permission.BLUETOOTH_STACK") public void setHfpEnabled(boolean);
@@ -133,18 +150,18 @@
field public static final int FLAG_FROM_KEY = 4096; // 0x1000
}
- public final class BtProfileConnectionInfo implements android.os.Parcelable {
- method @NonNull public static android.media.BtProfileConnectionInfo a2dpInfo(boolean, int);
- method @NonNull public static android.media.BtProfileConnectionInfo a2dpSinkInfo(int);
+ public final class BluetoothProfileConnectionInfo implements android.os.Parcelable {
+ method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpInfo(boolean, int);
+ method @NonNull public static android.media.BluetoothProfileConnectionInfo createA2dpSinkInfo(int);
+ method @NonNull public static android.media.BluetoothProfileConnectionInfo createHearingAidInfo(boolean);
+ method @NonNull public static android.media.BluetoothProfileConnectionInfo createLeAudioInfo(boolean, boolean);
method public int describeContents();
- method public boolean getIsLeOutput();
method public int getProfile();
- method public boolean getSuppressNoisyIntent();
method public int getVolume();
- method @NonNull public static android.media.BtProfileConnectionInfo hearingAidInfo(boolean);
- method @NonNull public static android.media.BtProfileConnectionInfo leAudio(boolean, boolean);
+ method public boolean isLeOutput();
+ method public boolean isSuppressNoisyIntent();
method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.BtProfileConnectionInfo> CREATOR;
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.BluetoothProfileConnectionInfo> CREATOR;
}
public class MediaMetadataRetriever implements java.lang.AutoCloseable {
@@ -201,10 +218,6 @@
package android.net {
- public final class ConnectivityFrameworkInitializerTiramisu {
- method public static void registerServiceWrappers();
- }
-
public final class EthernetNetworkSpecifier extends android.net.NetworkSpecifier implements android.os.Parcelable {
ctor public EthernetNetworkSpecifier(@NonNull String);
method public int describeContents();
@@ -221,11 +234,43 @@
method public int getResourceId();
}
+ public class LocalSocket implements java.io.Closeable {
+ ctor public LocalSocket(@NonNull java.io.FileDescriptor);
+ }
+
+ public class NetworkIdentity {
+ method public int getOemManaged();
+ method public int getRatType();
+ method @Nullable public String getSubscriberId();
+ method public int getType();
+ method @Nullable public String getWifiNetworkKey();
+ method public boolean isDefaultNetwork();
+ method public boolean isMetered();
+ method public boolean isRoaming();
+ }
+
+ public static final class NetworkIdentity.Builder {
+ ctor public NetworkIdentity.Builder();
+ method @NonNull public android.net.NetworkIdentity build();
+ method @NonNull public android.net.NetworkIdentity.Builder clearRatType();
+ method @NonNull public android.net.NetworkIdentity.Builder setDefaultNetwork(boolean);
+ method @NonNull public android.net.NetworkIdentity.Builder setMetered(boolean);
+ method @NonNull public android.net.NetworkIdentity.Builder setNetworkStateSnapshot(@NonNull android.net.NetworkStateSnapshot);
+ method @NonNull public android.net.NetworkIdentity.Builder setOemManaged(int);
+ method @NonNull public android.net.NetworkIdentity.Builder setRatType(int);
+ method @NonNull public android.net.NetworkIdentity.Builder setRoaming(boolean);
+ method @NonNull public android.net.NetworkIdentity.Builder setSubscriberId(@Nullable String);
+ method @NonNull public android.net.NetworkIdentity.Builder setType(int);
+ method @NonNull public android.net.NetworkIdentity.Builder setWifiNetworkKey(@Nullable String);
+ }
+
public class NetworkPolicyManager {
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getMultipathPreference(@NonNull android.net.Network);
method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public int getRestrictBackgroundStatus(int);
+ method @Nullable @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public android.telephony.SubscriptionPlan getSubscriptionPlan(@NonNull android.net.NetworkTemplate);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidNetworkingBlocked(int, boolean);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public boolean isUidRestrictedOnMeteredNetworks(int);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK}) public void notifyStatsProviderWarningOrLimitReached();
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void registerNetworkPolicyCallback(@Nullable java.util.concurrent.Executor, @NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
method @RequiresPermission(android.Manifest.permission.OBSERVE_NETWORK_POLICY) public void unregisterNetworkPolicyCallback(@NonNull android.net.NetworkPolicyManager.NetworkPolicyCallback);
}
@@ -246,6 +291,44 @@
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStateSnapshot> CREATOR;
}
+ public class NetworkStatsCollection {
+ method @NonNull public java.util.Map<android.net.NetworkStatsCollection.Key,android.net.NetworkStatsHistory> getEntries();
+ }
+
+ public static final class NetworkStatsCollection.Builder {
+ ctor public NetworkStatsCollection.Builder(long);
+ method @NonNull public android.net.NetworkStatsCollection.Builder addEntry(@NonNull android.net.NetworkStatsCollection.Key, @NonNull android.net.NetworkStatsHistory);
+ method @NonNull public android.net.NetworkStatsCollection build();
+ }
+
+ public static class NetworkStatsCollection.Key {
+ ctor public NetworkStatsCollection.Key(@NonNull java.util.Set<android.net.NetworkIdentity>, int, int, int);
+ }
+
+ public final class NetworkStatsHistory implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public java.util.List<android.net.NetworkStatsHistory.Entry> getEntries();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStatsHistory> CREATOR;
+ }
+
+ public static final class NetworkStatsHistory.Builder {
+ ctor public NetworkStatsHistory.Builder(long, int);
+ method @NonNull public android.net.NetworkStatsHistory.Builder addEntry(@NonNull android.net.NetworkStatsHistory.Entry);
+ method @NonNull public android.net.NetworkStatsHistory build();
+ }
+
+ public static final class NetworkStatsHistory.Entry {
+ ctor public NetworkStatsHistory.Entry(long, long, long, long, long, long, long);
+ method public long getActiveTime();
+ method public long getBucketStart();
+ method public long getOperations();
+ method public long getRxBytes();
+ method public long getRxPackets();
+ method public long getTxBytes();
+ method public long getTxPackets();
+ }
+
public final class NetworkTemplate implements android.os.Parcelable {
method public int describeContents();
method public int getDefaultNetworkStatus();
@@ -256,6 +339,7 @@
method public int getRoaming();
method @NonNull public java.util.Set<java.lang.String> getSubscriberIds();
method @NonNull public java.util.Set<java.lang.String> getWifiNetworkKeys();
+ method public boolean matches(@NonNull android.net.NetworkIdentity);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkTemplate> CREATOR;
field public static final int MATCH_BLUETOOTH = 8; // 0x8
@@ -301,6 +385,11 @@
method public static void setHttpProxyConfiguration(@Nullable android.net.ProxyInfo);
}
+ public class TrafficStats {
+ method public static void attachSocketTagger();
+ method public static void init(@NonNull android.content.Context);
+ }
+
public final class UnderlyingNetworkInfo implements android.os.Parcelable {
ctor public UnderlyingNetworkInfo(int, @NonNull String, @NonNull java.util.List<java.lang.String>);
method public int describeContents();
@@ -321,6 +410,17 @@
}
+package android.net.netstats {
+
+ public class NetworkStatsDataMigrationUtils {
+ method @NonNull public static android.net.NetworkStatsCollection readPlatformCollection(@NonNull String, long) throws java.io.IOException;
+ field public static final String PREFIX_UID = "uid";
+ field public static final String PREFIX_UID_TAG = "uid_tag";
+ field public static final String PREFIX_XT = "xt";
+ }
+
+}
+
package android.os {
public final class BatteryStatsManager {
@@ -344,6 +444,7 @@
}
public class Process {
+ field public static final int NFC_UID = 1027; // 0x403
field public static final int VPN_UID = 1016; // 0x3f8
}
@@ -375,6 +476,16 @@
method @NonNull public java.util.List<android.content.ComponentName> getEnabledComponentOverrides(@NonNull String);
}
+ public final class Trace {
+ method public static void asyncTraceBegin(long, @NonNull String, int);
+ method public static void asyncTraceEnd(long, @NonNull String, int);
+ method public static boolean isTagEnabled(long);
+ method public static void traceBegin(long, @NonNull String);
+ method public static void traceCounter(long, @NonNull String, int);
+ method public static void traceEnd(long);
+ field public static final long TRACE_TAG_NETWORK = 2097152L; // 0x200000L
+ }
+
}
package android.os.storage {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a8ef47e..7d68ee1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -63,6 +63,7 @@
field public static final String BIND_TELEPHONY_NETWORK_SERVICE = "android.permission.BIND_TELEPHONY_NETWORK_SERVICE";
field public static final String BIND_TEXTCLASSIFIER_SERVICE = "android.permission.BIND_TEXTCLASSIFIER_SERVICE";
field public static final String BIND_TIME_ZONE_PROVIDER_SERVICE = "android.permission.BIND_TIME_ZONE_PROVIDER_SERVICE";
+ field public static final String BIND_TRACE_REPORT_SERVICE = "android.permission.BIND_TRACE_REPORT_SERVICE";
field public static final String BIND_TRANSLATION_SERVICE = "android.permission.BIND_TRANSLATION_SERVICE";
field public static final String BIND_TRUST_AGENT = "android.permission.BIND_TRUST_AGENT";
field public static final String BIND_TV_REMOTE_SERVICE = "android.permission.BIND_TV_REMOTE_SERVICE";
@@ -144,6 +145,7 @@
field public static final String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
field public static final String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS";
field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
+ field public static final String MANAGE_ETHERNET_NETWORKS = "android.permission.MANAGE_ETHERNET_NETWORKS";
field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
field public static final String MANAGE_HOTWORD_DETECTION = "android.permission.MANAGE_HOTWORD_DETECTION";
field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
@@ -316,6 +318,7 @@
public static final class R.array {
field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005
+ field public static final int config_optionalIpSecAlgorithms;
}
public static final class R.attr {
@@ -1850,6 +1853,8 @@
}
public class NetworkStatsManager {
+ method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getMobileUidStats();
+ method @NonNull @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public android.net.NetworkStats getWifiUidStats();
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void registerNetworkStatsProvider(@NonNull String, @NonNull android.net.netstats.provider.NetworkStatsProvider);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STATS_PROVIDER, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void unregisterNetworkStatsProvider(@NonNull android.net.netstats.provider.NetworkStatsProvider);
}
@@ -1913,423 +1918,6 @@
}
-package android.bluetooth {
-
- public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
- method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public android.bluetooth.BufferConstraints getBufferConstraints();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getDynamicBufferSupport();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setBufferLengthMillis(int, int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD = 1; // 0x1
- field public static final int DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING = 2; // 0x2
- field public static final int DYNAMIC_BUFFER_SUPPORT_NONE = 0; // 0x0
- field public static final int OPTIONAL_CODECS_NOT_SUPPORTED = 0; // 0x0
- field public static final int OPTIONAL_CODECS_PREF_DISABLED = 0; // 0x0
- field public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; // 0x1
- field public static final int OPTIONAL_CODECS_PREF_UNKNOWN = -1; // 0xffffffff
- field public static final int OPTIONAL_CODECS_SUPPORTED = 1; // 0x1
- field public static final int OPTIONAL_CODECS_SUPPORT_UNKNOWN = -1; // 0xffffffff
- }
-
- public final class BluetoothA2dpSink implements android.bluetooth.BluetoothProfile {
- method public void finalize();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isAudioPlaying(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.a2dp-sink.profile.action.CONNECTION_STATE_CHANGED";
- }
-
- public final class BluetoothActivityEnergyInfo implements android.os.Parcelable {
- method public int getBluetoothStackState();
- method public long getControllerEnergyUsed();
- method public long getControllerIdleTimeMillis();
- method public long getControllerRxTimeMillis();
- method public long getControllerTxTimeMillis();
- method public long getTimestampMillis();
- method @NonNull public java.util.List<android.bluetooth.UidTraffic> getUidTraffic();
- method public boolean isValid();
- field public static final int BT_STACK_STATE_INVALID = 0; // 0x0
- field public static final int BT_STACK_STATE_STATE_ACTIVE = 1; // 0x1
- field public static final int BT_STACK_STATE_STATE_IDLE = 3; // 0x3
- field public static final int BT_STACK_STATE_STATE_SCANNING = 2; // 0x2
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothActivityEnergyInfo> CREATOR;
- }
-
- public final class BluetoothAdapter {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean disable(boolean);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disableBLE();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableBLE();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean enableNoAutoConnect();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void generateLocalOobData(int, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OobDataCallback);
- method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getActiveDevices(int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getDiscoveryEndMillis();
- method public boolean isBleScanAlwaysAvailable();
- method public boolean isLeEnabled();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int);
- field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
- field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
- 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
- }
-
- public static interface BluetoothAdapter.OnMetadataChangedListener {
- method public void onMetadataChanged(@NonNull android.bluetooth.BluetoothDevice, int, @Nullable byte[]);
- }
-
- public static interface BluetoothAdapter.OobDataCallback {
- method public void onError(int);
- method public void onOobData(int, @NonNull android.bluetooth.OobData);
- }
-
- public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.Map getGroupUuidMapByDevice(@Nullable android.bluetooth.BluetoothDevice);
- method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.UUID groupLock(int, @Nullable java.util.concurrent.Executor, @Nullable android.bluetooth.BluetoothCsipSetCoordinator.ClientLockCallback);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean groupUnlock(@NonNull java.util.UUID);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_DEVICE_AVAILABLE = "android.bluetooth.action.CSIS_DEVICE_AVAILABLE";
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public static final String ACTION_CSIS_SET_MEMBER_AVAILABLE = "android.bluetooth.action.CSIS_SET_MEMBER_AVAILABLE";
- }
-
- public static interface BluetoothCsipSetCoordinator.ClientLockCallback {
- method public void onGroupLockSet(int, int, boolean);
- }
-
- public final class BluetoothDevice implements android.os.Parcelable {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean canBondWithoutDialog();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean cancelBondProcess();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean fetchUuidsWithSdp(int);
- method @Nullable @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public byte[] getMetadata(int);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getSimAccessPermission();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isConnected();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isEncrypted();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isInSilenceMode();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeBond();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMessageAccessPermission(int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setMetadata(int, @NonNull byte[]);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setPhonebookAccessPermission(int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSilenceMode(boolean);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setSimAccessPermission(int);
- field public static final int ACCESS_ALLOWED = 1; // 0x1
- field public static final int ACCESS_REJECTED = 2; // 0x2
- field public static final int ACCESS_UNKNOWN = 0; // 0x0
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_SILENCE_MODE_CHANGED = "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
- field public static final String DEVICE_TYPE_DEFAULT = "Default";
- field public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset";
- field public static final String DEVICE_TYPE_WATCH = "Watch";
- field public static final int METADATA_COMPANION_APP = 4; // 0x4
- field public static final int METADATA_DEVICE_TYPE = 17; // 0x11
- field public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; // 0x10
- field public static final int METADATA_HARDWARE_VERSION = 3; // 0x3
- field public static final int METADATA_IS_UNTETHERED_HEADSET = 6; // 0x6
- field public static final int METADATA_MAIN_BATTERY = 18; // 0x12
- field public static final int METADATA_MAIN_CHARGING = 19; // 0x13
- field public static final int METADATA_MAIN_ICON = 5; // 0x5
- field public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20; // 0x14
- field public static final int METADATA_MANUFACTURER_NAME = 0; // 0x0
- field public static final int METADATA_MAX_LENGTH = 2048; // 0x800
- field public static final int METADATA_MODEL_NAME = 1; // 0x1
- field public static final int METADATA_SOFTWARE_VERSION = 2; // 0x2
- field public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; // 0xc
- field public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; // 0xf
- field public static final int METADATA_UNTETHERED_CASE_ICON = 9; // 0x9
- field public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23; // 0x17
- field public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; // 0xa
- field public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; // 0xd
- field public static final int METADATA_UNTETHERED_LEFT_ICON = 7; // 0x7
- field public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21; // 0x15
- field public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; // 0xb
- field public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; // 0xe
- field public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; // 0x8
- field public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22; // 0x16
- }
-
- public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean connect(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean disconnect(android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean isInbandRingingEnabled();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean startScoUsingVirtualVoiceCall();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean stopScoUsingVirtualVoiceCall();
- }
-
- public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public long getHiSyncId(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- }
-
- public final class BluetoothHidDevice implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- }
-
- public final class BluetoothHidHost implements android.bluetooth.BluetoothProfile {
- method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.input.profile.action.CONNECTION_STATE_CHANGED";
- }
-
- public final class BluetoothMap implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
- method public void close();
- method protected void finalize();
- method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
- }
-
- public final class BluetoothMapClient implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.SEND_SMS}) public boolean sendMessage(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.Collection<android.net.Uri>, @NonNull String, @Nullable android.app.PendingIntent, @Nullable android.app.PendingIntent);
- }
-
- public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
- method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean isTetheringOn();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.TETHER_PRIVILEGED}) public void setBluetoothTethering(boolean);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pan.profile.action.CONNECTION_STATE_CHANGED";
- field public static final String ACTION_TETHERING_STATE_CHANGED = "android.bluetooth.action.TETHERING_STATE_CHANGED";
- field public static final String EXTRA_LOCAL_ROLE = "android.bluetooth.pan.extra.LOCAL_ROLE";
- field public static final String EXTRA_TETHERING_STATE = "android.bluetooth.extra.TETHERING_STATE";
- field public static final int LOCAL_NAP_ROLE = 1; // 0x1
- field public static final int LOCAL_PANU_ROLE = 2; // 0x2
- field public static final int PAN_ROLE_NONE = 0; // 0x0
- field public static final int REMOTE_NAP_ROLE = 1; // 0x1
- field public static final int REMOTE_PANU_ROLE = 2; // 0x2
- field public static final int TETHERING_STATE_OFF = 1; // 0x1
- field public static final int TETHERING_STATE_ON = 2; // 0x2
- }
-
- public class BluetoothPbap implements android.bluetooth.BluetoothProfile {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.pbap.profile.action.CONNECTION_STATE_CHANGED";
- }
-
- public interface BluetoothProfile {
- field public static final int A2DP_SINK = 11; // 0xb
- field public static final int AVRCP_CONTROLLER = 12; // 0xc
- field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
- field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
- field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
- field public static final int HEADSET_CLIENT = 16; // 0x10
- field public static final int MAP_CLIENT = 18; // 0x12
- field public static final int PAN = 5; // 0x5
- field public static final int PBAP_CLIENT = 17; // 0x11
- field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
- field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
- field public static final int VOLUME_CONTROL = 23; // 0x17
- }
-
- public final class BluetoothStatusCodes {
- field public static final int ERROR_ANOTHER_ACTIVE_OOB_REQUEST = 1000; // 0x3e8
- }
-
- public final class BluetoothUuid {
- method public static boolean containsAnyUuid(@Nullable android.os.ParcelUuid[], @Nullable android.os.ParcelUuid[]);
- method @NonNull public static android.os.ParcelUuid parseUuidFrom(@Nullable byte[]);
- field @NonNull public static final android.os.ParcelUuid A2DP_SINK;
- field @NonNull public static final android.os.ParcelUuid A2DP_SOURCE;
- field @NonNull public static final android.os.ParcelUuid ADV_AUDIO_DIST;
- field @NonNull public static final android.os.ParcelUuid AVRCP_CONTROLLER;
- field @NonNull public static final android.os.ParcelUuid AVRCP_TARGET;
- field @NonNull public static final android.os.ParcelUuid BASE_UUID;
- field @NonNull public static final android.os.ParcelUuid BNEP;
- field @NonNull public static final android.os.ParcelUuid CAP;
- field @NonNull public static final android.os.ParcelUuid COORDINATED_SET;
- field @NonNull public static final android.os.ParcelUuid DIP;
- field @NonNull public static final android.os.ParcelUuid GENERIC_MEDIA_CONTROL;
- field @NonNull public static final android.os.ParcelUuid HEARING_AID;
- field @NonNull public static final android.os.ParcelUuid HFP;
- field @NonNull public static final android.os.ParcelUuid HFP_AG;
- field @NonNull public static final android.os.ParcelUuid HID;
- field @NonNull public static final android.os.ParcelUuid HOGP;
- field @NonNull public static final android.os.ParcelUuid HSP;
- field @NonNull public static final android.os.ParcelUuid HSP_AG;
- field @NonNull public static final android.os.ParcelUuid LE_AUDIO;
- field @NonNull public static final android.os.ParcelUuid MAP;
- field @NonNull public static final android.os.ParcelUuid MAS;
- field @NonNull public static final android.os.ParcelUuid MEDIA_CONTROL;
- field @NonNull public static final android.os.ParcelUuid MNS;
- field @NonNull public static final android.os.ParcelUuid NAP;
- field @NonNull public static final android.os.ParcelUuid OBEX_OBJECT_PUSH;
- field @NonNull public static final android.os.ParcelUuid PANU;
- field @NonNull public static final android.os.ParcelUuid PBAP_PCE;
- field @NonNull public static final android.os.ParcelUuid PBAP_PSE;
- field @NonNull public static final android.os.ParcelUuid SAP;
- field public static final int UUID_BYTES_128_BIT = 16; // 0x10
- field public static final int UUID_BYTES_16_BIT = 2; // 0x2
- field public static final int UUID_BYTES_32_BIT = 4; // 0x4
- field @NonNull public static final android.os.ParcelUuid VOLUME_CONTROL;
- }
-
- public final class BluetoothVolumeControl implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void close();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize();
- method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@Nullable android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int);
- field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED";
- }
-
- public final class BufferConstraint implements android.os.Parcelable {
- ctor public BufferConstraint(int, int, int);
- method public int describeContents();
- method public int getDefaultMillis();
- method public int getMaxMillis();
- method public int getMinMillis();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraint> CREATOR;
- }
-
- public final class BufferConstraints implements android.os.Parcelable {
- ctor public BufferConstraints(@NonNull java.util.List<android.bluetooth.BufferConstraint>);
- method public int describeContents();
- method @Nullable public android.bluetooth.BufferConstraint forCodec(int);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field public static final int BUFFER_CODEC_MAX_NUM = 32; // 0x20
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BufferConstraints> CREATOR;
- }
-
- public final class OobData implements android.os.Parcelable {
- method @NonNull public byte[] getClassOfDevice();
- method @NonNull public byte[] getClassicLength();
- method @NonNull public byte[] getConfirmationHash();
- method @NonNull public byte[] getDeviceAddressWithType();
- method @Nullable public byte[] getDeviceName();
- method @Nullable public byte[] getLeAppearance();
- method @NonNull public int getLeDeviceRole();
- method @NonNull public int getLeFlags();
- method @Nullable public byte[] getLeTemporaryKey();
- method @NonNull public byte[] getRandomizerHash();
- field public static final int CLASS_OF_DEVICE_OCTETS = 3; // 0x3
- field public static final int CONFIRMATION_OCTETS = 16; // 0x10
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.OobData> CREATOR;
- field public static final int DEVICE_ADDRESS_OCTETS = 7; // 0x7
- field public static final int LE_APPEARANCE_OCTETS = 2; // 0x2
- field public static final int LE_DEVICE_FLAG_OCTETS = 1; // 0x1
- field public static final int LE_DEVICE_ROLE_BOTH_PREFER_CENTRAL = 3; // 0x3
- field public static final int LE_DEVICE_ROLE_BOTH_PREFER_PERIPHERAL = 2; // 0x2
- field public static final int LE_DEVICE_ROLE_CENTRAL_ONLY = 1; // 0x1
- field public static final int LE_DEVICE_ROLE_OCTETS = 1; // 0x1
- field public static final int LE_DEVICE_ROLE_PERIPHERAL_ONLY = 0; // 0x0
- field public static final int LE_FLAG_BREDR_NOT_SUPPORTED = 2; // 0x2
- field public static final int LE_FLAG_GENERAL_DISCOVERY_MODE = 1; // 0x1
- field public static final int LE_FLAG_LIMITED_DISCOVERY_MODE = 0; // 0x0
- field public static final int LE_FLAG_SIMULTANEOUS_CONTROLLER = 3; // 0x3
- field public static final int LE_FLAG_SIMULTANEOUS_HOST = 4; // 0x4
- field public static final int LE_TK_OCTETS = 16; // 0x10
- field public static final int OOB_LENGTH_OCTETS = 2; // 0x2
- field public static final int RANDOMIZER_OCTETS = 16; // 0x10
- }
-
- public static final class OobData.ClassicBuilder {
- ctor public OobData.ClassicBuilder(@NonNull byte[], @NonNull byte[], @NonNull byte[]);
- method @NonNull public android.bluetooth.OobData build();
- method @NonNull public android.bluetooth.OobData.ClassicBuilder setClassOfDevice(@NonNull byte[]);
- method @NonNull public android.bluetooth.OobData.ClassicBuilder setDeviceName(@NonNull byte[]);
- method @NonNull public android.bluetooth.OobData.ClassicBuilder setRandomizerHash(@NonNull byte[]);
- }
-
- public static final class OobData.LeBuilder {
- ctor public OobData.LeBuilder(@NonNull byte[], @NonNull byte[], int);
- method @NonNull public android.bluetooth.OobData build();
- method @NonNull public android.bluetooth.OobData.LeBuilder setDeviceName(@NonNull byte[]);
- method @NonNull public android.bluetooth.OobData.LeBuilder setLeFlags(int);
- method @NonNull public android.bluetooth.OobData.LeBuilder setLeTemporaryKey(@NonNull byte[]);
- method @NonNull public android.bluetooth.OobData.LeBuilder setRandomizerHash(@NonNull byte[]);
- }
-
- public final class UidTraffic implements java.lang.Cloneable android.os.Parcelable {
- method public long getRxBytes();
- method public long getTxBytes();
- method public int getUid();
- field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.UidTraffic> CREATOR;
- }
-
-}
-
-package android.bluetooth.le {
-
- public final class AdvertiseSettings implements android.os.Parcelable {
- method public int getOwnAddressType();
- }
-
- public static final class AdvertiseSettings.Builder {
- method @NonNull public android.bluetooth.le.AdvertiseSettings.Builder setOwnAddressType(int);
- }
-
- public final class AdvertisingSetParameters implements android.os.Parcelable {
- method public int getOwnAddressType();
- field public static final int ADDRESS_TYPE_DEFAULT = -1; // 0xffffffff
- field public static final int ADDRESS_TYPE_PUBLIC = 0; // 0x0
- field public static final int ADDRESS_TYPE_RANDOM = 1; // 0x1
- }
-
- public static final class AdvertisingSetParameters.Builder {
- method @NonNull public android.bluetooth.le.AdvertisingSetParameters.Builder setOwnAddressType(int);
- }
-
- public final class BluetoothLeScanner {
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
- method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.UPDATE_DEVICE_STATS}) public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
- method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
- }
-
- @Deprecated public final class ResultStorageDescriptor implements android.os.Parcelable {
- ctor @Deprecated public ResultStorageDescriptor(int, int, int);
- method @Deprecated public int describeContents();
- method @Deprecated public int getLength();
- method @Deprecated public int getOffset();
- method @Deprecated public int getType();
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.ResultStorageDescriptor> CREATOR;
- }
-
- public final class ScanFilter implements android.os.Parcelable {
- method public int getAddressType();
- method @Nullable public byte[] getIrk();
- }
-
- public static final class ScanFilter.Builder {
- method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int);
- method @NonNull public android.bluetooth.le.ScanFilter.Builder setDeviceAddress(@NonNull String, int, @NonNull byte[]);
- field public static final int LEN_IRK_OCTETS = 16; // 0x10
- }
-
- public final class ScanSettings implements android.os.Parcelable {
- field public static final int SCAN_MODE_AMBIENT_DISCOVERY = 3; // 0x3
- field public static final int SCAN_RESULT_TYPE_ABBREVIATED = 1; // 0x1
- field public static final int SCAN_RESULT_TYPE_FULL = 0; // 0x0
- }
-
- public static final class ScanSettings.Builder {
- method public android.bluetooth.le.ScanSettings.Builder setScanResultType(int);
- }
-
- @Deprecated public final class TruncatedFilter {
- ctor @Deprecated public TruncatedFilter(android.bluetooth.le.ScanFilter, java.util.List<android.bluetooth.le.ResultStorageDescriptor>);
- method @Deprecated public android.bluetooth.le.ScanFilter getFilter();
- method @Deprecated public java.util.List<android.bluetooth.le.ResultStorageDescriptor> getStorageDescriptors();
- }
-
-}
-
package android.companion {
public final class CompanionDeviceManager {
@@ -2408,6 +1996,7 @@
field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
+ field public static final String NEARBY_SERVICE = "nearby";
field public static final String NETD_SERVICE = "netd";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
@@ -3366,6 +2955,7 @@
method public void sendKeyEvent(int, boolean);
method public void sendVendorCommand(int, byte[], boolean);
method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener);
+ method public void setVendorCommandListener(@NonNull android.hardware.hdmi.HdmiControlManager.VendorCommandListener, int);
}
public final class HdmiControlManager {
@@ -7433,7 +7023,10 @@
package android.net {
public class EthernetManager {
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void connectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void disconnectNetwork(@NonNull String, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull java.util.concurrent.Executor, @NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+ method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, android.Manifest.permission.NETWORK_STACK, android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}) public void updateConfiguration(@NonNull String, @NonNull android.net.EthernetNetworkUpdateRequest, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.BiConsumer<android.net.Network,android.net.EthernetNetworkManagementException>);
}
public static interface EthernetManager.TetheredInterfaceCallback {
@@ -7445,6 +7038,22 @@
method public void release();
}
+ public final class EthernetNetworkManagementException extends java.lang.RuntimeException implements android.os.Parcelable {
+ ctor public EthernetNetworkManagementException(@NonNull String);
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkManagementException> CREATOR;
+ }
+
+ public final class EthernetNetworkUpdateRequest implements android.os.Parcelable {
+ ctor public EthernetNetworkUpdateRequest(@NonNull android.net.StaticIpConfiguration, @NonNull android.net.NetworkCapabilities);
+ method public int describeContents();
+ method @NonNull public android.net.StaticIpConfiguration getIpConfig();
+ method @NonNull public android.net.NetworkCapabilities getNetworkCapabilities();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.EthernetNetworkUpdateRequest> CREATOR;
+ }
+
public final class IpSecManager {
method @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public void applyTunnelModeTransform(@NonNull android.net.IpSecManager.IpSecTunnelInterface, int, @NonNull android.net.IpSecTransform) throws java.io.IOException;
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_IPSEC_TUNNELS) public android.net.IpSecManager.IpSecTunnelInterface createIpSecTunnelInterface(@NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull android.net.Network) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException;
@@ -7523,11 +7132,12 @@
field public static final String PERMISSION_MAINLINE_NETWORK_STACK = "android.permission.MAINLINE_NETWORK_STACK";
}
- public final class NetworkStats implements android.os.Parcelable {
+ public final class NetworkStats implements java.lang.Iterable<android.net.NetworkStats.Entry> android.os.Parcelable {
ctor public NetworkStats(long, int);
method @NonNull public android.net.NetworkStats add(@NonNull android.net.NetworkStats);
method @NonNull public android.net.NetworkStats addEntry(@NonNull android.net.NetworkStats.Entry);
method public int describeContents();
+ method @NonNull public java.util.Iterator<android.net.NetworkStats.Entry> iterator();
method @NonNull public android.net.NetworkStats subtract(@NonNull android.net.NetworkStats);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkStats> CREATOR;
@@ -8240,6 +7850,7 @@
}
public static class Build.VERSION {
+ field @NonNull public static final java.util.Set<java.lang.String> KNOWN_CODENAMES;
field @NonNull public static final String PREVIEW_SDK_FINGERPRINT;
}
@@ -10533,6 +10144,22 @@
}
+package android.service.tracing {
+
+ public class TraceReportService extends android.app.Service {
+ ctor public TraceReportService();
+ method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public boolean onMessage(@NonNull android.os.Message);
+ method public void onReportTrace(@NonNull android.service.tracing.TraceReportService.TraceParams);
+ }
+
+ public static final class TraceReportService.TraceParams {
+ method @NonNull public android.os.ParcelFileDescriptor getFd();
+ method @NonNull public java.util.UUID getUuid();
+ }
+
+}
+
package android.service.translation {
public abstract class TranslationService extends android.app.Service {
@@ -12063,7 +11690,6 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesBitmask();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypesForReason(int);
method @Nullable @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.ComponentName getAndUpdateDefaultRespondViaMessageApplication();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallForwarding(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CallForwardingInfoCallback);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getCallWaitingStatus(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
@@ -12106,7 +11732,6 @@
method public int getSimCardState();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -12157,7 +11782,6 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int sendThermalMitigationRequest(@NonNull android.telephony.ThermalMitigationRequest);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAllowedNetworkTypesForReason(int, long);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallForwarding(@NonNull android.telephony.CallForwardingInfo, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallWaitingEnabled(boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
@@ -12207,10 +11831,8 @@
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
- field public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; // 0x2
field public static final int ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G = 3; // 0x3
field public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; // 0x1
- field public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; // 0x0
field public static final int CALL_WAITING_STATUS_DISABLED = 2; // 0x2
field public static final int CALL_WAITING_STATUS_ENABLED = 1; // 0x1
field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
@@ -12249,26 +11871,6 @@
field public static final int KEY_TYPE_WLAN = 2; // 0x2
field public static final int MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL = 1; // 0x1
field public static final int MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED = 2; // 0x2
- field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
- field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
- field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
- field public static final long NETWORK_TYPE_BITMASK_EHRPD = 8192L; // 0x2000L
- field public static final long NETWORK_TYPE_BITMASK_EVDO_0 = 16L; // 0x10L
- field public static final long NETWORK_TYPE_BITMASK_EVDO_A = 32L; // 0x20L
- field public static final long NETWORK_TYPE_BITMASK_EVDO_B = 2048L; // 0x800L
- field public static final long NETWORK_TYPE_BITMASK_GPRS = 1L; // 0x1L
- field public static final long NETWORK_TYPE_BITMASK_GSM = 32768L; // 0x8000L
- field public static final long NETWORK_TYPE_BITMASK_HSDPA = 128L; // 0x80L
- field public static final long NETWORK_TYPE_BITMASK_HSPA = 512L; // 0x200L
- field public static final long NETWORK_TYPE_BITMASK_HSPAP = 16384L; // 0x4000L
- field public static final long NETWORK_TYPE_BITMASK_HSUPA = 256L; // 0x100L
- field public static final long NETWORK_TYPE_BITMASK_IWLAN = 131072L; // 0x20000L
- field public static final long NETWORK_TYPE_BITMASK_LTE = 4096L; // 0x1000L
- field public static final long NETWORK_TYPE_BITMASK_LTE_CA = 262144L; // 0x40000L
- field public static final long NETWORK_TYPE_BITMASK_NR = 524288L; // 0x80000L
- field public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = 65536L; // 0x10000L
- field public static final long NETWORK_TYPE_BITMASK_UMTS = 4L; // 0x4L
- field public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L; // 0x0L
field public static final int NR_DUAL_CONNECTIVITY_DISABLE = 2; // 0x2
field public static final int NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE = 3; // 0x3
field public static final int NR_DUAL_CONNECTIVITY_ENABLE = 1; // 0x1
@@ -12325,6 +11927,7 @@
}
public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
+ ctor public TelephonyManager.ModemActivityInfoException(int);
method public int getErrorCode();
field public static final int ERROR_INVALID_INFO_RECEIVED = 2; // 0x2
field public static final int ERROR_MODEM_RESPONSE_ERROR = 3; // 0x3
@@ -13293,13 +12896,21 @@
public class ImsService extends android.app.Service {
ctor public ImsService();
- method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
- method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
- method public void disableIms(int);
- method public void enableIms(int);
- method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method @Nullable public android.telephony.ims.feature.MmTelFeature createEmergencyOnlyMmTelFeature(int);
+ method @Deprecated public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+ method @Nullable public android.telephony.ims.feature.MmTelFeature createMmTelFeatureForSubscription(int, int);
+ method @Deprecated public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+ method @Nullable public android.telephony.ims.feature.RcsFeature createRcsFeatureForSubscription(int, int);
+ method @Deprecated public void disableIms(int);
+ method public void disableImsForSubscription(int, int);
+ method @Deprecated public void enableIms(int);
+ method public void enableImsForSubscription(int, int);
+ method @Deprecated public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method @NonNull public android.telephony.ims.stub.ImsConfigImplBase getConfigForSubscription(int, int);
+ method @NonNull public java.util.concurrent.Executor getExecutor();
method public long getImsServiceCapabilities();
- method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method @Deprecated public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method @NonNull public android.telephony.ims.stub.ImsRegistrationImplBase getRegistrationForSubscription(int, int);
method @Nullable public android.telephony.ims.stub.SipTransportImplBase getSipTransport(int);
method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
@@ -13523,18 +13134,16 @@
public class ProvisioningManager {
method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerRcsProvisioningCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
- method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void unregisterRcsProvisioningCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
@@ -13581,6 +13190,7 @@
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsClientConfiguration> CREATOR;
field public static final String RCS_PROFILE_1_0 = "UP_1.0";
field public static final String RCS_PROFILE_2_3 = "UP_2.3";
+ field public static final String RCS_PROFILE_2_4 = "UP_2.4";
}
public final class RcsContactPresenceTuple implements android.os.Parcelable {
@@ -13691,6 +13301,7 @@
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6; // 0x6
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4; // 0x4
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5; // 0x5
+ field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12; // 0xc
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9; // 0x9
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2; // 0x2
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3; // 0x3
@@ -13916,6 +13527,7 @@
public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
ctor public MmTelFeature();
+ ctor public MmTelFeature(@NonNull java.util.concurrent.Executor);
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
method public void changeOfferedRtpHeaderExtensionTypes(@NonNull java.util.Set<android.telephony.ims.RtpHeaderExtensionType>);
method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
@@ -13949,7 +13561,7 @@
}
public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
- ctor @Deprecated public RcsFeature();
+ ctor public RcsFeature();
ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
@@ -13966,9 +13578,6 @@
method public void addCapabilities(int);
method public boolean isCapable(int);
method public void removeCapabilities(int);
- field public static final int CAPABILITY_TYPE_NONE = 0; // 0x0
- field public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1; // 0x1
- field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
}
}
@@ -14054,6 +13663,7 @@
}
public class ImsConfigImplBase {
+ ctor public ImsConfigImplBase(@NonNull java.util.concurrent.Executor);
ctor public ImsConfigImplBase();
method public int getConfigInt(int);
method public String getConfigString(int);
@@ -14106,6 +13716,7 @@
public class ImsRegistrationImplBase {
ctor public ImsRegistrationImplBase();
+ ctor public ImsRegistrationImplBase(@NonNull java.util.concurrent.Executor);
method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
method public final void onRegistered(int);
method public final void onRegistered(@NonNull android.telephony.ims.ImsRegistrationAttributes);
@@ -14116,11 +13727,6 @@
method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String);
method public void triggerSipDelegateDeregistration();
method public void updateSipDelegateRegistration();
- field public static final int REGISTRATION_TECH_CROSS_SIM = 2; // 0x2
- field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
- field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
- field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
- field public static final int REGISTRATION_TECH_NR = 3; // 0x3
}
public class ImsSmsImplBase {
@@ -14218,6 +13824,7 @@
}
public class SipTransportImplBase {
+ ctor public SipTransportImplBase();
ctor public SipTransportImplBase(@NonNull java.util.concurrent.Executor);
method public void createSipDelegate(int, @NonNull android.telephony.ims.DelegateRequest, @NonNull android.telephony.ims.DelegateStateCallback, @NonNull android.telephony.ims.DelegateMessageCallback);
method public void destroySipDelegate(@NonNull android.telephony.ims.stub.SipDelegate, int);
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 9a8a493..327bfef 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -68,14 +68,6 @@
}
-package android.bluetooth {
-
- public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
- method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
- }
-
-}
-
package android.content {
public class Intent implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index d0e659b..ae72657 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -675,14 +675,6 @@
}
-package android.bluetooth {
-
- public final class BluetoothClass implements android.os.Parcelable {
- method public int getClassOfDevice();
- }
-
-}
-
package android.content {
public final class AttributionSource implements android.os.Parcelable {
@@ -1715,8 +1707,11 @@
public final class Parcel {
method public boolean allowSquashing();
+ method public int getFlags();
method public int readExceptionCode();
method public void restoreAllowSquashing(boolean);
+ field public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1; // 0x1
+ field public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 2; // 0x2
}
public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
@@ -2201,8 +2196,8 @@
}
public class KeyStoreException extends java.lang.Exception {
- ctor public KeyStoreException(int, String);
method public int getErrorCode();
+ method public static boolean hasFailureInfoForError(int);
}
}
@@ -2505,7 +2500,6 @@
method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 343830a..7787963 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -33,6 +33,11 @@
srcs: ["android/tracing/ITracingServiceProxy.aidl"],
}
+filegroup {
+ name: "TraceReportParams.aidl",
+ srcs: ["android/tracing/TraceReportParams.aidl"],
+}
+
// These are subset of framework-core-sources that are needed by the
// android.test.mock library. The implementation of android.test.mock references
// private members of various components to allow mocking of classes that cannot
@@ -144,7 +149,6 @@
filegroup {
name: "framework-services-net-module-wifi-shared-srcs",
srcs: [
- "android/net/DhcpResults.java",
"android/util/LocalLog.java",
],
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3b0a5f3..6d7835f 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -97,6 +97,7 @@
import android.media.MediaServiceManager;
import android.net.ConnectivityManager;
import android.net.Proxy;
+import android.net.TrafficStats;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@@ -6663,6 +6664,13 @@
NetworkSecurityConfigProvider.install(appContext);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ // For backward compatibility, TrafficStats needs static access to the application context.
+ // But for isolated apps which cannot access network related services, service discovery
+ // is restricted. Hence, calling this would result in NPE.
+ if (!Process.isIsolated()) {
+ TrafficStats.init(appContext);
+ }
+
// Continue loading instrumentation.
if (ii != null) {
initInstrumentation(ii, data, appContext);
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index 6261950..877e7d3 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -119,7 +119,7 @@
for (int i = mExitTransitionCoordinators.size() - 1; i >= 0; i--) {
WeakReference<ExitTransitionCoordinator> oldRef
= mExitTransitionCoordinators.valueAt(i);
- if (oldRef.get() == null) {
+ if (oldRef.refersTo(null)) {
mExitTransitionCoordinators.removeAt(i);
}
}
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 198c33e..ab82398 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -678,8 +678,7 @@
int refCount = mResourceImpls.size();
for (int i = 0; i < refCount; i++) {
WeakReference<ResourcesImpl> weakImplRef = mResourceImpls.valueAt(i);
- ResourcesImpl impl = weakImplRef != null ? weakImplRef.get() : null;
- if (resourceImpl == impl) {
+ if (weakImplRef != null && weakImplRef.refersTo(resourceImpl)) {
return mResourceImpls.keyAt(i);
}
}
@@ -1671,7 +1670,7 @@
for (int i = mResourceImpls.size() - 1; i >= 0; i--) {
final ResourcesKey key = mResourceImpls.keyAt(i);
final WeakReference<ResourcesImpl> impl = mResourceImpls.valueAt(i);
- if (impl == null || impl.get() == null
+ if (impl == null || impl.refersTo(null)
|| !ArrayUtils.contains(key.mLoaders, loader)) {
continue;
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 6cfa39c..ab64596 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1452,18 +1452,27 @@
mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
- boolean ok = false;
+ final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid));
try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
- // The 'close()' is the trigger for any server-side image manipulation,
- // so we must do that before waiting for completion.
- fos.close();
- completion.waitForCompletion();
+ // If the stream can't be decoded, treat it as an invalid input.
+ if (tmp != null) {
+ fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+ // The 'close()' is the trigger for any server-side image manipulation,
+ // so we must do that before waiting for completion.
+ fos.close();
+ completion.waitForCompletion();
+ } else {
+ throw new IllegalArgumentException(
+ "Resource 0x" + Integer.toHexString(resid) + " is invalid");
+ }
} finally {
// Might be redundant but completion shouldn't wait unless the write
// succeeded; this is a fallback if it threw past the close+wait.
IoUtils.closeQuietly(fos);
+ if (tmp != null) {
+ tmp.recycle();
+ }
}
}
} catch (RemoteException e) {
@@ -1705,13 +1714,22 @@
result, which, completion, mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
+ final Bitmap tmp = BitmapFactory.decodeStream(bitmapData);
try {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- copyStreamToWallpaperFile(bitmapData, fos);
- fos.close();
- completion.waitForCompletion();
+ // If the stream can't be decoded, treat it as an invalid input.
+ if (tmp != null) {
+ fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
+ fos.close();
+ completion.waitForCompletion();
+ } else {
+ throw new IllegalArgumentException("InputStream is invalid");
+ }
} finally {
IoUtils.closeQuietly(fos);
+ if (tmp != null) {
+ tmp.recycle();
+ }
}
}
} catch (RemoteException e) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0fe80c4..3840f76 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10177,6 +10177,9 @@
* On fully-managed devices this method is unsupported because all traffic is considered
* work traffic.
*
+ * <p> This method enables preferential network service with a default configuration.
+ * To fine-tune the configuration, use {@link #setPreferentialNetworkServiceConfig) instead.
+ *
* <p>This method can only be called by the profile owner of a managed profile.
* @param enabled whether preferential network service should be enabled.
* @throws SecurityException if the caller is not the profile owner.
@@ -10215,6 +10218,56 @@
}
/**
+ * Sets preferential network configuration on the work profile.
+ * {@see PreferentialNetworkServiceConfig}
+ *
+ * An example of a supported preferential network service is the Enterprise
+ * slice on 5G networks.
+ *
+ * By default, preferential network service is disabled on the work profile on supported
+ * carriers and devices. Admins can explicitly enable it with this API.
+ * On fully-managed devices this method is unsupported because all traffic is considered
+ * work traffic.
+ *
+ * <p>This method can only be called by the profile owner of a managed profile.
+ * @param preferentialNetworkServiceConfig preferential network configuration.
+ * @throws SecurityException if the caller is not the profile owner.
+ **/
+ public void setPreferentialNetworkServiceConfig(
+ @NonNull PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) {
+ throwIfParentInstance("setPreferentialNetworkServiceConfig");
+ if (mService == null) {
+ return;
+ }
+ try {
+ mService.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfig);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get preferential network configuration
+ * {@see PreferentialNetworkServiceConfig}
+ *
+ * <p>This method can be called by the profile owner of a managed profile.
+ *
+ * @return preferential network configuration.
+ * @throws SecurityException if the caller is not the profile owner.
+ */
+ public @NonNull PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig() {
+ throwIfParentInstance("getPreferentialNetworkServiceConfig");
+ if (mService == null) {
+ return PreferentialNetworkServiceConfig.DEFAULT;
+ }
+ try {
+ return mService.getPreferentialNetworkServiceConfig();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* This method is mostly deprecated.
* Most of the settings that still have an effect have dedicated setter methods or user
* restrictions. See individual settings for details.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d287437..c78a5a0 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -21,6 +21,7 @@
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.app.admin.ParcelableGranteeMap;
+import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.StartInstallingUpdateCallback;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
@@ -278,6 +279,10 @@
void setPreferentialNetworkServiceEnabled(in boolean enabled);
boolean isPreferentialNetworkServiceEnabled(int userHandle);
+ void setPreferentialNetworkServiceConfig(
+ in PreferentialNetworkServiceConfig preferentialNetworkServiceConfig);
+ PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig();
+
void setLockTaskPackages(in ComponentName who, in String[] packages);
String[] getLockTaskPackages(in ComponentName who);
boolean isLockTaskPermitted(in String pkg);
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl b/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl
new file mode 100644
index 0000000..6b6ee7d
--- /dev/null
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2022, 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 android.app.admin;
+
+parcelable PreferentialNetworkServiceConfig;
\ No newline at end of file
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
new file mode 100644
index 0000000..2849139
--- /dev/null
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2022 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 android.app.admin;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Network configuration to be set for the user profile
+ * {@see DevicePolicyManager#setPreferentialNetworkServiceConfig}.
+ */
+public final class PreferentialNetworkServiceConfig implements Parcelable {
+ final boolean mIsEnabled;
+ final int mNetworkId;
+ final boolean mAllowFallbackToDefaultConnection;
+ final int[] mIncludedUids;
+ final int[] mExcludedUids;
+
+ /** @hide */
+ public static final PreferentialNetworkServiceConfig DEFAULT =
+ (new PreferentialNetworkServiceConfig.Builder()).build();
+
+ /**
+ * Preferential network identifier 1.
+ */
+ public static final int PREFERENTIAL_NETWORK_ID_1 = 1;
+
+ /**
+ * Preferential network identifier 2.
+ */
+ public static final int PREFERENTIAL_NETWORK_ID_2 = 2;
+
+ /**
+ * Preferential network identifier 3.
+ */
+ public static final int PREFERENTIAL_NETWORK_ID_3 = 3;
+
+ /**
+ * Preferential network identifier 4.
+ */
+ public static final int PREFERENTIAL_NETWORK_ID_4 = 4;
+
+ /**
+ * Preferential network identifier 5.
+ */
+ public static final int PREFERENTIAL_NETWORK_ID_5 = 5;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "PREFERENTIAL_NETWORK_ID_" }, value = {
+ PREFERENTIAL_NETWORK_ID_1,
+ PREFERENTIAL_NETWORK_ID_2,
+ PREFERENTIAL_NETWORK_ID_3,
+ PREFERENTIAL_NETWORK_ID_4,
+ PREFERENTIAL_NETWORK_ID_5,
+ })
+
+ public @interface PreferentialNetworkPreferenceId {
+ }
+
+ private PreferentialNetworkServiceConfig(boolean isEnabled,
+ boolean allowFallbackToDefaultConnection, int[] includedUids,
+ int[] excludedUids, @PreferentialNetworkPreferenceId int networkId) {
+ mIsEnabled = isEnabled;
+ mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
+ mIncludedUids = includedUids;
+ mExcludedUids = excludedUids;
+ mNetworkId = networkId;
+ }
+
+ private PreferentialNetworkServiceConfig(Parcel in) {
+ mIsEnabled = in.readBoolean();
+ mAllowFallbackToDefaultConnection = in.readBoolean();
+ mNetworkId = in.readInt();
+ mIncludedUids = in.createIntArray();
+ mExcludedUids = in.createIntArray();
+ }
+
+ /**
+ * Is the preferential network enabled.
+ * @return true if enabled else false
+ */
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
+ /**
+ * is fallback to default network allowed. This boolean configures whether default connection
+ * (default internet or wifi) should be used or not if a preferential network service
+ * connection is not available.
+ * @return true if fallback is allowed, else false.
+ */
+ public boolean isFallbackToDefaultConnectionAllowed() {
+ return mAllowFallbackToDefaultConnection;
+ }
+
+ /**
+ * Get the array of uids that are applicable for the profile preference.
+ *
+ * {@see #getExcludedUids()}
+ * Included UIDs and Excluded UIDs can't both be non-empty.
+ * if both are empty, it means this request applies to all uids in the user profile.
+ * if included is not empty, then only included UIDs are applied.
+ * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+ * @return Array of uids applicable for the profile preference.
+ * Empty array would mean that this request applies to all uids in the profile.
+ */
+ public @NonNull int[] getIncludedUids() {
+ return mIncludedUids;
+ }
+
+ /**
+ * Get the array of uids that are excluded for the profile preference.
+ *
+ * {@see #getIncludedUids()}
+ * Included UIDs and Excluded UIDs can't both be non-empty.
+ * if both are empty, it means this request applies to all uids in the user profile.
+ * if included is not empty, then only included UIDs are applied.
+ * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+ * @return Array of uids that are excluded for the profile preference.
+ * Empty array would mean that this request applies to all uids in the profile.
+ */
+ public @NonNull int[] getExcludedUids() {
+ return mExcludedUids;
+ }
+
+ /**
+ * @return preference enterprise identifier.
+ * valid values starts from
+ * {@link #PREFERENTIAL_NETWORK_ID_1} to {@link #PREFERENTIAL_NETWORK_ID_5}.
+ * preference identifier is applicable only if preference network service is enabled
+ *
+ */
+ public @PreferentialNetworkPreferenceId int getNetworkId() {
+ return mNetworkId;
+ }
+
+ @Override
+ public String toString() {
+ return "PreferentialNetworkServiceConfig{"
+ + "mIsEnabled=" + isEnabled()
+ + "mAllowFallbackToDefaultConnection=" + isFallbackToDefaultConnectionAllowed()
+ + "mIncludedUids=" + mIncludedUids.toString()
+ + "mExcludedUids=" + mExcludedUids.toString()
+ + "mNetworkId=" + mNetworkId
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ final PreferentialNetworkServiceConfig that = (PreferentialNetworkServiceConfig) o;
+ return mIsEnabled == that.mIsEnabled
+ && mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection
+ && mNetworkId == that.mNetworkId
+ && Objects.equals(mIncludedUids, that.mIncludedUids)
+ && Objects.equals(mExcludedUids, that.mExcludedUids);
+ }
+
+ @Override
+ public int hashCode() {
+ return ((Objects.hashCode(mIsEnabled) * 17)
+ + (Objects.hashCode(mAllowFallbackToDefaultConnection) * 19)
+ + (Objects.hashCode(mIncludedUids) * 23)
+ + (Objects.hashCode(mExcludedUids) * 29)
+ + mNetworkId * 31);
+ }
+
+ /**
+ * Builder used to create {@link PreferentialNetworkServiceConfig} objects.
+ * Specify the preferred Network preference
+ */
+ public static final class Builder {
+ boolean mIsEnabled = false;
+ int mNetworkId = 0;
+ boolean mAllowFallbackToDefaultConnection = true;
+ int[] mIncludedUids = new int[0];
+ int[] mExcludedUids = new int[0];
+
+ /**
+ * Constructs an empty Builder with preferential network disabled by default.
+ */
+ public Builder() {}
+
+ /**
+ * Set the preferential network service enabled state.
+ * Default value is false.
+ * @param isEnabled the desired network preference to use, true to enable else false
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public PreferentialNetworkServiceConfig.Builder setEnabled(boolean isEnabled) {
+ mIsEnabled = isEnabled;
+ return this;
+ }
+
+ /**
+ * Set whether the default connection should be used as fallback.
+ * This boolean configures whether the default connection (default internet or wifi)
+ * should be used if a preferential network service connection is not available.
+ * Default value is true
+ * @param allowFallbackToDefaultConnection true if fallback is allowed else false
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ @SuppressLint("MissingGetterMatchingBuilder")
+ public PreferentialNetworkServiceConfig.Builder setFallbackToDefaultConnectionAllowed(
+ boolean allowFallbackToDefaultConnection) {
+ mAllowFallbackToDefaultConnection = allowFallbackToDefaultConnection;
+ return this;
+ }
+
+ /**
+ * Set the array of uids whose network access will go through this preferential
+ * network service.
+ * {@see #setExcludedUids(int[])}
+ * Included UIDs and Excluded UIDs can't both be non-empty.
+ * if both are empty, it means this request applies to all uids in the user profile.
+ * if included is not empty, then only included UIDs are applied.
+ * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+ * @param uids array of included uids
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public PreferentialNetworkServiceConfig.Builder setIncludedUids(
+ @NonNull int[] uids) {
+ Objects.requireNonNull(uids);
+ mIncludedUids = uids;
+ return this;
+ }
+
+ /**
+ * Set the array of uids who are not allowed through this preferential
+ * network service.
+ * {@see #setIncludedUids(int[])}
+ * Included UIDs and Excluded UIDs can't both be non-empty.
+ * if both are empty, it means this request applies to all uids in the user profile.
+ * if included is not empty, then only included UIDs are applied.
+ * if excluded is not empty, then it is all uids in the user profile except these UIDs.
+ * @param uids array of excluded uids
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public PreferentialNetworkServiceConfig.Builder setExcludedUids(
+ @NonNull int[] uids) {
+ Objects.requireNonNull(uids);
+ mExcludedUids = uids;
+ return this;
+ }
+
+ /**
+ * Returns an instance of {@link PreferentialNetworkServiceConfig} created from the
+ * fields set on this builder.
+ */
+ @NonNull
+ public PreferentialNetworkServiceConfig build() {
+ if (mIncludedUids.length > 0 && mExcludedUids.length > 0) {
+ throw new IllegalStateException("Both includedUids and excludedUids "
+ + "cannot be nonempty");
+ }
+ return new PreferentialNetworkServiceConfig(mIsEnabled,
+ mAllowFallbackToDefaultConnection, mIncludedUids, mExcludedUids, mNetworkId);
+ }
+
+ /**
+ * Set the preferential network identifier.
+ * Valid values starts from {@link #PREFERENTIAL_NETWORK_ID_1} to
+ * {@link #PREFERENTIAL_NETWORK_ID_5}.
+ * preference identifier is applicable only if preferential network service is enabled.
+ * @param preferenceId preference Id
+ * @return The builder to facilitate chaining.
+ */
+ @NonNull
+ public PreferentialNetworkServiceConfig.Builder setNetworkId(
+ @PreferentialNetworkPreferenceId int preferenceId) {
+ if ((preferenceId < PREFERENTIAL_NETWORK_ID_1)
+ || (preferenceId > PREFERENTIAL_NETWORK_ID_5)) {
+ throw new IllegalArgumentException("Invalid preference identifier");
+ }
+ mNetworkId = preferenceId;
+ return this;
+ }
+ }
+
+ @Override
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ dest.writeBoolean(mIsEnabled);
+ dest.writeBoolean(mAllowFallbackToDefaultConnection);
+ dest.writeInt(mNetworkId);
+ dest.writeIntArray(mIncludedUids);
+ dest.writeIntArray(mExcludedUids);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Creator<PreferentialNetworkServiceConfig> CREATOR =
+ new Creator<PreferentialNetworkServiceConfig>() {
+ @Override
+ public PreferentialNetworkServiceConfig[] newArray(int size) {
+ return new PreferentialNetworkServiceConfig[size];
+ }
+
+ @Override
+ public PreferentialNetworkServiceConfig createFromParcel(
+ @NonNull android.os.Parcel in) {
+ return new PreferentialNetworkServiceConfig(in);
+ }
+ };
+}
diff --git a/core/java/android/app/trust/OWNERS b/core/java/android/app/trust/OWNERS
new file mode 100644
index 0000000..e2c6ce1
--- /dev/null
+++ b/core/java/android/app/trust/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/trust/OWNERS
diff --git a/core/java/android/app/wallpapereffectsgeneration/OWNERS b/core/java/android/app/wallpapereffectsgeneration/OWNERS
new file mode 100644
index 0000000..2bc0154
--- /dev/null
+++ b/core/java/android/app/wallpapereffectsgeneration/OWNERS
@@ -0,0 +1,5 @@
+susharon@google.com
+shanh@google.com
+huiwu@google.com
+srazdan@google.com
+
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 98e124d..30850e3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5778,6 +5778,17 @@
public static final String DISPLAY_HASH_SERVICE = "display_hash";
/**
+ * Use with {@link #getSystemService(String)} to retrieve a
+ * {@link android.nearby.NearbyManager} to discover nearby devices.
+ *
+ * @see #getSystemService(String)
+ * @see android.nearby.NearbyManager
+ * @hide
+ */
+ @SystemApi
+ public static final String NEARBY_SERVICE = "nearby";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/res/ColorStateList.java b/core/java/android/content/res/ColorStateList.java
index 5b727cc..5031faa 100644
--- a/core/java/android/content/res/ColorStateList.java
+++ b/core/java/android/content/res/ColorStateList.java
@@ -198,7 +198,7 @@
// Prune the cache before adding new items.
final int N = sCache.size();
for (int i = N - 1; i >= 0; i--) {
- if (sCache.valueAt(i).get() == null) {
+ if (sCache.valueAt(i).refersTo(null)) {
sCache.removeAt(i);
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 12e41e2..932cc8e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -2011,7 +2011,7 @@
// Clean up references to garbage collected themes
if (mThemeRefs.size() > mThemeRefsNextFlushSize) {
- mThemeRefs.removeIf(ref -> ref.get() == null);
+ mThemeRefs.removeIf(ref -> ref.refersTo(null));
mThemeRefsNextFlushSize = Math.max(MIN_THEME_REFS_FLUSH_SIZE,
2 * mThemeRefs.size());
}
diff --git a/core/java/android/content/res/loader/ResourcesLoader.java b/core/java/android/content/res/loader/ResourcesLoader.java
index c308400..cf6e166 100644
--- a/core/java/android/content/res/loader/ResourcesLoader.java
+++ b/core/java/android/content/res/loader/ResourcesLoader.java
@@ -257,7 +257,7 @@
for (int i = mChangeCallbacks.size() - 1; i >= 0; i--) {
final WeakReference<Object> key = mChangeCallbacks.keyAt(i);
- if (key.get() == null) {
+ if (key.refersTo(null)) {
mChangeCallbacks.removeAt(i);
} else {
uniqueCallbacks.add(mChangeCallbacks.valueAt(i));
diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS
index 4143bfc..ce5cf67 100644
--- a/core/java/android/hardware/OWNERS
+++ b/core/java/android/hardware/OWNERS
@@ -1,3 +1,9 @@
+# Generic
+etalvala@google.com
+jreck@google.com
+michaelwr@google.com
+sumir@google.com
+
# Camera
per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,zhijunhe@google.com,jchowdhary@google.com
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index 0c21746..066de11 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -17,6 +17,8 @@
public abstract class HdmiClient {
private static final String TAG = "HdmiClient";
+ private static final int UNKNOWN_VENDOR_ID = 0xFFFFFF;
+
/* package */ final IHdmiControlService mService;
private IHdmiVendorCommandListener mIHdmiVendorCommandListener;
@@ -94,11 +96,25 @@
}
/**
- * Sets a listener used to receive incoming vendor-specific command.
+ * Sets a listener used to receive incoming vendor-specific command. This listener will only
+ * receive {@code <Vendor Command>} but will not receive any {@code <Vendor Command with ID>}
+ * messages.
*
* @param listener listener object
*/
public void setVendorCommandListener(@NonNull VendorCommandListener listener) {
+ // Set the vendor ID to INVALID_VENDOR_ID.
+ setVendorCommandListener(listener, UNKNOWN_VENDOR_ID);
+ }
+
+ /**
+ * Sets a listener used to receive incoming vendor-specific command.
+ *
+ * @param listener listener object
+ * @param vendorId The listener is interested in {@code <Vendor Command with ID>} received with
+ * this vendorId and all {@code <Vendor Command>} messages.
+ */
+ public void setVendorCommandListener(@NonNull VendorCommandListener listener, int vendorId) {
if (listener == null) {
throw new IllegalArgumentException("listener cannot be null");
}
@@ -107,7 +123,7 @@
}
try {
IHdmiVendorCommandListener wrappedListener = getListenerWrapper(listener);
- mService.addVendorCommandListener(wrappedListener, getDeviceType());
+ mService.addVendorCommandListener(wrappedListener, vendorId);
mIHdmiVendorCommandListener = wrappedListener;
} catch (RemoteException e) {
Log.e(TAG, "failed to set vendor command listener: ", e);
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 9a9e945..45b0689 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -221,8 +221,8 @@
}
@Override
- public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
- HdmiControlServiceWrapper.this.addVendorCommandListener(listener, deviceType);
+ public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {
+ HdmiControlServiceWrapper.this.addVendorCommandListener(listener, vendorId);
}
@Override
@@ -471,7 +471,7 @@
boolean hasVendorId) {}
/** @hide */
- public void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {}
+ public void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {}
/** @hide */
public void sendStandby(int deviceType, int deviceId) {}
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 7f0e53e..48177e1 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -76,7 +76,7 @@
void askRemoteDeviceToBecomeActiveSource(int physicalAddress);
void sendVendorCommand(int deviceType, int targetAddress, in byte[] params,
boolean hasVendorId);
- void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType);
+ void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId);
void sendStandby(int deviceType, int deviceId);
void setHdmiRecordListener(IHdmiRecordListener callback);
void startOneTouchRecord(int recorderAddress, in byte[] recordSource);
diff --git a/core/java/android/net/DhcpResults.aidl b/core/java/android/net/DhcpResults.aidl
deleted file mode 100644
index f4db3c3..0000000
--- a/core/java/android/net/DhcpResults.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * Copyright (c) 2012, 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 android.net;
-
-parcelable DhcpResults;
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
deleted file mode 100644
index 82ba156..0000000
--- a/core/java/android/net/DhcpResults.java
+++ /dev/null
@@ -1,330 +0,0 @@
-/*
- * Copyright (C) 2012 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 android.net;
-
-import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.os.Build;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.net.module.util.InetAddressUtils;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A simple object for retrieving the results of a DHCP request.
- * Optimized (attempted) for that jni interface
- * TODO: remove this class and replace with other existing constructs
- * @hide
- */
-public final class DhcpResults implements Parcelable {
- private static final String TAG = "DhcpResults";
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public LinkAddress ipAddress;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public InetAddress gateway;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public final ArrayList<InetAddress> dnsServers = new ArrayList<>();
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public String domains;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public Inet4Address serverAddress;
-
- /** Vendor specific information (from RFC 2132). */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public String vendorInfo;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int leaseDuration;
-
- /** Link MTU option. 0 means unset. */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int mtu;
-
- public String serverHostName;
-
- @Nullable
- public String captivePortalApiUrl;
-
- public DhcpResults() {
- super();
- }
-
- /**
- * Create a {@link StaticIpConfiguration} based on the DhcpResults.
- */
- public StaticIpConfiguration toStaticIpConfiguration() {
- return new StaticIpConfiguration.Builder()
- .setIpAddress(ipAddress)
- .setGateway(gateway)
- .setDnsServers(dnsServers)
- .setDomains(domains)
- .build();
- }
-
- public DhcpResults(StaticIpConfiguration source) {
- if (source != null) {
- ipAddress = source.getIpAddress();
- gateway = source.getGateway();
- dnsServers.addAll(source.getDnsServers());
- domains = source.getDomains();
- }
- }
-
- /** copy constructor */
- public DhcpResults(DhcpResults source) {
- this(source == null ? null : source.toStaticIpConfiguration());
- if (source != null) {
- serverAddress = source.serverAddress;
- vendorInfo = source.vendorInfo;
- leaseDuration = source.leaseDuration;
- mtu = source.mtu;
- serverHostName = source.serverHostName;
- captivePortalApiUrl = source.captivePortalApiUrl;
- }
- }
-
- /**
- * @see StaticIpConfiguration#getRoutes(String)
- * @hide
- */
- public List<RouteInfo> getRoutes(String iface) {
- return toStaticIpConfiguration().getRoutes(iface);
- }
-
- /**
- * Test if this DHCP lease includes vendor hint that network link is
- * metered, and sensitive to heavy data transfers.
- */
- public boolean hasMeteredHint() {
- if (vendorInfo != null) {
- return vendorInfo.contains("ANDROID_METERED");
- } else {
- return false;
- }
- }
-
- public void clear() {
- ipAddress = null;
- gateway = null;
- dnsServers.clear();
- domains = null;
- serverAddress = null;
- vendorInfo = null;
- leaseDuration = 0;
- mtu = 0;
- serverHostName = null;
- captivePortalApiUrl = null;
- }
-
- @Override
- public String toString() {
- StringBuffer str = new StringBuffer(super.toString());
-
- str.append(" DHCP server ").append(serverAddress);
- str.append(" Vendor info ").append(vendorInfo);
- str.append(" lease ").append(leaseDuration).append(" seconds");
- if (mtu != 0) str.append(" MTU ").append(mtu);
- str.append(" Servername ").append(serverHostName);
- if (captivePortalApiUrl != null) {
- str.append(" CaptivePortalApiUrl ").append(captivePortalApiUrl);
- }
-
- return str.toString();
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) return true;
-
- if (!(obj instanceof DhcpResults)) return false;
-
- DhcpResults target = (DhcpResults)obj;
-
- return toStaticIpConfiguration().equals(target.toStaticIpConfiguration())
- && Objects.equals(serverAddress, target.serverAddress)
- && Objects.equals(vendorInfo, target.vendorInfo)
- && Objects.equals(serverHostName, target.serverHostName)
- && leaseDuration == target.leaseDuration
- && mtu == target.mtu
- && Objects.equals(captivePortalApiUrl, target.captivePortalApiUrl);
- }
-
- /**
- * Implement the Parcelable interface
- */
- public static final @android.annotation.NonNull Creator<DhcpResults> CREATOR =
- new Creator<DhcpResults>() {
- public DhcpResults createFromParcel(Parcel in) {
- return readFromParcel(in);
- }
-
- public DhcpResults[] newArray(int size) {
- return new DhcpResults[size];
- }
- };
-
- /** Implement the Parcelable interface */
- public void writeToParcel(Parcel dest, int flags) {
- toStaticIpConfiguration().writeToParcel(dest, flags);
- dest.writeInt(leaseDuration);
- dest.writeInt(mtu);
- InetAddressUtils.parcelInetAddress(dest, serverAddress, flags);
- dest.writeString(vendorInfo);
- dest.writeString(serverHostName);
- dest.writeString(captivePortalApiUrl);
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- private static DhcpResults readFromParcel(Parcel in) {
- final StaticIpConfiguration s = StaticIpConfiguration.CREATOR.createFromParcel(in);
- final DhcpResults dhcpResults = new DhcpResults(s);
- dhcpResults.leaseDuration = in.readInt();
- dhcpResults.mtu = in.readInt();
- dhcpResults.serverAddress = (Inet4Address) InetAddressUtils.unparcelInetAddress(in);
- dhcpResults.vendorInfo = in.readString();
- dhcpResults.serverHostName = in.readString();
- dhcpResults.captivePortalApiUrl = in.readString();
- return dhcpResults;
- }
-
- // Utils for jni population - false on success
- // Not part of the superclass because they're only used by the JNI iterface to the DHCP daemon.
- public boolean setIpAddress(String addrString, int prefixLength) {
- try {
- Inet4Address addr = (Inet4Address) InetAddresses.parseNumericAddress(addrString);
- ipAddress = new LinkAddress(addr, prefixLength);
- } catch (IllegalArgumentException|ClassCastException e) {
- Log.e(TAG, "setIpAddress failed with addrString " + addrString + "/" + prefixLength);
- return true;
- }
- return false;
- }
-
- public boolean setGateway(String addrString) {
- try {
- gateway = InetAddresses.parseNumericAddress(addrString);
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "setGateway failed with addrString " + addrString);
- return true;
- }
- return false;
- }
-
- public boolean addDns(String addrString) {
- if (TextUtils.isEmpty(addrString) == false) {
- try {
- dnsServers.add(InetAddresses.parseNumericAddress(addrString));
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "addDns failed with addrString " + addrString);
- return true;
- }
- }
- return false;
- }
-
- public LinkAddress getIpAddress() {
- return ipAddress;
- }
-
- public void setIpAddress(LinkAddress ipAddress) {
- this.ipAddress = ipAddress;
- }
-
- public InetAddress getGateway() {
- return gateway;
- }
-
- public void setGateway(InetAddress gateway) {
- this.gateway = gateway;
- }
-
- public List<InetAddress> getDnsServers() {
- return dnsServers;
- }
-
- /**
- * Add a DNS server to this configuration.
- */
- public void addDnsServer(InetAddress server) {
- dnsServers.add(server);
- }
-
- public String getDomains() {
- return domains;
- }
-
- public void setDomains(String domains) {
- this.domains = domains;
- }
-
- public Inet4Address getServerAddress() {
- return serverAddress;
- }
-
- public void setServerAddress(Inet4Address addr) {
- serverAddress = addr;
- }
-
- public int getLeaseDuration() {
- return leaseDuration;
- }
-
- public void setLeaseDuration(int duration) {
- leaseDuration = duration;
- }
-
- public String getVendorInfo() {
- return vendorInfo;
- }
-
- public void setVendorInfo(String info) {
- vendorInfo = info;
- }
-
- public int getMtu() {
- return mtu;
- }
-
- public void setMtu(int mtu) {
- this.mtu = mtu;
- }
-
- public String getCaptivePortalApiUrl() {
- return captivePortalApiUrl;
- }
-
- public void setCaptivePortalApiUrl(String url) {
- captivePortalApiUrl = url;
- }
-}
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 147138e..6284f56 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -70,7 +70,7 @@
int getMultipathPreference(in Network network);
SubscriptionPlan getSubscriptionPlan(in NetworkTemplate template);
- void onStatsProviderWarningOrLimitReached();
+ void notifyStatsProviderWarningOrLimitReached();
SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
String getSubscriptionPlansOwner(int subId);
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index 271efe4..070efa3 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -38,7 +38,7 @@
/** VpnManager APIs */
boolean provisionVpnProfile(in VpnProfile profile, String packageName);
void deleteVpnProfile(String packageName);
- void startVpnProfile(String packageName);
+ String startVpnProfile(String packageName);
void stopVpnProfile(String packageName);
/** Always-on VPN APIs */
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 5554137..ec752fd 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -25,6 +25,12 @@
import static android.net.IpSecAlgorithm.AUTH_HMAC_SHA512;
import static android.net.IpSecAlgorithm.CRYPT_AES_CBC;
import static android.net.IpSecAlgorithm.CRYPT_AES_CTR;
+import static android.net.eap.EapSessionConfig.EapMsChapV2Config;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignLocalConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthDigitalSignRemoteConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthEapConfig;
+import static android.net.ipsec.ike.IkeSessionParams.IkeAuthPskConfig;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.util.Preconditions.checkStringNotEmpty;
@@ -34,6 +40,14 @@
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.content.pm.PackageManager;
+import android.net.ipsec.ike.IkeFqdnIdentification;
+import android.net.ipsec.ike.IkeIdentification;
+import android.net.ipsec.ike.IkeIpv4AddrIdentification;
+import android.net.ipsec.ike.IkeIpv6AddrIdentification;
+import android.net.ipsec.ike.IkeKeyIdIdentification;
+import android.net.ipsec.ike.IkeRfc822AddrIdentification;
+import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.IkeTunnelConnectionParams;
import android.security.Credentials;
import android.util.Log;
@@ -145,8 +159,9 @@
boolean isMetered,
int maxMtu,
boolean restrictToTestNetworks,
- boolean excludeLocalRoutes) {
- super(type, excludeLocalRoutes);
+ boolean excludeLocalRoutes,
+ boolean requiresInternetValidation) {
+ super(type, excludeLocalRoutes, requiresInternetValidation);
checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
checkNotNull(userIdentity, MISSING_PARAM_MSG_TMPL, "User Identity");
@@ -167,7 +182,7 @@
mAllowedAlgorithms = Collections.unmodifiableList(new ArrayList<>(allowedAlgorithms));
if (excludeLocalRoutes && !isBypassable) {
throw new IllegalArgumentException(
- "Vpn should be byassable if excludeLocalRoutes is set");
+ "Vpn must be bypassable if excludeLocalRoutes is set");
}
mIsBypassable = isBypassable;
@@ -224,7 +239,7 @@
* that provides Authentication, and one that provides Encryption. Authenticated Encryption with
* Associated Data (AEAD) algorithms are counted as providing Authentication and Encryption.
*
- * @param allowedAlgorithms The list to be validated
+ * @param algorithmNames The list to be validated
*/
private static void validateAllowedAlgorithms(@NonNull List<String> algorithmNames) {
// First, make sure no insecure algorithms were proposed.
@@ -386,7 +401,9 @@
mIsBypassable,
mIsMetered,
mMaxMtu,
- mIsRestrictedToTestNetworks);
+ mIsRestrictedToTestNetworks,
+ mExcludeLocalRoutes,
+ mRequiresInternetValidation);
}
@Override
@@ -411,7 +428,8 @@
&& mIsMetered == other.mIsMetered
&& mMaxMtu == other.mMaxMtu
&& mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
- && mExcludeLocalRoutes == other.mExcludeLocalRoutes;
+ && mExcludeLocalRoutes == other.mExcludeLocalRoutes
+ && mRequiresInternetValidation == other.mRequiresInternetValidation;
}
/**
@@ -425,7 +443,7 @@
@NonNull
public VpnProfile toVpnProfile() throws IOException, GeneralSecurityException {
final VpnProfile profile = new VpnProfile("" /* Key; value unused by IKEv2VpnProfile(s) */,
- mIsRestrictedToTestNetworks, mExcludeLocalRoutes);
+ mIsRestrictedToTestNetworks, mExcludeLocalRoutes, mRequiresInternetValidation);
profile.type = mType;
profile.server = mServerAddr;
profile.ipsecIdentifier = mUserIdentity;
@@ -530,6 +548,7 @@
Log.w(TAG, "ExcludeLocalRoutes should only be set in the bypassable VPN");
}
builder.setExcludeLocalRoutes(profile.excludeLocalRoutes && profile.isBypassable);
+ builder.setRequiresInternetValidation(profile.requiresInternetValidation);
return builder.build();
}
@@ -644,6 +663,102 @@
return Objects.requireNonNull(reference, String.format(messageTemplate, messageArgs));
}
+ private static void checkBuilderSetter(boolean constructedFromIkeTunConParams,
+ @NonNull String message) {
+ if (constructedFromIkeTunConParams) {
+ throw new IllegalArgumentException("Constructed using IkeTunnelConnectionParams "
+ + "should not set " + message);
+ }
+ }
+
+ private static int getTypeFromIkeSession(@NonNull IkeSessionParams params) {
+ final IkeAuthConfig config = params.getLocalAuthConfig();
+ if (config instanceof IkeAuthDigitalSignLocalConfig) {
+ return TYPE_IKEV2_IPSEC_RSA;
+ } else if (config instanceof IkeAuthEapConfig) {
+ return TYPE_IKEV2_IPSEC_USER_PASS;
+ } else if (config instanceof IkeAuthPskConfig) {
+ return TYPE_IKEV2_IPSEC_PSK;
+ } else {
+ throw new IllegalStateException("Invalid local IkeAuthConfig");
+ }
+ }
+
+ @Nullable
+ private static String getPasswordFromIkeSession(@NonNull IkeSessionParams params) {
+ if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
+
+ final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
+ final EapMsChapV2Config eapMsChapV2Config =
+ ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
+ return (eapMsChapV2Config != null) ? eapMsChapV2Config.getPassword() : null;
+ }
+
+ @Nullable
+ private static String getUsernameFromIkeSession(@NonNull IkeSessionParams params) {
+ if (!(params.getLocalAuthConfig() instanceof IkeAuthEapConfig)) return null;
+
+ final IkeAuthEapConfig ikeAuthEapConfig = (IkeAuthEapConfig) params.getLocalAuthConfig();
+ final EapMsChapV2Config eapMsChapV2Config =
+ ikeAuthEapConfig.getEapConfig().getEapMsChapV2Config();
+ return (eapMsChapV2Config != null) ? eapMsChapV2Config.getUsername() : null;
+ }
+
+ @Nullable
+ private static X509Certificate getUserCertFromIkeSession(@NonNull IkeSessionParams params) {
+ if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
+
+ final IkeAuthDigitalSignLocalConfig config =
+ (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
+ return config.getClientEndCertificate();
+ }
+
+ @Nullable
+ private static X509Certificate getServerRootCaCertFromIkeSession(
+ @NonNull IkeSessionParams params) {
+ if (!(params.getRemoteAuthConfig() instanceof IkeAuthDigitalSignRemoteConfig)) return null;
+
+ final IkeAuthDigitalSignRemoteConfig config =
+ (IkeAuthDigitalSignRemoteConfig) params.getRemoteAuthConfig();
+ return config.getRemoteCaCert();
+ }
+
+ @Nullable
+ private static PrivateKey getRsaPrivateKeyFromIkeSession(@NonNull IkeSessionParams params) {
+ if (!(params.getLocalAuthConfig() instanceof IkeAuthDigitalSignLocalConfig)) return null;
+
+ final IkeAuthDigitalSignLocalConfig config =
+ (IkeAuthDigitalSignLocalConfig) params.getLocalAuthConfig();
+ return config.getPrivateKey();
+ }
+
+ @Nullable
+ private static byte[] getPresharedKeyFromIkeSession(@NonNull IkeSessionParams params) {
+ if (!(params.getLocalAuthConfig() instanceof IkeAuthPskConfig)) return null;
+
+ final IkeAuthPskConfig config = (IkeAuthPskConfig) params.getLocalAuthConfig();
+ return config.getPsk();
+ }
+
+ @NonNull
+ private static String getUserIdentityFromIkeSession(@NonNull IkeSessionParams params) {
+ final IkeIdentification ident = params.getLocalIdentification();
+ // Refer to VpnIkev2Utils.parseIkeIdentification().
+ if (ident instanceof IkeKeyIdIdentification) {
+ return "@#" + new String(((IkeKeyIdIdentification) ident).keyId);
+ } else if (ident instanceof IkeRfc822AddrIdentification) {
+ return "@@" + ((IkeRfc822AddrIdentification) ident).rfc822Name;
+ } else if (ident instanceof IkeFqdnIdentification) {
+ return "@" + ((IkeFqdnIdentification) ident).fqdn;
+ } else if (ident instanceof IkeIpv4AddrIdentification) {
+ return ((IkeIpv4AddrIdentification) ident).ipv4Address.getHostAddress();
+ } else if (ident instanceof IkeIpv6AddrIdentification) {
+ return ((IkeIpv6AddrIdentification) ident).ipv6Address.getHostAddress();
+ } else {
+ throw new IllegalArgumentException("Unknown IkeIdentification to get user identity");
+ }
+ }
+
/** A incremental builder for IKEv2 VPN profiles */
public static final class Builder {
private int mType = -1;
@@ -666,11 +781,13 @@
@Nullable private ProxyInfo mProxyInfo;
@NonNull private List<String> mAllowedAlgorithms = DEFAULT_ALGORITHMS;
+ private boolean mRequiresInternetValidation = false;
private boolean mIsBypassable = false;
private boolean mIsMetered = true;
private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
private boolean mIsRestrictedToTestNetworks = false;
private boolean mExcludeLocalRoutes = false;
+ @Nullable private IkeTunnelConnectionParams mIkeTunConnParams;
/**
* Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -687,6 +804,32 @@
mUserIdentity = identity;
}
+ /**
+ * Creates a new builder from a {@link IkeTunnelConnectionParams}
+ *
+ * @param ikeTunConnParams the {@link IkeTunnelConnectionParams} contains IKEv2
+ * configurations
+ */
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+ public Builder(@NonNull IkeTunnelConnectionParams ikeTunConnParams) {
+ checkNotNull(ikeTunConnParams, MISSING_PARAM_MSG_TMPL, "ikeTunConnParams");
+
+ mIkeTunConnParams = ikeTunConnParams;
+
+ final IkeSessionParams ikeSessionParams = mIkeTunConnParams.getIkeSessionParams();
+ mServerAddr = ikeSessionParams.getServerHostname();
+
+ mType = getTypeFromIkeSession(ikeSessionParams);
+ mUserCert = getUserCertFromIkeSession(ikeSessionParams);
+ mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
+ mRsaPrivateKey = getRsaPrivateKeyFromIkeSession(ikeSessionParams);
+ mServerRootCaCert = getServerRootCaCertFromIkeSession(ikeSessionParams);
+ mUsername = getUsernameFromIkeSession(ikeSessionParams);
+ mPassword = getPasswordFromIkeSession(ikeSessionParams);
+ mPresharedKey = getPresharedKeyFromIkeSession(ikeSessionParams);
+ mUserIdentity = getUserIdentityFromIkeSession(ikeSessionParams);
+ }
+
private void resetAuthParams() {
mPresharedKey = null;
mServerRootCaCert = null;
@@ -719,6 +862,7 @@
@Nullable X509Certificate serverRootCa) {
checkNotNull(user, MISSING_PARAM_MSG_TMPL, "user");
checkNotNull(pass, MISSING_PARAM_MSG_TMPL, "pass");
+ checkBuilderSetter(mIkeTunConnParams != null, "authUsernamePassword");
// Test to make sure all auth params can be encoded safely.
if (serverRootCa != null) checkCert(serverRootCa);
@@ -755,6 +899,7 @@
@Nullable X509Certificate serverRootCa) {
checkNotNull(userCert, MISSING_PARAM_MSG_TMPL, "userCert");
checkNotNull(key, MISSING_PARAM_MSG_TMPL, "key");
+ checkBuilderSetter(mIkeTunConnParams != null, "authDigitalSignature");
// Test to make sure all auth params can be encoded safely.
checkCert(userCert);
@@ -782,6 +927,7 @@
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
public Builder setAuthPsk(@NonNull byte[] psk) {
checkNotNull(psk, MISSING_PARAM_MSG_TMPL, "psk");
+ checkBuilderSetter(mIkeTunConnParams != null, "authPsk");
resetAuthParams();
mPresharedKey = psk;
@@ -848,6 +994,30 @@
}
/**
+ * Request that this VPN undergoes Internet validation.
+ *
+ * If this is true, the platform will perform basic validation checks for Internet
+ * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+ * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+ * capability.
+ *
+ * If this is false, the platform assumes the VPN either is always capable of reaching the
+ * Internet or intends not to. In this case, the VPN network capabilities will
+ * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+ * immediately after it connects, whether it can reach public Internet destinations or not.
+ *
+ * @param requiresInternetValidation {@code true} if the framework should attempt to
+ * validate this VPN for Internet connectivity. Defaults
+ * to {@code false}.
+ */
+ @NonNull
+ @RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
+ public Builder setRequiresInternetValidation(boolean requiresInternetValidation) {
+ mRequiresInternetValidation = requiresInternetValidation;
+ return this;
+ }
+
+ /**
* Marks the VPN network as metered.
*
* <p>A VPN network is classified as metered when the user is sensitive to heavy data usage
@@ -931,8 +1101,6 @@
*
* Note that because the local traffic will always bypass the VPN,
* it is not possible to set this flag on a non-bypassable VPN.
- *
- * @hide TODO(184750836): unhide once the implementation is completed
*/
@NonNull
@RequiresFeature(PackageManager.FEATURE_IPSEC_TUNNELS)
@@ -965,7 +1133,8 @@
mIsMetered,
mMaxMtu,
mIsRestrictedToTestNetworks,
- mExcludeLocalRoutes);
+ mExcludeLocalRoutes,
+ mRequiresInternetValidation);
}
}
}
diff --git a/core/java/android/net/InternalNetworkManagementException.java b/core/java/android/net/InternalNetworkManagementException.java
deleted file mode 100644
index 7f4e403..0000000
--- a/core/java/android/net/InternalNetworkManagementException.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 android.net;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-/** @hide */
-public final class InternalNetworkManagementException
- extends RuntimeException implements Parcelable {
-
- /* @hide */
- public InternalNetworkManagementException(@NonNull final Throwable t) {
- super(t);
- }
-
- private InternalNetworkManagementException(@NonNull final Parcel source) {
- super(source.readString());
- }
-
- @Override
- public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeString(getCause().getMessage());
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @NonNull
- public static final Parcelable.Creator<InternalNetworkManagementException> CREATOR =
- new Parcelable.Creator<InternalNetworkManagementException>() {
- @Override
- public InternalNetworkManagementException[] newArray(int size) {
- return new InternalNetworkManagementException[size];
- }
-
- @Override
- public InternalNetworkManagementException createFromParcel(@NonNull Parcel source) {
- return new InternalNetworkManagementException(source);
- }
- };
-}
diff --git a/core/java/android/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java
index d1f49d2..506cbcb 100644
--- a/core/java/android/net/LocalServerSocket.java
+++ b/core/java/android/net/LocalServerSocket.java
@@ -55,7 +55,9 @@
* Create a LocalServerSocket from a file descriptor that's already
* been created and bound. listen() will be called immediately on it.
* Used for cases where file descriptors are passed in via environment
- * variables
+ * variables. The passed-in FileDescriptor is not managed by this class
+ * and must be closed by the caller. Calling {@link #close()} on a socket
+ * created by this method has no effect.
*
* @param fd bound file descriptor
* @throws IOException
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 5b38f78..b69410c 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -16,7 +16,14 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.system.ErrnoException;
+import android.system.Os;
import java.io.Closeable;
import java.io.FileDescriptor;
@@ -74,32 +81,39 @@
this.isBound = false;
}
+ private void checkConnected() {
+ try {
+ Os.getpeername(impl.getFileDescriptor());
+ } catch (ErrnoException e) {
+ throw new IllegalArgumentException("Not a connected socket", e);
+ }
+ isConnected = true;
+ isBound = true;
+ implCreated = true;
+ }
+
/**
- * Creates a LocalSocket instances using the FileDescriptor for an already-connected
- * AF_LOCAL/UNIX domain stream socket. Note: the FileDescriptor must be closed by the caller:
- * closing the LocalSocket will not close it.
+ * Creates a LocalSocket instance using the {@link FileDescriptor} for an already-connected
+ * AF_LOCAL/UNIX domain stream socket. The passed-in FileDescriptor is not managed by this class
+ * and must be closed by the caller. Calling {@link #close()} on a socket created by this
+ * method has no effect.
*
- * @hide - used by BluetoothSocket.
+ * @param fd the filedescriptor to adopt
+ *
+ * @hide
*/
- public static LocalSocket createConnectedLocalSocket(FileDescriptor fd) {
- return createConnectedLocalSocket(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
+ @SystemApi(client = MODULE_LIBRARIES)
+ public LocalSocket(@NonNull @SuppressLint("UseParcelFileDescriptor") FileDescriptor fd) {
+ this(new LocalSocketImpl(fd), SOCKET_UNKNOWN);
+ checkConnected();
}
/**
* for use with LocalServerSocket.accept()
*/
static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl) {
- return createConnectedLocalSocket(impl, SOCKET_UNKNOWN);
- }
-
- /**
- * Creates a LocalSocket from an existing LocalSocketImpl that is already connected.
- */
- private static LocalSocket createConnectedLocalSocket(LocalSocketImpl impl, int sockType) {
- LocalSocket socket = new LocalSocket(impl, sockType);
- socket.isConnected = true;
- socket.isBound = true;
- socket.implCreated = true;
+ LocalSocket socket = new LocalSocket(impl, SOCKET_UNKNOWN);
+ socket.checkConnected();
return socket;
}
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 426fc61..c936bfa 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -546,7 +546,7 @@
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
- // @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public SubscriptionPlan getSubscriptionPlan(@NonNull NetworkTemplate template) {
try {
return mService.getSubscriptionPlan(template);
@@ -565,10 +565,10 @@
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
- // @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
- public void onStatsProviderWarningOrLimitReached() {
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public void notifyStatsProviderWarningOrLimitReached() {
try {
- mService.onStatsProviderWarningOrLimitReached();
+ mService.notifyStatsProviderWarningOrLimitReached();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/net/PlatformVpnProfile.java b/core/java/android/net/PlatformVpnProfile.java
index 777a90c..8bd1c8d 100644
--- a/core/java/android/net/PlatformVpnProfile.java
+++ b/core/java/android/net/PlatformVpnProfile.java
@@ -16,10 +16,6 @@
package android.net;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_PSK;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_RSA;
-import static android.net.PlatformVpnProfile.TYPE_IKEV2_IPSEC_USER_PASS;
-
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -67,11 +63,15 @@
/** @hide */
protected final boolean mExcludeLocalRoutes;
+ /** @hide */
+ protected final boolean mRequiresInternetValidation;
/** @hide */
- PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes) {
+ PlatformVpnProfile(@PlatformVpnType int type, boolean excludeLocalRoutes,
+ boolean requiresValidation) {
mType = type;
mExcludeLocalRoutes = excludeLocalRoutes;
+ mRequiresInternetValidation = requiresValidation;
}
/** Returns the profile integer type. */
@@ -80,16 +80,30 @@
return mType;
}
-
/**
- * Returns if the local traffic is exempted from the VPN.
- *
- * @hide TODO(184750836): unhide once the implementation is completed
+ * Returns whether the local traffic is exempted from the VPN.
*/
public final boolean getExcludeLocalRoutes() {
return mExcludeLocalRoutes;
}
+ /**
+ * Returns whether this VPN should undergo Internet validation.
+ *
+ * If this is true, the platform will perform basic validation checks for Internet
+ * connectivity over this VPN. If and when they succeed, the VPN network capabilities will
+ * reflect this by gaining the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}
+ * capability.
+ *
+ * If this is false, the platform assumes the VPN either is always capable of reaching the
+ * Internet or intends not to. In this case, the VPN network capabilities will
+ * always gain the {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} capability
+ * immediately after it connects, whether it can reach public Internet destinations or not.
+ */
+ public final boolean getRequiresInternetValidation() {
+ return mRequiresInternetValidation;
+ }
+
/** Returns a type string describing the VPN profile type */
@NonNull
public final String getTypeString() {
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index 3193826..9132791 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -317,17 +317,32 @@
/**
* Request the startup of a previously provisioned VPN.
*
+ * @return A unique key corresponding to this session.
* @throws SecurityException exception if user or device settings prevent this VPN from being
- * setup, or if user consent has not been granted
+ * setup, or if user consent has not been granted
*/
- public void startProvisionedVpnProfile() {
+ @NonNull
+ public String startProvisionedVpnProfileSession() {
try {
- mService.startVpnProfile(mContext.getOpPackageName());
+ return mService.startVpnProfile(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
+ /**
+ * Request the startup of a previously provisioned VPN.
+ *
+ * @throws SecurityException exception if user or device settings prevent this VPN from being
+ * setup, or if user consent has not been granted
+ * @deprecated This method is replaced by startProvisionedVpnProfileSession which returns a
+ * session key for the caller to diagnose the errors.
+ */
+ @Deprecated
+ public void startProvisionedVpnProfile() {
+ startProvisionedVpnProfileSession();
+ }
+
/** Tear down the VPN provided by the calling app (if any) */
public void stopProvisionedVpnProfile() {
try {
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
new file mode 100644
index 0000000..9772bde
--- /dev/null
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2022 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 android.net.netstats;
+
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
+import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
+import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
+import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.TAG_NONE;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.net.NetworkIdentity;
+import android.net.NetworkStatsCollection;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.Environment;
+import android.util.AtomicFile;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastDataInput;
+
+import libcore.io.IoUtils;
+
+import java.io.BufferedInputStream;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.ProtocolException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Helper class to read old version of persistent network statistics.
+ *
+ * The implementation is intended to be modified by OEM partners to
+ * accommodate their custom changes.
+ *
+ * @hide
+ */
+@SystemApi(client = MODULE_LIBRARIES)
+public class NetworkStatsDataMigrationUtils {
+ /**
+ * Prefix of the files which are used to store per network interface statistics.
+ */
+ public static final String PREFIX_XT = "xt";
+ /**
+ * Prefix of the files which are used to store per uid statistics.
+ */
+ public static final String PREFIX_UID = "uid";
+ /**
+ * Prefix of the files which are used to store per uid tagged traffic statistics.
+ */
+ public static final String PREFIX_UID_TAG = "uid_tag";
+
+ private static final HashMap<String, String> sPrefixLegacyFileNameMap =
+ new HashMap<String, String>() {{
+ put(PREFIX_XT, "netstats_xt.bin");
+ put(PREFIX_UID, "netstats_uid.bin");
+ put(PREFIX_UID_TAG, "netstats_uid.bin");
+ }};
+
+ // These version constants are copied from NetworkStatsCollection/History, which is okay for
+ // OEMs to modify to adapt their own logic.
+ private static class CollectionVersion {
+ static final int VERSION_NETWORK_INIT = 1;
+
+ static final int VERSION_UID_INIT = 1;
+ static final int VERSION_UID_WITH_IDENT = 2;
+ static final int VERSION_UID_WITH_TAG = 3;
+ static final int VERSION_UID_WITH_SET = 4;
+
+ static final int VERSION_UNIFIED_INIT = 16;
+ }
+
+ private static class HistoryVersion {
+ static final int VERSION_INIT = 1;
+ static final int VERSION_ADD_PACKETS = 2;
+ static final int VERSION_ADD_ACTIVE = 3;
+ }
+
+ private static class IdentitySetVersion {
+ static final int VERSION_INIT = 1;
+ static final int VERSION_ADD_ROAMING = 2;
+ static final int VERSION_ADD_NETWORK_ID = 3;
+ static final int VERSION_ADD_METERED = 4;
+ static final int VERSION_ADD_DEFAULT_NETWORK = 5;
+ static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+ }
+
+ /**
+ * File header magic number: "ANET". The definition is copied from NetworkStatsCollection,
+ * but it is fine for OEM to re-define to their own value to adapt the legacy file reading
+ * logic.
+ */
+ private static final int FILE_MAGIC = 0x414E4554;
+ /** Default buffer size from BufferedInputStream */
+ private static final int BUFFER_SIZE = 8192;
+
+ // Constructing this object is not allowed.
+ private NetworkStatsDataMigrationUtils() {
+ }
+
+ // Used to read files at /data/system/netstats_*.bin.
+ @NonNull
+ private static File getPlatformSystemDir() {
+ return new File(Environment.getDataDirectory(), "system");
+ }
+
+ // Used to read files at /data/system/netstats/<tag>.<start>-<end>.
+ @NonNull
+ private static File getPlatformBaseDir() {
+ File baseDir = new File(getPlatformSystemDir(), "netstats");
+ baseDir.mkdirs();
+ return baseDir;
+ }
+
+ // Get /data/system/netstats_*.bin legacy files. Does not check for existence.
+ @NonNull
+ private static File getLegacyBinFileForPrefix(@NonNull String prefix) {
+ return new File(getPlatformSystemDir(), sPrefixLegacyFileNameMap.get(prefix));
+ }
+
+ // List /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files.
+ @NonNull
+ private static ArrayList<File> getPlatformFileListForPrefix(@NonNull String prefix) {
+ final ArrayList<File> list = new ArrayList<>();
+ final File platformFiles = new File(getPlatformBaseDir(), "netstats");
+ if (platformFiles.exists()) {
+ for (String name : platformFiles.list()) {
+ // Skip when prefix doesn't match.
+ if (!name.startsWith(prefix + ".")) continue;
+
+ list.add(new File(platformFiles, name));
+ }
+ }
+ return list;
+ }
+
+ /**
+ * Read legacy persisted network stats from disk.
+ *
+ * This function provides the implementation to read legacy network stats
+ * from disk. It is used for migration of legacy network stats into the
+ * stats provided by the Connectivity module.
+ * This function needs to know about the previous format(s) of the network
+ * stats data that might be stored on this device so it can be read and
+ * conserved upon upgrade to Android 13 or above.
+ *
+ * This function will be called multiple times sequentially, all on the
+ * same thread, and will not be called multiple times concurrently. This
+ * function is expected to do a substantial amount of disk access, and
+ * doesn't need to return particularly fast, but the first boot after
+ * an upgrade to Android 13+ will be held until migration is done. As
+ * migration is only necessary once, after the first boot following the
+ * upgrade, this delay is not incurred.
+ *
+ * If this function fails in any way, it should throw an exception. If this
+ * happens, the system can't know about the data that was stored in the
+ * legacy files, but it will still count data usage happening on this
+ * session. On the next boot, the system will try migration again, and
+ * merge the returned data with the data used with the previous session.
+ * The system will only try the migration up to three (3) times. The remaining
+ * count is stored in the netstats_import_legacy_file_needed device config. The
+ * legacy data is never deleted by the mainline module to avoid any possible
+ * data loss.
+ *
+ * It is possible to set the netstats_import_legacy_file_needed device config
+ * to any positive integer to force the module to perform the migration. This
+ * can be achieved by calling the following command before rebooting :
+ * adb shell device_config put connectivity netstats_import_legacy_file_needed 1
+ *
+ * The AOSP implementation provides code to read persisted network stats as
+ * they were written by AOSP prior to Android 13.
+ * OEMs who have used the AOSP implementation of persisting network stats
+ * to disk don't need to change anything.
+ * OEM that had modifications to this format should modify this function
+ * to read from their custom file format or locations if necessary.
+ *
+ * @param prefix Type of data which is being read by the service.
+ * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+ * @return {@link NetworkStatsCollection} instance.
+ */
+ @NonNull
+ public static NetworkStatsCollection readPlatformCollection(
+ @NonNull String prefix, long bucketDuration) throws IOException {
+ final NetworkStatsCollection.Builder builder =
+ new NetworkStatsCollection.Builder(bucketDuration);
+
+ // Import /data/system/netstats_uid.bin legacy files if exists.
+ switch (prefix) {
+ case PREFIX_UID:
+ case PREFIX_UID_TAG:
+ final File uidFile = getLegacyBinFileForPrefix(prefix);
+ if (uidFile.exists()) {
+ readLegacyUid(builder, uidFile, PREFIX_UID_TAG.equals(prefix) ? true : false);
+ }
+ break;
+ default:
+ // Ignore other types.
+ }
+
+ // Import /data/system/netstats/[xt|uid|uid_tag].<start>-<end> legacy files if exists.
+ final ArrayList<File> platformFiles = getPlatformFileListForPrefix(prefix);
+ for (final File platformFile : platformFiles) {
+ if (platformFile.exists()) {
+ readPlatformCollection(builder, platformFile);
+ }
+ }
+
+ return builder.build();
+ }
+
+ private static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder,
+ @NonNull File file) throws IOException {
+ final FileInputStream is = new FileInputStream(file);
+ final FastDataInput dataIn = new FastDataInput(is, BUFFER_SIZE);
+ try {
+ readPlatformCollection(builder, dataIn);
+ } finally {
+ IoUtils.closeQuietly(dataIn);
+ }
+ }
+
+ /**
+ * Helper function to read old version of NetworkStatsCollections that resided in the platform.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static void readPlatformCollection(@NonNull NetworkStatsCollection.Builder builder,
+ @NonNull DataInput in) throws IOException {
+ // verify file magic header intact
+ final int magic = in.readInt();
+ if (magic != FILE_MAGIC) {
+ throw new ProtocolException("unexpected magic: " + magic);
+ }
+
+ final int version = in.readInt();
+ switch (version) {
+ case CollectionVersion.VERSION_UNIFIED_INIT: {
+ // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
+ final int identSize = in.readInt();
+ for (int i = 0; i < identSize; i++) {
+ final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in);
+
+ final int size = in.readInt();
+ for (int j = 0; j < size; j++) {
+ final int uid = in.readInt();
+ final int set = in.readInt();
+ final int tag = in.readInt();
+
+ final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key(
+ ident, uid, set, tag);
+ final NetworkStatsHistory history = readPlatformHistory(in);
+ builder.addEntry(key, history);
+ }
+ }
+ break;
+ }
+ default: {
+ throw new ProtocolException("unexpected version: " + version);
+ }
+ }
+ }
+
+ // Copied from NetworkStatsHistory#DataStreamUtils.
+ private static long[] readFullLongArray(DataInput in) throws IOException {
+ final int size = in.readInt();
+ if (size < 0) throw new ProtocolException("negative array size");
+ final long[] values = new long[size];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = in.readLong();
+ }
+ return values;
+ }
+
+ // Copied from NetworkStatsHistory#DataStreamUtils.
+ private static long[] readVarLongArray(@NonNull DataInput in) throws IOException {
+ final int size = in.readInt();
+ if (size == -1) return null;
+ if (size < 0) throw new ProtocolException("negative array size");
+ final long[] values = new long[size];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = readVarLong(in);
+ }
+ return values;
+ }
+
+ /**
+ * Read variable-length {@link Long} using protobuf-style approach.
+ */
+ // Copied from NetworkStatsHistory#DataStreamUtils.
+ private static long readVarLong(DataInput in) throws IOException {
+ int shift = 0;
+ long result = 0;
+ while (shift < 64) {
+ byte b = in.readByte();
+ result |= (long) (b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ shift += 7;
+ }
+ throw new ProtocolException("malformed var long");
+ }
+
+ // Copied from NetworkIdentitySet.
+ private static String readOptionalString(DataInput in) throws IOException {
+ if (in.readByte() != 0) {
+ return in.readUTF();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * This is copied from NetworkStatsHistory#NetworkStatsHistory(DataInput in). But it is fine
+ * for OEM to re-write the logic to adapt the legacy file reading.
+ */
+ @NonNull
+ private static NetworkStatsHistory readPlatformHistory(@NonNull DataInput in)
+ throws IOException {
+ final long bucketDuration;
+ final long[] bucketStart;
+ final long[] rxBytes;
+ final long[] rxPackets;
+ final long[] txBytes;
+ final long[] txPackets;
+ final long[] operations;
+ final int bucketCount;
+ long[] activeTime = new long[0];
+
+ final int version = in.readInt();
+ switch (version) {
+ case HistoryVersion.VERSION_INIT: {
+ bucketDuration = in.readLong();
+ bucketStart = readFullLongArray(in);
+ rxBytes = readFullLongArray(in);
+ rxPackets = new long[bucketStart.length];
+ txBytes = readFullLongArray(in);
+ txPackets = new long[bucketStart.length];
+ operations = new long[bucketStart.length];
+ bucketCount = bucketStart.length;
+ break;
+ }
+ case HistoryVersion.VERSION_ADD_PACKETS:
+ case HistoryVersion.VERSION_ADD_ACTIVE: {
+ bucketDuration = in.readLong();
+ bucketStart = readVarLongArray(in);
+ activeTime = (version >= HistoryVersion.VERSION_ADD_ACTIVE)
+ ? readVarLongArray(in)
+ : new long[bucketStart.length];
+ rxBytes = readVarLongArray(in);
+ rxPackets = readVarLongArray(in);
+ txBytes = readVarLongArray(in);
+ txPackets = readVarLongArray(in);
+ operations = readVarLongArray(in);
+ bucketCount = bucketStart.length;
+ break;
+ }
+ default: {
+ throw new ProtocolException("unexpected version: " + version);
+ }
+ }
+
+ final NetworkStatsHistory.Builder historyBuilder =
+ new NetworkStatsHistory.Builder(bucketDuration, bucketCount);
+ for (int i = 0; i < bucketCount; i++) {
+ final NetworkStatsHistory.Entry entry = new NetworkStatsHistory.Entry(
+ bucketStart[i], activeTime[i],
+ rxBytes[i], rxPackets[i], txBytes[i], txPackets[i], operations[i]);
+ historyBuilder.addEntry(entry);
+ }
+
+ return historyBuilder.build();
+ }
+
+ @NonNull
+ private static Set<NetworkIdentity> readPlatformNetworkIdentitySet(@NonNull DataInput in)
+ throws IOException {
+ final int version = in.readInt();
+ final int size = in.readInt();
+ final Set<NetworkIdentity> set = new HashSet<>();
+ for (int i = 0; i < size; i++) {
+ if (version <= IdentitySetVersion.VERSION_INIT) {
+ final int ignored = in.readInt();
+ }
+ final int type = in.readInt();
+ final int ratType = in.readInt();
+ final String subscriberId = readOptionalString(in);
+ final String networkId;
+ if (version >= IdentitySetVersion.VERSION_ADD_NETWORK_ID) {
+ networkId = readOptionalString(in);
+ } else {
+ networkId = null;
+ }
+ final boolean roaming;
+ if (version >= IdentitySetVersion.VERSION_ADD_ROAMING) {
+ roaming = in.readBoolean();
+ } else {
+ roaming = false;
+ }
+
+ final boolean metered;
+ if (version >= IdentitySetVersion.VERSION_ADD_METERED) {
+ metered = in.readBoolean();
+ } else {
+ // If this is the old data and the type is mobile, treat it as metered. (Note that
+ // if this is a mobile network, TYPE_MOBILE is the only possible type that could be
+ // used.)
+ metered = (type == TYPE_MOBILE);
+ }
+
+ final boolean defaultNetwork;
+ if (version >= IdentitySetVersion.VERSION_ADD_DEFAULT_NETWORK) {
+ defaultNetwork = in.readBoolean();
+ } else {
+ defaultNetwork = true;
+ }
+
+ final int oemNetCapabilities;
+ if (version >= IdentitySetVersion.VERSION_ADD_OEM_MANAGED_NETWORK) {
+ oemNetCapabilities = in.readInt();
+ } else {
+ oemNetCapabilities = NetworkTemplate.OEM_MANAGED_NO;
+ }
+
+ // Legacy files might contain TYPE_MOBILE_* types which were deprecated in later
+ // releases. For backward compatibility, record them as TYPE_MOBILE instead.
+ final int collapsedLegacyType = getCollapsedLegacyType(type);
+ final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
+ .setType(collapsedLegacyType)
+ .setSubscriberId(subscriberId)
+ .setWifiNetworkKey(networkId)
+ .setRoaming(roaming).setMetered(metered)
+ .setDefaultNetwork(defaultNetwork)
+ .setOemManaged(oemNetCapabilities);
+ if (type == TYPE_MOBILE && ratType != NetworkTemplate.NETWORK_TYPE_ALL) {
+ builder.setRatType(ratType);
+ }
+ set.add(builder.build());
+ }
+ return set;
+ }
+
+ private static int getCollapsedLegacyType(int networkType) {
+ // The constants are referenced from ConnectivityManager#TYPE_MOBILE_*.
+ switch (networkType) {
+ case TYPE_MOBILE:
+ case TYPE_MOBILE_SUPL:
+ case TYPE_MOBILE_MMS:
+ case TYPE_MOBILE_DUN:
+ case TYPE_MOBILE_HIPRI:
+ case 10 /* TYPE_MOBILE_FOTA */:
+ case 11 /* TYPE_MOBILE_IMS */:
+ case 12 /* TYPE_MOBILE_CBS */:
+ case 14 /* TYPE_MOBILE_IA */:
+ case 15 /* TYPE_MOBILE_EMERGENCY */:
+ return TYPE_MOBILE;
+ }
+ return networkType;
+ }
+
+ private static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder,
+ @NonNull File uidFile, boolean onlyTaggedData) throws IOException {
+ final AtomicFile inputFile = new AtomicFile(uidFile);
+ DataInputStream in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
+ try {
+ readLegacyUid(builder, in, onlyTaggedData);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ /**
+ * Read legacy Uid statistics file format into the collection.
+ *
+ * This is copied from {@code NetworkStatsCollection#readLegacyUid}.
+ * See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
+ *
+ * @param taggedData whether to read tagged data. For legacy uid files, the tagged
+ * data was stored in the same binary file with non-tagged data.
+ * But in later releases, these data should be kept in different
+ * recorders.
+ * @hide
+ */
+ @VisibleForTesting
+ public static void readLegacyUid(@NonNull NetworkStatsCollection.Builder builder,
+ @NonNull DataInput in, boolean taggedData) throws IOException {
+ try {
+ // verify file magic header intact
+ final int magic = in.readInt();
+ if (magic != FILE_MAGIC) {
+ throw new ProtocolException("unexpected magic: " + magic);
+ }
+
+ final int version = in.readInt();
+ switch (version) {
+ case CollectionVersion.VERSION_UID_INIT: {
+ // uid := size *(UID NetworkStatsHistory)
+ // drop this data version, since we don't have a good
+ // mapping into NetworkIdentitySet.
+ break;
+ }
+ case CollectionVersion.VERSION_UID_WITH_IDENT: {
+ // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
+ // drop this data version, since this version only existed
+ // for a short time.
+ break;
+ }
+ case CollectionVersion.VERSION_UID_WITH_TAG:
+ case CollectionVersion.VERSION_UID_WITH_SET: {
+ // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
+ final int identSize = in.readInt();
+ for (int i = 0; i < identSize; i++) {
+ final Set<NetworkIdentity> ident = readPlatformNetworkIdentitySet(in);
+
+ final int size = in.readInt();
+ for (int j = 0; j < size; j++) {
+ final int uid = in.readInt();
+ final int set = (version >= CollectionVersion.VERSION_UID_WITH_SET)
+ ? in.readInt()
+ : SET_DEFAULT;
+ final int tag = in.readInt();
+
+ final NetworkStatsCollection.Key key = new NetworkStatsCollection.Key(
+ ident, uid, set, tag);
+ final NetworkStatsHistory history = readPlatformHistory(in);
+
+ if ((tag == TAG_NONE) != taggedData) {
+ builder.addEntry(key, history);
+ }
+ }
+ }
+ break;
+ }
+ default: {
+ throw new ProtocolException("unknown version: " + version);
+ }
+ }
+ } catch (FileNotFoundException | ProtocolException e) {
+ // missing stats is okay, probably first boot
+ }
+ }
+}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index a6830b7..2339656 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -549,8 +549,8 @@
* networks, a network will be chosen arbitrarily amongst the networks matching the highest
* priority rule.
*
- * <p>If all networks fail to match the rules provided, an underlying network will still be
- * selected (at random if necessary).
+ * <p>If all networks fail to match the rules provided, a carrier-owned underlying network
+ * will still be selected (if available, at random if necessary).
*
* @param underlyingNetworkTemplates a list of unique VcnUnderlyingNetworkTemplates that are
* ordered from most to least preferred, or an empty list to use the default
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 0f94cbe..86e6db1 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -127,6 +127,7 @@
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
private final Parcel mHistoryBuffer;
private final List<BatteryStats.HistoryTag> mHistoryTagPool;
+ private final BatteryStatsHistory mBatteryStatsHistory;
private BatteryUsageStats(@NonNull Builder builder) {
mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
@@ -138,6 +139,7 @@
mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
mHistoryBuffer = builder.mHistoryBuffer;
mHistoryTagPool = builder.mHistoryTagPool;
+ mBatteryStatsHistory = builder.mBatteryStatsHistory;
mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
@@ -289,8 +291,8 @@
throw new IllegalStateException(
"Battery history was not requested in the BatteryUsageStatsQuery");
}
- return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer),
- mHistoryTagPool);
+
+ return new BatteryStatsHistoryIterator(mBatteryStatsHistory, mHistoryTagPool);
}
@Override
@@ -356,7 +358,10 @@
tag.poolIdx = source.readInt();
mHistoryTagPool.add(tag);
}
+ mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ mBatteryStatsHistory.readFromBatteryUsageStatsParcel(source);
} else {
+ mBatteryStatsHistory = null;
mHistoryBuffer = null;
mHistoryTagPool = null;
}
@@ -404,6 +409,7 @@
dest.writeInt(tag.uid);
dest.writeInt(tag.poolIdx);
}
+ mBatteryStatsHistory.writeToBatteryUsageStatsParcel(dest);
} else {
dest.writeBoolean(false);
}
@@ -757,6 +763,7 @@
new SparseArray<>();
private Parcel mHistoryBuffer;
private List<BatteryStats.HistoryTag> mHistoryTagPool;
+ private BatteryStatsHistory mBatteryStatsHistory;
public Builder(@NonNull String[] customPowerComponentNames) {
this(customPowerComponentNames, false);
@@ -865,10 +872,12 @@
* Sets the parceled recent history.
*/
@NonNull
- public Builder setBatteryHistory(Parcel historyBuffer,
- List<BatteryStats.HistoryTag> historyTagPool) {
+ public Builder setBatteryHistory(@NonNull Parcel historyBuffer,
+ @NonNull List<BatteryStats.HistoryTag> historyTagPool,
+ @NonNull BatteryStatsHistory batteryStatsHistory) {
mHistoryBuffer = historyBuffer;
mHistoryTagPool = historyTagPool;
+ mBatteryStatsHistory = batteryStatsHistory;
return this;
}
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index c646623..71c63ff 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -116,7 +116,7 @@
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
for (WeakReference<BinderProxy> ref : a) {
- if (ref.get() != null) {
+ if (!ref.refersTo(null)) {
++size;
}
}
@@ -187,7 +187,7 @@
// This ensures that ArrayList size is bounded by the maximum occupancy of
// that bucket.
for (int i = 0; i < size; ++i) {
- if (valueArray.get(i).get() == null) {
+ if (valueArray.get(i).refersTo(null)) {
valueArray.set(i, newWr);
Long[] keyArray = mMainIndexKeys[myHash];
keyArray[i] = key;
@@ -195,7 +195,7 @@
// "Randomly" check one of the remaining entries in [i+1, size), so that
// needlessly long buckets are eventually pruned.
int rnd = Math.floorMod(++mRandom, size - (i + 1));
- if (valueArray.get(i + 1 + rnd).get() == null) {
+ if (valueArray.get(i + 1 + rnd).refersTo(null)) {
remove(myHash, i + 1 + rnd);
}
}
@@ -516,12 +516,15 @@
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
- if (mWarnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
+ boolean warnOnBlocking = mWarnOnBlocking; // Cache it to reduce volatile access.
+
+ if (warnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
&& Binder.sWarnOnBlockingOnCurrentThread.get()) {
// For now, avoid spamming the log by disabling after we've logged
// about this interface at least once
mWarnOnBlocking = false;
+ warnOnBlocking = false;
if (Build.IS_USERDEBUG) {
// Log this as a WTF on userdebug builds.
@@ -568,7 +571,13 @@
}
try {
- return transactNative(code, data, reply, flags);
+ final boolean result = transactNative(code, data, reply, flags);
+
+ if (reply != null && !warnOnBlocking) {
+ reply.addFlags(Parcel.FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT);
+ }
+
+ return result;
} finally {
AppOpsManager.resumeNotedAppOpsCollection(prevCollection);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index e519ff3..f46f452 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -31,6 +31,7 @@
import android.sysprop.SocProperties;
import android.sysprop.TelephonyProperties;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Slog;
import android.view.View;
@@ -39,6 +40,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -396,6 +398,17 @@
*/
public static final String CODENAME = getString("ro.build.version.codename");
+ /**
+ * All known codenames starting from {@link VERSION_CODES.Q}.
+ *
+ * <p>This includes in development codenames as well.
+ *
+ * @hide
+ */
+ @SystemApi
+ @NonNull public static final Set<String> KNOWN_CODENAMES =
+ new ArraySet<>(new String[]{"Q", "R", "S", "Sv2", "Tiramisu"});
+
private static final String[] ALL_CODENAMES
= getStringList("ro.build.version.all_codenames", ",");
@@ -1024,7 +1037,7 @@
* will also enable {@link StrictMode.ThreadPolicy.Builder#detectUnbufferedIo}.</li>
* <li>{@link android.provider.DocumentsContract}'s various methods will throw failure
* exceptions back to the caller instead of returning null.
- * <li>{@link View#hasFocusable View.hasFocusable} now includes auto-focusable views.</li>
+ * <li>{@link View#hasFocusable() View.hasFocusable} now includes auto-focusable views.</li>
* <li>{@link android.view.SurfaceView} will no longer always change the underlying
* Surface object when something about it changes; apps need to look at the current
* state of the object to determine which things they are interested in have changed.</li>
@@ -1132,6 +1145,14 @@
public static final int S = 31;
/**
+ * S V2.
+ *
+ * Once more unto the breach, dear friends, once more.
+ *
+ */
+ public static final int S_V2 = 32;
+
+ /**
* Tiramisu.
*/
public static final int TIRAMISU = CUR_DEVELOPMENT;
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 09eac79..13d1d96 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -18,6 +18,7 @@
import static java.util.Objects.requireNonNull;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
@@ -53,6 +54,8 @@
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -229,6 +232,25 @@
private RuntimeException mStack;
+ /** @hide */
+ @TestApi
+ public static final int FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT = 1 << 0;
+
+ /** @hide */
+ @TestApi
+ public static final int FLAG_PROPAGATE_ALLOW_BLOCKING = 1 << 1;
+
+ /** @hide */
+ @IntDef(flag = true, prefix = { "FLAG_" }, value = {
+ FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT,
+ FLAG_PROPAGATE_ALLOW_BLOCKING,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ParcelFlags {}
+
+ @ParcelFlags
+ private int mFlags;
+
/**
* Whether or not to parcel the stack trace of an exception. This has a performance
* impact, so should only be included in specific processes and only on debug builds.
@@ -585,6 +607,40 @@
nativeMarkForBinder(mNativePtr, binder);
}
+ /** @hide */
+ @ParcelFlags
+ @TestApi
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /** @hide */
+ public void setFlags(@ParcelFlags int flags) {
+ mFlags = flags;
+ }
+
+ /** @hide */
+ public void addFlags(@ParcelFlags int flags) {
+ mFlags |= flags;
+ }
+
+ /** @hide */
+ private boolean hasFlags(@ParcelFlags int flags) {
+ return (mFlags & flags) == flags;
+ }
+
+ /**
+ * This method is used by the AIDL compiler for system components. Not intended to be
+ * used by non-system apps.
+ */
+ // Note: Ideally this method should be @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES),
+ // but we need to make this method public due to the way the aidl compiler is compiled.
+ // We don't really need to protect it; even if 3p / non-system apps, nothing would happen.
+ // This would only work when used on a reply parcel by a binder object that's allowed-blocking.
+ public void setPropagateAllowBlocking() {
+ addFlags(FLAG_PROPAGATE_ALLOW_BLOCKING);
+ }
+
/**
* Returns the total amount of data contained in the parcel.
*/
@@ -2079,6 +2135,102 @@
}
/**
+ * Flatten a homogeneous multi-dimensional array with fixed-size. This delegates to other
+ * APIs to write a one-dimensional array. Use {@link #readFixedArray(Object)} or
+ * {@link #createFixedArray(Class, int[])} with the same dimensions to unmarshal.
+ *
+ * @param val The array to be written.
+ * @param parcelableFlags Contextual flags as per
+ * {@link Parcelable#writeToParcel(Parcel, int) Parcelable.writeToParcel()}.
+ * Used only if val is an array of Parcelable objects.
+ * @param dimensions an array of int representing length of each dimension. The array should be
+ * sized with the exact size of dimensions.
+ *
+ * @see #readFixedArray
+ * @see #createFixedArray
+ * @see #writeBooleanArray
+ * @see #writeByteArray
+ * @see #writeCharArray
+ * @see #writeIntArray
+ * @see #writeLongArray
+ * @see #writeFloatArray
+ * @see #writeDoubleArray
+ * @see #writeBinderArray
+ * @see #writeInterfaceArray
+ * @see #writeTypedArray
+ * @throws BadParcelableException If the array's component type is not supported or if its
+ * size doesn't match with the given dimensions.
+ */
+ public <T> void writeFixedArray(@Nullable T val, int parcelableFlags,
+ @NonNull int... dimensions) {
+ if (val == null) {
+ writeInt(-1);
+ return;
+ }
+ writeFixedArrayInternal(val, parcelableFlags, /*index=*/0, dimensions);
+ }
+
+ private <T> void writeFixedArrayInternal(T val, int parcelableFlags, int index,
+ int[] dimensions) {
+ if (index >= dimensions.length) {
+ throw new BadParcelableException("Array has more dimensions than expected: "
+ + dimensions.length);
+ }
+
+ int length = dimensions[index];
+
+ // val should be an array of length N
+ if (val == null) {
+ throw new BadParcelableException("Non-null array shouldn't have a null array.");
+ }
+ if (!val.getClass().isArray()) {
+ throw new BadParcelableException("Not an array: " + val);
+ }
+ if (Array.getLength(val) != length) {
+ throw new BadParcelableException("bad length: expected " + length + ", but got "
+ + Array.getLength(val));
+ }
+
+ // Delegates to other writers if this is a one-dimensional array.
+ // Otherwise, write component arrays with recursive calls.
+
+ final Class<?> componentType = val.getClass().getComponentType();
+ if (!componentType.isArray() && index + 1 != dimensions.length) {
+ throw new BadParcelableException("Array has fewer dimensions than expected: "
+ + dimensions.length);
+ }
+ if (componentType == boolean.class) {
+ writeBooleanArray((boolean[]) val);
+ } else if (componentType == byte.class) {
+ writeByteArray((byte[]) val);
+ } else if (componentType == char.class) {
+ writeCharArray((char[]) val);
+ } else if (componentType == int.class) {
+ writeIntArray((int[]) val);
+ } else if (componentType == long.class) {
+ writeLongArray((long[]) val);
+ } else if (componentType == float.class) {
+ writeFloatArray((float[]) val);
+ } else if (componentType == double.class) {
+ writeDoubleArray((double[]) val);
+ } else if (componentType == IBinder.class) {
+ writeBinderArray((IBinder[]) val);
+ } else if (IInterface.class.isAssignableFrom(componentType)) {
+ writeInterfaceArray((IInterface[]) val);
+ } else if (Parcelable.class.isAssignableFrom(componentType)) {
+ writeTypedArray((Parcelable[]) val, parcelableFlags);
+ } else if (componentType.isArray()) {
+ writeInt(length);
+ for (int i = 0; i < length; i++) {
+ writeFixedArrayInternal(Array.get(val, i), parcelableFlags, index + 1,
+ dimensions);
+ }
+ } else {
+ throw new BadParcelableException("unknown type for fixed-size array: " + componentType);
+ }
+ }
+
+ /**
* Flatten a generic object in to a parcel. The given Object value may
* currently be one of the following types:
*
@@ -2940,7 +3092,15 @@
* Read an object from the parcel at the current dataPosition().
*/
public final IBinder readStrongBinder() {
- return nativeReadStrongBinder(mNativePtr);
+ final IBinder result = nativeReadStrongBinder(mNativePtr);
+
+ // If it's a reply from a method with @PropagateAllowBlocking, then inherit allow-blocking
+ // from the object that returned it.
+ if (result != null && hasFlags(
+ FLAG_IS_REPLY_FROM_BLOCKING_ALLOWED_OBJECT | FLAG_PROPAGATE_ALLOW_BLOCKING)) {
+ Binder.allowBlocking(result);
+ }
+ return result;
}
/**
@@ -3781,6 +3941,317 @@
}
/**
+ * Read a new multi-dimensional array from a parcel. If you want to read Parcelable or
+ * IInterface values, use {@link #readFixedArray(Object, Parcelable.Creator)} or
+ * {@link #readFixedArray(Object, Function)}.
+ * @param val the destination array to hold the read values.
+ *
+ * @see #writeTypedArray
+ * @see #readBooleanArray
+ * @see #readByteArray
+ * @see #readCharArray
+ * @see #readIntArray
+ * @see #readLongArray
+ * @see #readFloatArray
+ * @see #readDoubleArray
+ * @see #readBinderArray
+ * @see #readInterfaceArray
+ * @see #readTypedArray
+ */
+ public <T> void readFixedArray(@NonNull T val) {
+ Class<?> componentType = val.getClass().getComponentType();
+ if (componentType == boolean.class) {
+ readBooleanArray((boolean[]) val);
+ } else if (componentType == byte.class) {
+ readByteArray((byte[]) val);
+ } else if (componentType == char.class) {
+ readCharArray((char[]) val);
+ } else if (componentType == int.class) {
+ readIntArray((int[]) val);
+ } else if (componentType == long.class) {
+ readLongArray((long[]) val);
+ } else if (componentType == float.class) {
+ readFloatArray((float[]) val);
+ } else if (componentType == double.class) {
+ readDoubleArray((double[]) val);
+ } else if (componentType == IBinder.class) {
+ readBinderArray((IBinder[]) val);
+ } else if (componentType.isArray()) {
+ int length = readInt();
+ if (length != Array.getLength(val)) {
+ throw new BadParcelableException("Bad length: expected " + Array.getLength(val)
+ + ", but got " + length);
+ }
+ for (int i = 0; i < length; i++) {
+ readFixedArray(Array.get(val, i));
+ }
+ } else {
+ throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+ }
+ }
+
+ /**
+ * Read a new multi-dimensional array of typed interfaces from a parcel.
+ * If you want to read Parcelable values, use
+ * {@link #readFixedArray(Object, Parcelable.Creator)}. For values of other types, use
+ * {@link #readFixedArray(Object)}.
+ * @param val the destination array to hold the read values.
+ */
+ public <T, S extends IInterface> void readFixedArray(@NonNull T val,
+ @NonNull Function<IBinder, S> asInterface) {
+ Class<?> componentType = val.getClass().getComponentType();
+ if (IInterface.class.isAssignableFrom(componentType)) {
+ readInterfaceArray((S[]) val, asInterface);
+ } else if (componentType.isArray()) {
+ int length = readInt();
+ if (length != Array.getLength(val)) {
+ throw new BadParcelableException("Bad length: expected " + Array.getLength(val)
+ + ", but got " + length);
+ }
+ for (int i = 0; i < length; i++) {
+ readFixedArray(Array.get(val, i), asInterface);
+ }
+ } else {
+ throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+ }
+ }
+
+ /**
+ * Read a new multi-dimensional array of typed parcelables from a parcel.
+ * If you want to read IInterface values, use
+ * {@link #readFixedArray(Object, Function)}. For values of other types, use
+ * {@link #readFixedArray(Object)}.
+ * @param val the destination array to hold the read values.
+ */
+ public <T, S extends Parcelable> void readFixedArray(@NonNull T val,
+ @NonNull Parcelable.Creator<S> c) {
+ Class<?> componentType = val.getClass().getComponentType();
+ if (Parcelable.class.isAssignableFrom(componentType)) {
+ readTypedArray((S[]) val, c);
+ } else if (componentType.isArray()) {
+ int length = readInt();
+ if (length != Array.getLength(val)) {
+ throw new BadParcelableException("Bad length: expected " + Array.getLength(val)
+ + ", but got " + length);
+ }
+ for (int i = 0; i < length; i++) {
+ readFixedArray(Array.get(val, i), c);
+ }
+ } else {
+ throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+ }
+ }
+
+ private void ensureClassHasExpectedDimensions(@NonNull Class<?> cls, int numDimension) {
+ if (numDimension <= 0) {
+ throw new BadParcelableException("Fixed-size array should have dimensions.");
+ }
+
+ for (int i = 0; i < numDimension; i++) {
+ if (!cls.isArray()) {
+ throw new BadParcelableException("Array has fewer dimensions than expected: "
+ + numDimension);
+ }
+ cls = cls.getComponentType();
+ }
+ if (cls.isArray()) {
+ throw new BadParcelableException("Array has more dimensions than expected: "
+ + numDimension);
+ }
+ }
+
+ /**
+ * Read and return a new multi-dimensional array from a parcel. Returns null if the
+ * previously written array object is null. If you want to read Parcelable or
+ * IInterface values, use {@link #createFixedArray(Class, Parcelable.Creator, int[])} or
+ * {@link #createFixedArray(Class, Function, int[])}.
+ * @param cls the Class object for the target array type. (e.g. int[][].class)
+ * @param dimensions an array of int representing length of each dimension.
+ *
+ * @see #writeTypedArray
+ * @see #createBooleanArray
+ * @see #createByteArray
+ * @see #createCharArray
+ * @see #createIntArray
+ * @see #createLongArray
+ * @see #createFloatArray
+ * @see #createDoubleArray
+ * @see #createBinderArray
+ * @see #createInterfaceArray
+ * @see #createTypedArray
+ */
+ @Nullable
+ public <T> T createFixedArray(@NonNull Class<T> cls, @NonNull int... dimensions) {
+ // Check if type matches with dimensions
+ // If type is one-dimensional array, delegate to other creators
+ // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray
+
+ ensureClassHasExpectedDimensions(cls, dimensions.length);
+
+ T val = null;
+ final Class<?> componentType = cls.getComponentType();
+ if (componentType == boolean.class) {
+ val = (T) createBooleanArray();
+ } else if (componentType == byte.class) {
+ val = (T) createByteArray();
+ } else if (componentType == char.class) {
+ val = (T) createCharArray();
+ } else if (componentType == int.class) {
+ val = (T) createIntArray();
+ } else if (componentType == long.class) {
+ val = (T) createLongArray();
+ } else if (componentType == float.class) {
+ val = (T) createFloatArray();
+ } else if (componentType == double.class) {
+ val = (T) createDoubleArray();
+ } else if (componentType == IBinder.class) {
+ val = (T) createBinderArray();
+ } else if (componentType.isArray()) {
+ int length = readInt();
+ if (length < 0) {
+ return null;
+ }
+ if (length != dimensions[0]) {
+ throw new BadParcelableException("Bad length: expected " + dimensions[0]
+ + ", but got " + length);
+ }
+
+ // Create a multi-dimensional array with an innermost component type and dimensions
+ Class<?> innermost = componentType.getComponentType();
+ while (innermost.isArray()) {
+ innermost = innermost.getComponentType();
+ }
+ val = (T) Array.newInstance(innermost, dimensions);
+ for (int i = 0; i < length; i++) {
+ readFixedArray(Array.get(val, i));
+ }
+ return val;
+ } else {
+ throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+ }
+
+ // Check if val is null (which is OK) or has the expected size.
+ // This check doesn't have to be multi-dimensional because multi-dimensional arrays
+ // are created with expected dimensions.
+ if (val != null && Array.getLength(val) != dimensions[0]) {
+ throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got "
+ + Array.getLength(val));
+ }
+ return val;
+ }
+
+ /**
+ * Read and return a new multi-dimensional array of typed interfaces from a parcel.
+ * Returns null if the previously written array object is null. If you want to read
+ * Parcelable values, use {@link #createFixedArray(Class, Parcelable.Creator, int[])}.
+ * For values of other types use {@link #createFixedArray(Class, int[])}.
+ * @param cls the Class object for the target array type. (e.g. IFoo[][].class)
+ * @param dimensions an array of int representing length of each dimension.
+ */
+ @Nullable
+ public <T, S extends IInterface> T createFixedArray(@NonNull Class<T> cls,
+ @NonNull Function<IBinder, S> asInterface, @NonNull int... dimensions) {
+ // Check if type matches with dimensions
+ // If type is one-dimensional array, delegate to other creators
+ // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray
+
+ ensureClassHasExpectedDimensions(cls, dimensions.length);
+
+ T val = null;
+ final Class<?> componentType = cls.getComponentType();
+ if (IInterface.class.isAssignableFrom(componentType)) {
+ val = (T) createInterfaceArray(n -> (S[]) Array.newInstance(componentType, n),
+ asInterface);
+ } else if (componentType.isArray()) {
+ int length = readInt();
+ if (length < 0) {
+ return null;
+ }
+ if (length != dimensions[0]) {
+ throw new BadParcelableException("Bad length: expected " + dimensions[0]
+ + ", but got " + length);
+ }
+
+ // Create a multi-dimensional array with an innermost component type and dimensions
+ Class<?> innermost = componentType.getComponentType();
+ while (innermost.isArray()) {
+ innermost = innermost.getComponentType();
+ }
+ val = (T) Array.newInstance(innermost, dimensions);
+ for (int i = 0; i < length; i++) {
+ readFixedArray(Array.get(val, i), asInterface);
+ }
+ return val;
+ } else {
+ throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+ }
+
+ // Check if val is null (which is OK) or has the expected size.
+ // This check doesn't have to be multi-dimensional because multi-dimensional arrays
+ // are created with expected dimensions.
+ if (val != null && Array.getLength(val) != dimensions[0]) {
+ throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got "
+ + Array.getLength(val));
+ }
+ return val;
+ }
+
+ /**
+ * Read and return a new multi-dimensional array of typed parcelables from a parcel.
+ * Returns null if the previously written array object is null. If you want to read
+ * IInterface values, use {@link #createFixedArray(Class, Function, int[])}.
+ * For values of other types use {@link #createFixedArray(Class, int[])}.
+ * @param cls the Class object for the target array type. (e.g. Foo[][].class)
+ * @param dimensions an array of int representing length of each dimension.
+ */
+ @Nullable
+ public <T, S extends Parcelable> T createFixedArray(@NonNull Class<T> cls,
+ @NonNull Parcelable.Creator<S> c, @NonNull int... dimensions) {
+ // Check if type matches with dimensions
+ // If type is one-dimensional array, delegate to other creators
+ // Otherwise, create an multi-dimensional array at once and then fill it with readFixedArray
+
+ ensureClassHasExpectedDimensions(cls, dimensions.length);
+
+ T val = null;
+ final Class<?> componentType = cls.getComponentType();
+ if (Parcelable.class.isAssignableFrom(componentType)) {
+ val = (T) createTypedArray(c);
+ } else if (componentType.isArray()) {
+ int length = readInt();
+ if (length < 0) {
+ return null;
+ }
+ if (length != dimensions[0]) {
+ throw new BadParcelableException("Bad length: expected " + dimensions[0]
+ + ", but got " + length);
+ }
+
+ // Create a multi-dimensional array with an innermost component type and dimensions
+ Class<?> innermost = componentType.getComponentType();
+ while (innermost.isArray()) {
+ innermost = innermost.getComponentType();
+ }
+ val = (T) Array.newInstance(innermost, dimensions);
+ for (int i = 0; i < length; i++) {
+ readFixedArray(Array.get(val, i), c);
+ }
+ return val;
+ } else {
+ throw new BadParcelableException("Unknown type for fixed-size array: " + componentType);
+ }
+
+ // Check if val is null (which is OK) or has the expected size.
+ // This check doesn't have to be multi-dimensional because multi-dimensional arrays
+ // are created with expected dimensions.
+ if (val != null && Array.getLength(val) != dimensions[0]) {
+ throw new BadParcelableException("Bad length: expected " + dimensions[0] + ", but got "
+ + Array.getLength(val));
+ }
+ return val;
+ }
+
+ /**
* Write a heterogeneous array of Parcelable objects into the Parcel.
* Each object in the array is written along with its class name, so
* that the correct class can later be instantiated. As a result, this
@@ -4581,6 +5052,7 @@
}
private void freeBuffer() {
+ mFlags = 0;
resetSqaushingState();
if (mOwnsNativeParcelObject) {
nativeFreeBuffer(mNativePtr);
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9f37c48..2030571 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -129,6 +129,7 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@TestApi
+ @SystemApi(client = MODULE_LIBRARIES)
public static final int NFC_UID = 1027;
/**
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index d974e0c..6b869f1 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -16,7 +16,10 @@
package android.os;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import dalvik.annotation.optimization.CriticalNative;
@@ -90,6 +93,7 @@
/** @hide */
public static final long TRACE_TAG_DATABASE = 1L << 20;
/** @hide */
+ @SystemApi(client = MODULE_LIBRARIES)
public static final long TRACE_TAG_NETWORK = 1L << 21;
/** @hide */
public static final long TRACE_TAG_ADB = 1L << 22;
@@ -148,6 +152,7 @@
* @hide
*/
@UnsupportedAppUsage
+ @SystemApi(client = MODULE_LIBRARIES)
public static boolean isTagEnabled(long traceTag) {
long tags = nativeGetEnabledTags();
return (tags & traceTag) != 0;
@@ -163,7 +168,8 @@
* @hide
*/
@UnsupportedAppUsage
- public static void traceCounter(long traceTag, String counterName, int counterValue) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void traceCounter(long traceTag, @NonNull String counterName, int counterValue) {
if (isTagEnabled(traceTag)) {
nativeTraceCounter(traceTag, counterName, counterValue);
}
@@ -202,7 +208,8 @@
* @hide
*/
@UnsupportedAppUsage
- public static void traceBegin(long traceTag, String methodName) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void traceBegin(long traceTag, @NonNull String methodName) {
if (isTagEnabled(traceTag)) {
nativeTraceBegin(traceTag, methodName);
}
@@ -217,6 +224,7 @@
* @hide
*/
@UnsupportedAppUsage
+ @SystemApi(client = MODULE_LIBRARIES)
public static void traceEnd(long traceTag) {
if (isTagEnabled(traceTag)) {
nativeTraceEnd(traceTag);
@@ -237,7 +245,8 @@
* @hide
*/
@UnsupportedAppUsage
- public static void asyncTraceBegin(long traceTag, String methodName, int cookie) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void asyncTraceBegin(long traceTag, @NonNull String methodName, int cookie) {
if (isTagEnabled(traceTag)) {
nativeAsyncTraceBegin(traceTag, methodName, cookie);
}
@@ -255,7 +264,8 @@
* @hide
*/
@UnsupportedAppUsage
- public static void asyncTraceEnd(long traceTag, String methodName, int cookie) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void asyncTraceEnd(long traceTag, @NonNull String methodName, int cookie) {
if (isTagEnabled(traceTag)) {
nativeAsyncTraceEnd(traceTag, methodName, cookie);
}
diff --git a/core/java/android/os/image/IDynamicSystemService.aidl b/core/java/android/os/image/IDynamicSystemService.aidl
index a5a40ad..4e69952 100644
--- a/core/java/android/os/image/IDynamicSystemService.aidl
+++ b/core/java/android/os/image/IDynamicSystemService.aidl
@@ -26,6 +26,7 @@
* @param dsuSlot Name used to identify this installation
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean startInstallation(@utf8InCpp String dsuSlot);
/**
@@ -36,6 +37,7 @@
* @param readOnly True if this partition is readOnly
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean createPartition(@utf8InCpp String name, long size, boolean readOnly);
/**
@@ -43,12 +45,14 @@
*
* @return true if the partition installation completes without error.
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean closePartition();
/**
* Finish a previously started installation. Installations without
* a cooresponding finishInstallation() will be cleaned up during device boot.
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean finishInstallation();
/**
@@ -57,6 +61,7 @@
*
* @return GsiProgress
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
GsiProgress getInstallationProgress();
/**
@@ -66,21 +71,25 @@
*
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean abort();
/**
* @return true if the device is running an DynamicAnroid image
*/
+ @RequiresNoPermission
boolean isInUse();
/**
* @return true if the device has an DynamicSystem image installed
*/
+ @RequiresNoPermission
boolean isInstalled();
/**
* @return true if the device has an DynamicSystem image enabled
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean isEnabled();
/**
@@ -88,6 +97,7 @@
*
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean remove();
/**
@@ -97,6 +107,7 @@
*
* @return true if the call succeeds
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean setEnable(boolean enable, boolean oneShot);
/**
@@ -106,6 +117,7 @@
* @param fd fd that points to a ashmem
* @param size size of the ashmem file
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean setAshmem(in ParcelFileDescriptor fd, long size);
/**
@@ -115,6 +127,7 @@
* @param bytes number of bytes that can be read from stream.
* @return true on success, false otherwise.
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean submitFromAshmem(long bytes);
/**
@@ -124,10 +137,12 @@
* @return true on success, false if partition doesn't have a
* valid VBMeta block to retrieve the AVB key from.
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
boolean getAvbPublicKey(out AvbPublicKey dst);
/**
* Returns the suggested scratch partition size for overlayFS.
*/
+ @EnforcePermission("MANAGE_DYNAMIC_SYSTEM")
long suggestScratchSize();
}
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 3b4f7e2..f900558 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -317,16 +317,35 @@
ErrorCode.MISSING_MIN_MAC_LENGTH; // -58;
public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH =
ErrorCode.UNSUPPORTED_MIN_MAC_LENGTH; // -59;
+ public static final int KM_ERROR_UNSUPPORTED_KDF = ErrorCode.UNSUPPORTED_KDF; // -60
+ public static final int KM_ERROR_UNSUPPORTED_EC_CURVE = ErrorCode.UNSUPPORTED_EC_CURVE; // -61
+ // -62 is KEY_REQUIRES_UPGRADE and is handled by Keystore.
+ public static final int KM_ERROR_ATTESTATION_CHALLENGE_MISSING =
+ ErrorCode.ATTESTATION_CHALLENGE_MISSING; // -63
+ public static final int KM_ERROR_KEYMINT_NOT_CONFIGURED =
+ ErrorCode.KEYMINT_NOT_CONFIGURED; // -64
+ public static final int KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING =
+ ErrorCode.ATTESTATION_APPLICATION_ID_MISSING; // -65;
public static final int KM_ERROR_CANNOT_ATTEST_IDS =
ErrorCode.CANNOT_ATTEST_IDS; // -66;
+ public static final int KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE =
+ ErrorCode.ROLLBACK_RESISTANCE_UNAVAILABLE; // -67;
public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE =
ErrorCode.HARDWARE_TYPE_UNAVAILABLE; // -68;
public static final int KM_ERROR_DEVICE_LOCKED =
ErrorCode.DEVICE_LOCKED; // -72;
+ public static final int KM_ERROR_STORAGE_KEY_UNSUPPORTED =
+ ErrorCode.STORAGE_KEY_UNSUPPORTED; // -77,
+ public static final int KM_ERROR_INCOMPATIBLE_MGF_DIGEST =
+ ErrorCode.INCOMPATIBLE_MGF_DIGEST; // -78,
+ public static final int KM_ERROR_UNSUPPORTED_MGF_DIGEST =
+ ErrorCode.UNSUPPORTED_MGF_DIGEST; // -79,
public static final int KM_ERROR_MISSING_NOT_BEFORE =
ErrorCode.MISSING_NOT_BEFORE; // -80;
public static final int KM_ERROR_MISSING_NOT_AFTER =
ErrorCode.MISSING_NOT_AFTER; // -80;
+ public static final int KM_ERROR_HARDWARE_NOT_YET_AVAILABLE =
+ ErrorCode.HARDWARE_NOT_YET_AVAILABLE; // -85
public static final int KM_ERROR_UNIMPLEMENTED =
ErrorCode.UNIMPLEMENTED; // -100;
public static final int KM_ERROR_VERSION_MISMATCH =
diff --git a/core/java/android/service/security/attestationverification/OWNERS b/core/java/android/service/security/attestationverification/OWNERS
new file mode 100644
index 0000000..12c9978
--- /dev/null
+++ b/core/java/android/service/security/attestationverification/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/security/attestationverification/OWNERS
diff --git a/core/java/android/service/tracing/TraceReportService.java b/core/java/android/service/tracing/TraceReportService.java
new file mode 100644
index 0000000..3d16a3d
--- /dev/null
+++ b/core/java/android/service/tracing/TraceReportService.java
@@ -0,0 +1,165 @@
+/*
+ * 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 android.service.tracing;
+
+import static android.annotation.SystemApi.Client.PRIVILEGED_APPS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.tracing.TraceReportParams;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * Service to be sub-classed and exposed by (privileged) apps which want to report
+ * system traces.
+ * <p>
+ * Subclasses should implement the onReportTrace method to handle traces reported
+ * to them.
+ * </p>
+ * <pre>
+ * public class SampleReportService extends TraceReportService {
+ * public void onReportTrace(TraceParams args) {
+ * // --- Implementation goes here ---
+ * }
+ * }
+ * </pre>
+ * <p>
+ * The service declaration in the application manifest must specify
+ * BIND_TRACE_REPORT_SERVICE in the permission attribute.
+ * </p>
+ * <pre>
+ * <application>
+ * <service android:name=".SampleReportService"
+ * android:permission="android.permission.BIND_TRACE_REPORT_SERVICE">
+ * </service>
+ * </application>
+ * </pre>
+ *
+ * Moreover, the package containing this service must hold the DUMP and PACKAGE_USAGE_STATS
+ * permissions.
+ *
+ * @hide
+ */
+@SystemApi(client = PRIVILEGED_APPS)
+public class TraceReportService extends Service {
+ private static final String TAG = "TraceReportService";
+ private Messenger mMessenger = null;
+
+ /**
+ * Public to allow this to be used by TracingServiceProxy in system_server.
+ *
+ * @hide
+ */
+ public static final int MSG_REPORT_TRACE = 1;
+
+ /**
+ * Contains information about the trace which is being reported.
+ *
+ * @hide
+ */
+ @SystemApi(client = PRIVILEGED_APPS)
+ public static final class TraceParams {
+ private final ParcelFileDescriptor mFd;
+ private final UUID mUuid;
+
+ private TraceParams(TraceReportParams params) {
+ mFd = params.fd;
+ mUuid = new UUID(params.uuidMsb, params.uuidLsb);
+ }
+
+ /**
+ * Returns the ParcelFileDescriptor for the collected trace.
+ */
+ @NonNull
+ public ParcelFileDescriptor getFd() {
+ return mFd;
+ }
+
+ /**
+ * Returns the UUID of the trace; this is exactly the UUID created by the tracing system
+ * (i.e. Perfetto) and is also present inside the trace file.
+ */
+ @NonNull
+ public UUID getUuid() {
+ return mUuid;
+ }
+ }
+
+ // Methods to override.
+ /**
+ * Called when a trace is reported and sent to this class.
+ *
+ * Note: the trace file descriptor should not be persisted beyond the lifetime of this
+ * function as it is owned by the framework and will be closed immediately after this function
+ * returns: if future use of the fd is needed, it should be duped.
+ */
+ public void onReportTrace(@NonNull TraceParams args) {
+ }
+
+ // Optional methods to override.
+ // Realistically, these methods are internal implementation details but since this class is
+ // a SystemApi, it's better to err on the side of flexibility just in-case we need to override
+ // these methods down the line.
+
+ /**
+ * Handles binder calls from system_server.
+ */
+ public boolean onMessage(@NonNull Message msg) {
+ if (msg.what == MSG_REPORT_TRACE) {
+ if (!(msg.obj instanceof TraceReportParams)) {
+ Log.e(TAG, "Received invalid type for report trace message.");
+ return false;
+ }
+ TraceParams params = new TraceParams((TraceReportParams) msg.obj);
+ try {
+ onReportTrace(params);
+ } finally {
+ try {
+ params.getFd().close();
+ } catch (IOException ignored) {
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns an IBinder for handling binder calls from system_server.
+ */
+ @Nullable
+ @Override
+ public IBinder onBind(@NonNull Intent intent) {
+ if (mMessenger == null) {
+ mMessenger = new Messenger(new Handler(Looper.getMainLooper(), this::onMessage));
+ }
+ return mMessenger.getBinder();
+ }
+}
\ No newline at end of file
diff --git a/core/java/android/service/wallpapereffectsgeneration/OWNERS b/core/java/android/service/wallpapereffectsgeneration/OWNERS
new file mode 100644
index 0000000..d2d3e2c0
--- /dev/null
+++ b/core/java/android/service/wallpapereffectsgeneration/OWNERS
@@ -0,0 +1,4 @@
+susharon@google.com
+shanh@google.com
+huiwu@google.com
+srazdan@google.com
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
index 9cbda9c..2eb917b 100644
--- a/core/java/android/text/method/TextKeyListener.java
+++ b/core/java/android/text/method/TextKeyListener.java
@@ -306,7 +306,7 @@
/* package */ int getPrefs(Context context) {
synchronized (this) {
- if (!mPrefsInited || mResolver.get() == null) {
+ if (!mPrefsInited || mResolver.refersTo(null)) {
initPrefs(context);
}
}
diff --git a/core/java/android/tracing/ITracingServiceProxy.aidl b/core/java/android/tracing/ITracingServiceProxy.aidl
index 4520db3..8029b88 100644
--- a/core/java/android/tracing/ITracingServiceProxy.aidl
+++ b/core/java/android/tracing/ITracingServiceProxy.aidl
@@ -16,17 +16,25 @@
package android.tracing;
+import android.tracing.TraceReportParams;
+
/**
* Binder interface for the TracingServiceProxy running in system_server.
*
* {@hide}
*/
-interface ITracingServiceProxy
-{
+interface ITracingServiceProxy {
/**
* Notifies system tracing app that a tracing session has ended. If a session is repurposed
* for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
* there is no buffer available to dump.
*/
oneway void notifyTraceSessionEnded(boolean sessionStolen);
+
+ /**
+ * Notifies the specified service that a trace has been captured. The contents of |params|
+ * contains the intended recipient (package and class) of this trace as well as a file
+ * descriptor to an unlinked trace |fd| (i.e. an fd opened using O_TMPFILE).
+ */
+ oneway void reportTrace(in TraceReportParams params);
}
diff --git a/core/java/android/tracing/TraceReportParams.aidl b/core/java/android/tracing/TraceReportParams.aidl
new file mode 100644
index 0000000..f57386c
--- /dev/null
+++ b/core/java/android/tracing/TraceReportParams.aidl
@@ -0,0 +1,59 @@
+/**
+ * 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 android.tracing;
+
+import android.os.ParcelFileDescriptor;
+
+/*
+ * Parameters for a trace report.
+ *
+ * See ITracingServiceProxy::reportTrace for more details.
+ *
+ * @hide
+ */
+parcelable TraceReportParams {
+ // The package name containing the reporter service (see |reporterClassName|).
+ String reporterPackageName;
+
+ // The class name of the reporter service. The framework will bind to this service and pass the
+ // trace fd and metadata to this class.
+ // This class should be "trusted" (in practice this means being a priv_app + having DUMP and
+ // USAGE_STATS permissions).
+ String reporterClassName;
+
+ // The file descriptor for the trace file. This will be an unlinked file fd (i.e. created
+ // with O_TMPFILE); the intention is that reporter classes link this fd into a app-private
+ // folder for reporting when conditions are right (e.g. charging, on unmetered networks etc).
+ ParcelFileDescriptor fd;
+
+ // The least-significant-bytes of the UUID of this trace.
+ long uuidLsb;
+
+ // The most-significant-bytes of the UUID of this trace.
+ long uuidMsb;
+
+ // Flag indicating whether, instead of passing the fd from the trace collector, to pass a
+ // pipe fd from system_server and send the file over it.
+ //
+ // This flag is necessary because there is no good way to write a CTS test where a helper
+ // priv_app (in terms of SELinux) is needed (this is because priv_apps are supposed to be
+ // preinstalled on the system partition). By creating a pipe in system_server we work around
+ // this restriction. Note that there is a maximum allowed file size if this flag is set
+ // (see TracingServiceProxy). Further note that, even though SELinux may be worked around,
+ // manifest (i.e. framework) permissions are still checked even if this flag is set.
+ boolean usePipeForTesting;
+}
\ No newline at end of file
diff --git a/core/java/android/util/OWNERS b/core/java/android/util/OWNERS
index 5425c21..28c078e 100644
--- a/core/java/android/util/OWNERS
+++ b/core/java/android/util/OWNERS
@@ -1,6 +1,6 @@
+per-file Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
per-file FeatureFlagUtils.java = sbasi@google.com
per-file FeatureFlagUtils.java = tmfang@google.com
-per-file FeatureFlagUtils.java = asapperstein@google.com
per-file AttributeSet.java = file:/core/java/android/content/res/OWNERS
per-file TypedValue.java = file:/core/java/android/content/res/OWNERS
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index c7d9b9c..c8c1fd4 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -407,20 +407,6 @@
}
}
- static byte[] generateApkVerityRootHash(String apkPath)
- throws IOException, SignatureNotFoundException, DigestException,
- NoSuchAlgorithmException {
- try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
- SignatureInfo signatureInfo = findSignature(apk);
- VerifiedSigner vSigner = verify(apk, false);
- if (vSigner.verityRootHash == null) {
- return null;
- }
- return VerityBuilder.generateApkVerityRootHash(
- apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
- }
- }
-
/**
* Verified APK Signature Scheme v2 signer.
*
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
index b07b522..15215c6 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java
@@ -444,20 +444,6 @@
}
}
- static byte[] generateApkVerityRootHash(String apkPath)
- throws NoSuchAlgorithmException, DigestException, IOException,
- SignatureNotFoundException {
- try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
- SignatureInfo signatureInfo = findSignature(apk);
- VerifiedSigner vSigner = verify(apk, false);
- if (vSigner.verityRootHash == null) {
- return null;
- }
- return VerityBuilder.generateApkVerityRootHash(
- apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
- }
- }
-
/**
* Verified APK Signature Scheme v3 signer, including the proof of rotation structure.
*
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index 73f7543..f6b85fd 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -551,27 +551,6 @@
}
/**
- * Generates the FSVerity root hash from FSVerity header, extensions and Merkle tree root hash
- * in Signing Block.
- *
- * @return FSverity root hash
- */
- public static byte[] generateApkVerityRootHash(String apkPath)
- throws NoSuchAlgorithmException, DigestException, IOException {
- // first try v3
- try {
- return ApkSignatureSchemeV3Verifier.generateApkVerityRootHash(apkPath);
- } catch (SignatureNotFoundException e) {
- // try older version
- }
- try {
- return ApkSignatureSchemeV2Verifier.generateApkVerityRootHash(apkPath);
- } catch (SignatureNotFoundException e) {
- return null;
- }
- }
-
- /**
* Extended signing details.
* @hide for internal use only.
*/
diff --git a/core/java/android/util/apk/VerityBuilder.java b/core/java/android/util/apk/VerityBuilder.java
index c7c465d3..adf53c2 100644
--- a/core/java/android/util/apk/VerityBuilder.java
+++ b/core/java/android/util/apk/VerityBuilder.java
@@ -143,25 +143,6 @@
return generateFsVerityTreeInternal(apk, salt, levelOffset, tree);
}
}
- /**
- * Calculates the apk-verity root hash for integrity measurement. This needs to be consistent
- * to what kernel returns.
- */
- @NonNull
- static byte[] generateApkVerityRootHash(@NonNull RandomAccessFile apk,
- @NonNull ByteBuffer apkDigest, @NonNull SignatureInfo signatureInfo)
- throws NoSuchAlgorithmException, DigestException, IOException {
- assertSigningBlockAlignedAndHasFullPages(signatureInfo);
-
- ByteBuffer footer = ByteBuffer.allocate(CHUNK_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN);
- generateApkVerityFooter(apk, signatureInfo, footer);
- footer.flip();
-
- MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM);
- md.update(footer);
- md.update(apkDigest);
- return md.digest();
- }
/**
* Generates the apk-verity header and hash tree to be used by kernel for the given apk. This
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index f5c1bcf..452dad3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4347,7 +4347,7 @@
* pixel" units. This size is adjusted based on the current density and
* user font size preference.
*
- * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op.
+ * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op.
*
* @param size The scaled pixel size.
*
@@ -4362,7 +4362,7 @@
* Set the default text size to a given unit and value. See {@link
* TypedValue} for the possible dimension units.
*
- * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op.
+ * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
diff --git a/core/java/com/android/internal/midi/OWNERS b/core/java/com/android/internal/midi/OWNERS
new file mode 100644
index 0000000..af273a6
--- /dev/null
+++ b/core/java/com/android/internal/midi/OWNERS
@@ -0,0 +1 @@
+include /services/midi/OWNERS
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 2ae56f8..f174498 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -105,6 +105,7 @@
public boolean allowIPv4;
public boolean allowIPv6;
public boolean isMetered = true;
+ public boolean requiresInternetValidation = false;
public Network[] underlyingNetworks;
public ProxyInfo proxyInfo;
@@ -131,6 +132,7 @@
allowIPv4 = other.allowIPv4;
allowIPv6 = other.allowIPv6;
isMetered = other.isMetered;
+ requiresInternetValidation = other.requiresInternetValidation;
underlyingNetworks = other.underlyingNetworks != null ? Arrays.copyOf(
other.underlyingNetworks, other.underlyingNetworks.length) : null;
proxyInfo = other.proxyInfo;
@@ -189,6 +191,7 @@
out.writeInt(allowIPv4 ? 1 : 0);
out.writeInt(allowIPv6 ? 1 : 0);
out.writeInt(isMetered ? 1 : 0);
+ out.writeInt(requiresInternetValidation ? 1 : 0);
out.writeTypedArray(underlyingNetworks, flags);
out.writeParcelable(proxyInfo, flags);
}
@@ -216,6 +219,7 @@
config.allowIPv4 = in.readInt() != 0;
config.allowIPv6 = in.readInt() != 0;
config.isMetered = in.readInt() != 0;
+ config.requiresInternetValidation = in.readInt() != 0;
config.underlyingNetworks = in.createTypedArray(Network.CREATOR);
config.proxyInfo = in.readParcelable(null);
return config;
@@ -248,6 +252,8 @@
.append(", allowBypass=").append(allowBypass)
.append(", allowIPv4=").append(allowIPv4)
.append(", allowIPv6=").append(allowIPv6)
+ .append(", isMetered=").append(isMetered)
+ .append(", requiresInternetValidation").append(requiresInternetValidation)
.append(", underlyingNetworks=").append(Arrays.toString(underlyingNetworks))
.append(", proxyInfo=").append(proxyInfo)
.append("}")
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index d8dc143..bd3e898 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -144,23 +144,26 @@
public final boolean isRestrictedToTestNetworks; // 24
public final boolean excludeLocalRoutes; // 25
+ public final boolean requiresInternetValidation; // 26
// Helper fields.
@UnsupportedAppUsage
public transient boolean saveLogin = false;
public VpnProfile(String key) {
- this(key, false, false);
+ this(key, false, false, false);
}
public VpnProfile(String key, boolean isRestrictedToTestNetworks) {
- this(key, isRestrictedToTestNetworks, false);
+ this(key, isRestrictedToTestNetworks, false, false);
}
- public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes) {
+ public VpnProfile(String key, boolean isRestrictedToTestNetworks, boolean excludeLocalRoutes,
+ boolean requiresInternetValidation) {
this.key = key;
this.isRestrictedToTestNetworks = isRestrictedToTestNetworks;
this.excludeLocalRoutes = excludeLocalRoutes;
+ this.requiresInternetValidation = requiresInternetValidation;
}
@UnsupportedAppUsage
@@ -191,6 +194,7 @@
areAuthParamsInline = in.readBoolean();
isRestrictedToTestNetworks = in.readBoolean();
excludeLocalRoutes = in.readBoolean();
+ requiresInternetValidation = in.readBoolean();
}
/**
@@ -239,6 +243,7 @@
out.writeBoolean(areAuthParamsInline);
out.writeBoolean(isRestrictedToTestNetworks);
out.writeBoolean(excludeLocalRoutes);
+ out.writeBoolean(requiresInternetValidation);
}
/**
@@ -258,9 +263,11 @@
// 14-19: Standard profile, with option for serverCert, proxy
// 24: Standard profile with serverCert, proxy and platform-VPN parameters
// 25: Standard profile with platform-VPN parameters and isRestrictedToTestNetworks
- // 26: Standard profile with platform-VPN parameters and excludeLocalRoutes
- if ((values.length < 14 || values.length > 19)
- && values.length != 24 && values.length != 25 && values.length != 26) {
+ // 26: ...and excludeLocalRoutes
+ // (26 can only be found on dogfood devices)
+ // 27: ...and requiresInternetValidation
+ if ((values.length < 14 || (values.length > 19 && values.length < 24)
+ || values.length > 27)) {
return null;
}
@@ -278,8 +285,15 @@
excludeLocalRoutes = false;
}
+ final boolean requiresInternetValidation;
+ if (values.length >= 27) {
+ requiresInternetValidation = Boolean.parseBoolean(values[26]);
+ } else {
+ requiresInternetValidation = false;
+ }
+
VpnProfile profile = new VpnProfile(key, isRestrictedToTestNetworks,
- excludeLocalRoutes);
+ excludeLocalRoutes, requiresInternetValidation);
profile.name = values[0];
profile.type = Integer.parseInt(values[1]);
if (profile.type < 0 || profile.type > TYPE_MAX) {
@@ -390,6 +404,7 @@
builder.append(VALUE_DELIMITER).append(isRestrictedToTestNetworks);
builder.append(VALUE_DELIMITER).append(excludeLocalRoutes);
+ builder.append(VALUE_DELIMITER).append(requiresInternetValidation);
return builder.toString().getBytes(StandardCharsets.UTF_8);
}
@@ -471,7 +486,7 @@
key, type, server, username, password, dnsServers, searchDomains, routes, mppe,
l2tpSecret, ipsecIdentifier, ipsecSecret, ipsecUserCert, ipsecCaCert, ipsecServerCert,
proxy, mAllowedAlgorithms, isBypassable, isMetered, maxMtu, areAuthParamsInline,
- isRestrictedToTestNetworks, excludeLocalRoutes);
+ isRestrictedToTestNetworks, excludeLocalRoutes, requiresInternetValidation);
}
/** Checks VPN profiles for interior equality. */
@@ -505,11 +520,12 @@
&& maxMtu == other.maxMtu
&& areAuthParamsInline == other.areAuthParamsInline
&& isRestrictedToTestNetworks == other.isRestrictedToTestNetworks
- && excludeLocalRoutes == other.excludeLocalRoutes;
+ && excludeLocalRoutes == other.excludeLocalRoutes
+ && requiresInternetValidation == other.requiresInternetValidation;
}
@NonNull
- public static final Creator<VpnProfile> CREATOR = new Creator<VpnProfile>() {
+ public static final Creator<VpnProfile> CREATOR = new Creator<>() {
@Override
public VpnProfile createFromParcel(Parcel in) {
return new VpnProfile(in);
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 879e0a8..8ebb11d 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -160,6 +160,11 @@
mHistoryDir = null;
mHistoryBuffer = historyBuffer;
}
+
+ public File getHistoryDirectory() {
+ return mHistoryDir;
+ }
+
/**
* Set the active file that mHistoryBuffer is backed up into.
*
@@ -375,12 +380,24 @@
}
/**
- * Read all history files and serialize into a big Parcel. This is to send history files to
- * Settings app since Settings app can not access /data/system directory.
- * Checkin file also call this method.
+ * Read all history files and serialize into a big Parcel.
+ * Checkin file calls this method.
* @param out the output parcel
*/
public void writeToParcel(Parcel out) {
+ writeToParcel(out, false /* useBlobs */);
+ }
+
+ /**
+ * Read all history files and serialize into a big Parcel. This is to send history files to
+ * Settings app since Settings app can not access /data/system directory.
+ * @param out the output parcel
+ */
+ public void writeToBatteryUsageStatsParcel(Parcel out) {
+ writeToParcel(out, true /* useBlobs */);
+ }
+
+ private void writeToParcel(Parcel out, boolean useBlobs) {
final long start = SystemClock.uptimeMillis();
out.writeInt(mFileNumbers.size() - 1);
for(int i = 0; i < mFileNumbers.size() - 1; i++) {
@@ -391,7 +408,12 @@
} catch(Exception e) {
Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
}
- out.writeByteArray(raw);
+ if (useBlobs) {
+ out.writeBlob(raw);
+ } else {
+ // Avoiding blobs in the check-in file for compatibility
+ out.writeByteArray(raw);
+ }
}
if (DEBUG) {
Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start));
@@ -399,18 +421,29 @@
}
/**
- * This is for Settings app, when Settings app receives big history parcel, it call
- * this method to parse it into list of parcels.
- * Checkin file also call this method.
+ * This is for the check-in file, which has all history files embedded.
* @param in the input parcel.
*/
public void readFromParcel(Parcel in) {
+ readFromParcel(in, false /* useBlobs */);
+ }
+
+ /**
+ * This is for Settings app, when Settings app receives big history parcel, it calls
+ * this method to parse it into list of parcels.
+ * @param in the input parcel.
+ */
+ public void readFromBatteryUsageStatsParcel(Parcel in) {
+ readFromParcel(in, true /* useBlobs */);
+ }
+
+ private void readFromParcel(Parcel in, boolean useBlobs) {
final long start = SystemClock.uptimeMillis();
mHistoryParcels = new ArrayList<>();
final int count = in.readInt();
for(int i = 0; i < count; i++) {
- byte[] temp = in.createByteArray();
- if (temp.length == 0) {
+ byte[] temp = useBlobs ? in.readBlob() : in.createByteArray();
+ if (temp == null || temp.length == 0) {
continue;
}
Parcel p = Parcel.obtain();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 270b5d6..58a0622 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -83,7 +83,6 @@
import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.MutableInt;
-import android.util.Pools;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;
@@ -136,9 +135,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -1203,12 +1200,21 @@
}
public BatteryStatsImpl(Clocks clocks) {
+ this(clocks, (File) null);
+ }
+
+ public BatteryStatsImpl(Clocks clocks, File historyDirectory) {
init(clocks);
mStartClockTimeMs = clocks.currentTimeMillis();
- mStatsFile = null;
mCheckinFile = null;
mDailyFile = null;
- mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ if (historyDirectory == null) {
+ mStatsFile = null;
+ mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
+ } else {
+ mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
+ mBatteryStatsHistory = new BatteryStatsHistory(this, historyDirectory, mHistoryBuffer);
+ }
mHandler = null;
mPlatformIdleStateCallback = null;
mMeasuredEnergyRetriever = null;
@@ -11522,8 +11528,6 @@
}
}
- private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
-
private final Object mWifiNetworkLock = new Object();
@GuardedBy("mWifiNetworkLock")
@@ -11541,13 +11545,15 @@
private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
@VisibleForTesting
- protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager,
- String[] ifaces) {
- Objects.requireNonNull(networkStatsManager);
- if (!ArrayUtils.isEmpty(ifaces)) {
- return networkStatsManager.getDetailedUidStats(Set.of(ifaces));
- }
- return null;
+ protected NetworkStats readMobileNetworkStatsLocked(
+ @NonNull NetworkStatsManager networkStatsManager) {
+ return networkStatsManager.getMobileUidStats();
+ }
+
+ @VisibleForTesting
+ protected NetworkStats readWifiNetworkStatsLocked(
+ @NonNull NetworkStatsManager networkStatsManager) {
+ return networkStatsManager.getWifiUidStats();
}
/**
@@ -11564,21 +11570,15 @@
// Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null;
synchronized (mWifiNetworkLock) {
- final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager,
- mWifiIfaces);
+ final NetworkStats latestStats = readWifiNetworkStatsLocked(networkStatsManager);
if (latestStats != null) {
- delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
- mNetworkStatsPool.acquire());
- mNetworkStatsPool.release(mLastWifiNetworkStats);
+ delta = latestStats.subtract(mLastWifiNetworkStats);
mLastWifiNetworkStats = latestStats;
}
}
synchronized (this) {
if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
- if (delta != null) {
- mNetworkStatsPool.release(delta);
- }
if (mIgnoreNextExternalStats) {
// TODO: Strictly speaking, we should re-mark all 5 timers for each uid (and the
// global one) here like we do for display. But I'm not sure it's worth the
@@ -11599,61 +11599,60 @@
long totalTxPackets = 0;
long totalRxPackets = 0;
if (delta != null) {
- NetworkStats.Entry entry = new NetworkStats.Entry();
- final int size = delta.size();
- for (int i = 0; i < size; i++) {
- entry = delta.getValues(i, entry);
-
+ for (NetworkStats.Entry entry : delta) {
if (DEBUG_ENERGY) {
- Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
- + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
- + " txPackets=" + entry.txPackets);
+ Slog.d(TAG, "Wifi uid " + entry.getUid()
+ + ": delta rx=" + entry.getRxBytes()
+ + " tx=" + entry.getTxBytes()
+ + " rxPackets=" + entry.getRxPackets()
+ + " txPackets=" + entry.getTxPackets());
}
- if (entry.rxBytes == 0 && entry.txBytes == 0) {
+ if (entry.getRxBytes() == 0 && entry.getTxBytes() == 0) {
// Skip the lookup below since there is no work to do.
continue;
}
- final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs);
- if (entry.rxBytes != 0) {
- u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
- entry.rxPackets);
- if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
- u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
- entry.rxPackets);
+ final Uid u = getUidStatsLocked(mapUid(entry.getUid()),
+ elapsedRealtimeMs, uptimeMs);
+ if (entry.getRxBytes() != 0) {
+ u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.getRxBytes(),
+ entry.getRxPackets());
+ if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
+ u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.getRxBytes(),
+ entry.getRxPackets());
}
mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
- entry.rxBytes);
+ entry.getRxBytes());
mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
- entry.rxPackets);
+ entry.getRxPackets());
// TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
- rxPackets.put(u.getUid(), entry.rxPackets);
+ rxPackets.put(u.getUid(), entry.getRxPackets());
// Sum the total number of packets so that the Rx Power can
// be evenly distributed amongst the apps.
- totalRxPackets += entry.rxPackets;
+ totalRxPackets += entry.getRxPackets();
}
- if (entry.txBytes != 0) {
- u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
- entry.txPackets);
- if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
- u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
- entry.txPackets);
+ if (entry.getTxBytes() != 0) {
+ u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.getTxBytes(),
+ entry.getTxPackets());
+ if (entry.getSet() == NetworkStats.SET_DEFAULT) { // Background transfers
+ u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.getTxBytes(),
+ entry.getTxPackets());
}
mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
- entry.txBytes);
+ entry.getTxBytes());
mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
- entry.txPackets);
+ entry.getTxPackets());
// TODO(b/182845426): What if u was a mapped isolated uid? Shouldn't we sum?
- txPackets.put(u.getUid(), entry.txPackets);
+ txPackets.put(u.getUid(), entry.getTxPackets());
// Sum the total number of packets so that the Tx Power can
// be evenly distributed amongst the apps.
- totalTxPackets += entry.txPackets;
+ totalTxPackets += entry.getTxPackets();
}
// Calculate consumed energy for this uid. Only do so if WifiReporting isn't
@@ -11681,11 +11680,10 @@
uidEstimatedConsumptionMah.add(u.getUid(),
mWifiPowerCalculator.calcPowerWithoutControllerDataMah(
- entry.rxPackets, entry.txPackets,
+ entry.getRxPackets(), entry.getTxPackets(),
uidRunningMs, uidScanMs, uidBatchScanMs));
}
}
- mNetworkStatsPool.release(delta);
delta = null;
}
@@ -11932,21 +11930,15 @@
// Grab a separate lock to acquire the network stats, which may do I/O.
NetworkStats delta = null;
synchronized (mModemNetworkLock) {
- final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager,
- mModemIfaces);
+ final NetworkStats latestStats = readMobileNetworkStatsLocked(networkStatsManager);
if (latestStats != null) {
- delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
- mNetworkStatsPool.acquire());
- mNetworkStatsPool.release(mLastModemNetworkStats);
+ delta = latestStats.subtract(mLastModemNetworkStats);
mLastModemNetworkStats = latestStats;
}
}
synchronized (this) {
if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
- if (delta != null) {
- mNetworkStatsPool.release(delta);
- }
return;
}
@@ -12148,7 +12140,6 @@
totalEstimatedConsumptionMah);
}
- mNetworkStatsPool.release(delta);
delta = null;
}
}
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index 980aec1..7983286 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -21,6 +21,7 @@
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.BatteryUsageStatsQuery;
+import android.os.Parcel;
import android.os.SystemClock;
import android.os.UidBatteryConsumer;
import android.util.Log;
@@ -28,6 +29,7 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -186,16 +188,28 @@
}
BatteryStatsImpl batteryStatsImpl = (BatteryStatsImpl) mStats;
+
+ // Make a copy of battery history to avoid concurrent modification.
+ Parcel historyBuffer = Parcel.obtain();
+ historyBuffer.appendFrom(batteryStatsImpl.mHistoryBuffer, 0,
+ batteryStatsImpl.mHistoryBuffer.dataSize());
+
ArrayList<BatteryStats.HistoryTag> tags = new ArrayList<>(
batteryStatsImpl.mHistoryTagPool.size());
for (Map.Entry<BatteryStats.HistoryTag, Integer> entry :
batteryStatsImpl.mHistoryTagPool.entrySet()) {
- final BatteryStats.HistoryTag tag = entry.getKey();
+ final BatteryStats.HistoryTag tag = new BatteryStats.HistoryTag();
+ tag.setTo(entry.getKey());
tag.poolIdx = entry.getValue();
tags.add(tag);
}
- batteryUsageStatsBuilder.setBatteryHistory(batteryStatsImpl.mHistoryBuffer, tags);
+ final File systemDir =
+ batteryStatsImpl.mBatteryStatsHistory.getHistoryDirectory().getParentFile();
+ final BatteryStatsHistory batteryStatsHistory =
+ new BatteryStatsHistory(batteryStatsImpl, systemDir, historyBuffer);
+
+ batteryUsageStatsBuilder.setBatteryHistory(historyBuffer, tags, batteryStatsHistory);
}
return batteryUsageStatsBuilder.build();
diff --git a/core/java/com/android/internal/os/BinderLatencyObserver.java b/core/java/com/android/internal/os/BinderLatencyObserver.java
index 20cf102..e9d55db 100644
--- a/core/java/com/android/internal/os/BinderLatencyObserver.java
+++ b/core/java/com/android/internal/os/BinderLatencyObserver.java
@@ -19,7 +19,6 @@
import android.annotation.Nullable;
import android.os.Binder;
import android.os.Handler;
-import android.os.Looper;
import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.Slog;
@@ -181,7 +180,7 @@
}
public Handler getHandler() {
- return new Handler(Looper.getMainLooper());
+ return BackgroundThread.getHandler();
}
}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 8d1f16b..44c7f54 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -22,6 +22,7 @@
import android.app.IActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.type.DefaultMimeMapFactory;
+import android.net.TrafficStats;
import android.os.Build;
import android.os.DeadObjectException;
import android.os.IBinder;
@@ -32,7 +33,6 @@
import android.util.Slog;
import com.android.internal.logging.AndroidConfig;
-import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.RuntimeHooks;
import dalvik.system.VMRuntime;
@@ -254,7 +254,7 @@
/*
* Wire socket tagging to traffic stats.
*/
- NetworkManagementSocketTagger.install();
+ TrafficStats.attachSocketTagger();
initialized = true;
}
diff --git a/core/java/com/android/internal/security/VerityUtils.java b/core/java/com/android/internal/security/VerityUtils.java
index 8770267..76f7b21 100644
--- a/core/java/com/android/internal/security/VerityUtils.java
+++ b/core/java/com/android/internal/security/VerityUtils.java
@@ -18,28 +18,15 @@
import android.annotation.NonNull;
import android.os.Build;
-import android.os.SharedMemory;
import android.os.SystemProperties;
-import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
-import android.util.Pair;
import android.util.Slog;
-import android.util.apk.ApkSignatureVerifier;
-import android.util.apk.ByteBufferFactory;
-import android.util.apk.SignatureNotFoundException;
-
-import libcore.util.HexEncoding;
import java.io.File;
-import java.io.FileDescriptor;
import java.io.IOException;
-import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;
-import java.security.DigestException;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
/** Provides fsverity related operations. */
public abstract class VerityUtils {
@@ -57,8 +44,6 @@
/** SHA256 hash size. */
private static final int HASH_SIZE_BYTES = 32;
- private static final boolean DEBUG = false;
-
public static boolean isFsVeritySupported() {
return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R
|| SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
@@ -123,204 +108,4 @@
private static native int measureFsverityNative(@NonNull String filePath,
@NonNull byte[] digest);
private static native int statxForFsverityNative(@NonNull String filePath);
-
- /**
- * Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped.
- *
- * @deprecated This is only used for previous fs-verity implementation, and should never be used
- * on new devices.
- * @return {@code SetupResult} that contains the result code, and when success, the
- * {@code FileDescriptor} to read all the data from.
- */
- @Deprecated
- public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) {
- if (DEBUG) {
- Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath);
- }
- SharedMemory shm = null;
- try {
- final byte[] signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath);
- if (signedVerityHash == null) {
- if (DEBUG) {
- Slog.d(TAG, "Skip verity tree generation since there is no signed root hash");
- }
- return SetupResult.skipped();
- }
-
- Pair<SharedMemory, Integer> result =
- generateFsVerityIntoSharedMemory(apkPath, signedVerityHash);
- shm = result.first;
- int contentSize = result.second;
- FileDescriptor rfd = shm.getFileDescriptor();
- if (rfd == null || !rfd.valid()) {
- return SetupResult.failed();
- }
- return SetupResult.ok(Os.dup(rfd), contentSize);
- } catch (IOException | SecurityException | DigestException | NoSuchAlgorithmException
- | SignatureNotFoundException | ErrnoException e) {
- Slog.e(TAG, "Failed to set up apk verity: ", e);
- return SetupResult.failed();
- } finally {
- if (shm != null) {
- shm.close();
- }
- }
- }
-
- /**
- * {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}.
- * @deprecated This is only used for previous fs-verity implementation, and should never be used
- * on new devices.
- */
- @Deprecated
- public static byte[] generateApkVerityRootHash(@NonNull String apkPath)
- throws NoSuchAlgorithmException, DigestException, IOException {
- return ApkSignatureVerifier.generateApkVerityRootHash(apkPath);
- }
-
- /**
- * {@see ApkSignatureVerifier#getVerityRootHash(String)}.
- * @deprecated This is only used for previous fs-verity implementation, and should never be used
- * on new devices.
- */
- @Deprecated
- public static byte[] getVerityRootHash(@NonNull String apkPath)
- throws IOException, SignatureNotFoundException {
- return ApkSignatureVerifier.getVerityRootHash(apkPath);
- }
-
- /**
- * Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains
- * Merkle tree and fsverity headers for the given apk, in the form that can immediately be used
- * for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has
- * length equals to the returned {@code Integer}.
- */
- private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(String apkPath,
- @NonNull byte[] expectedRootHash)
- throws IOException, DigestException, NoSuchAlgorithmException,
- SignatureNotFoundException {
- TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory();
- byte[] generatedRootHash =
- ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory);
- // We only generate Merkle tree once here, so it's important to make sure the root hash
- // matches the signed one in the apk.
- if (!Arrays.equals(expectedRootHash, generatedRootHash)) {
- throw new SecurityException("verity hash mismatch: "
- + bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash));
- }
-
- int contentSize = shmBufferFactory.getBufferLimit();
- SharedMemory shm = shmBufferFactory.releaseSharedMemory();
- if (shm == null) {
- throw new IllegalStateException("Failed to generate verity tree into shared memory");
- }
- if (!shm.setProtect(OsConstants.PROT_READ)) {
- throw new SecurityException("Failed to set up shared memory correctly");
- }
- return Pair.create(shm, contentSize);
- }
-
- private static String bytesToString(byte[] bytes) {
- return HexEncoding.encodeToString(bytes);
- }
-
- /**
- * @deprecated This is only used for previous fs-verity implementation, and should never be used
- * on new devices.
- */
- @Deprecated
- public static class SetupResult {
- /** Result code if verity is set up correctly. */
- private static final int RESULT_OK = 1;
-
- /** Result code if signature is not provided. */
- private static final int RESULT_SKIPPED = 2;
-
- /** Result code if the setup failed. */
- private static final int RESULT_FAILED = 3;
-
- private final int mCode;
- private final FileDescriptor mFileDescriptor;
- private final int mContentSize;
-
- /** @deprecated */
- @Deprecated
- public static SetupResult ok(@NonNull FileDescriptor fileDescriptor, int contentSize) {
- return new SetupResult(RESULT_OK, fileDescriptor, contentSize);
- }
-
- /** @deprecated */
- @Deprecated
- public static SetupResult skipped() {
- return new SetupResult(RESULT_SKIPPED, null, -1);
- }
-
- /** @deprecated */
- @Deprecated
- public static SetupResult failed() {
- return new SetupResult(RESULT_FAILED, null, -1);
- }
-
- private SetupResult(int code, FileDescriptor fileDescriptor, int contentSize) {
- this.mCode = code;
- this.mFileDescriptor = fileDescriptor;
- this.mContentSize = contentSize;
- }
-
- public boolean isFailed() {
- return mCode == RESULT_FAILED;
- }
-
- public boolean isOk() {
- return mCode == RESULT_OK;
- }
-
- public @NonNull FileDescriptor getUnownedFileDescriptor() {
- return mFileDescriptor;
- }
-
- public int getContentSize() {
- return mContentSize;
- }
- }
-
- /** A {@code ByteBufferFactory} that creates a shared memory backed {@code ByteBuffer}. */
- private static class TrackedShmBufferFactory implements ByteBufferFactory {
- private SharedMemory mShm;
- private ByteBuffer mBuffer;
-
- @Override
- public ByteBuffer create(int capacity) {
- try {
- if (DEBUG) Slog.d(TAG, "Creating shared memory for apk verity");
- // NB: This method is supposed to be called once according to the contract with
- // ApkSignatureSchemeV2Verifier.
- if (mBuffer != null) {
- throw new IllegalStateException("Multiple instantiation from this factory");
- }
- mShm = SharedMemory.create("apkverity", capacity);
- if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) {
- throw new SecurityException("Failed to set protection");
- }
- mBuffer = mShm.mapReadWrite();
- return mBuffer;
- } catch (ErrnoException e) {
- throw new SecurityException("Failed to set protection", e);
- }
- }
-
- public SharedMemory releaseSharedMemory() {
- if (mBuffer != null) {
- SharedMemory.unmap(mBuffer);
- mBuffer = null;
- }
- SharedMemory tmp = mShm;
- mShm = null;
- return tmp;
- }
-
- public int getBufferLimit() {
- return mBuffer == null ? -1 : mBuffer.limit();
- }
- }
}
diff --git a/core/java/com/android/internal/util/FileRotator.java b/core/java/com/android/internal/util/FileRotator.java
index 3ca3320..4b3af15 100644
--- a/core/java/com/android/internal/util/FileRotator.java
+++ b/core/java/com/android/internal/util/FileRotator.java
@@ -17,7 +17,7 @@
package com.android.internal.util;
import android.os.FileUtils;
-import android.util.Slog;
+import android.util.Log;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -32,7 +32,6 @@
import java.util.zip.ZipOutputStream;
import libcore.io.IoUtils;
-import libcore.io.Streams;
/**
* Utility that rotates files over time, similar to {@code logrotate}. There is
@@ -47,6 +46,8 @@
* <p>
* Users must periodically call {@link #maybeRotate(long)} to perform actual
* rotation. Not inherently thread safe.
+ *
+ * @hide
*/
public class FileRotator {
private static final String TAG = "FileRotator";
@@ -110,7 +111,7 @@
if (!name.startsWith(mPrefix)) continue;
if (name.endsWith(SUFFIX_BACKUP)) {
- if (LOGD) Slog.d(TAG, "recovering " + name);
+ if (LOGD) Log.d(TAG, "recovering " + name);
final File backupFile = new File(mBasePath, name);
final File file = new File(
@@ -120,7 +121,7 @@
backupFile.renameTo(file);
} else if (name.endsWith(SUFFIX_NO_BACKUP)) {
- if (LOGD) Slog.d(TAG, "recovering " + name);
+ if (LOGD) Log.d(TAG, "recovering " + name);
final File noBackupFile = new File(mBasePath, name);
final File file = new File(
@@ -231,7 +232,7 @@
* if the write fails.
*/
private void rewriteSingle(Rewriter rewriter, String name) throws IOException {
- if (LOGD) Slog.d(TAG, "rewriting " + name);
+ if (LOGD) Log.d(TAG, "rewriting " + name);
final File file = new File(mBasePath, name);
final File backupFile;
@@ -291,7 +292,7 @@
// read file when it overlaps
if (info.startMillis <= matchEndMillis && matchStartMillis <= info.endMillis) {
- if (LOGD) Slog.d(TAG, "reading matching " + name);
+ if (LOGD) Log.d(TAG, "reading matching " + name);
final File file = new File(mBasePath, name);
readFile(file, reader);
@@ -348,7 +349,7 @@
if (info.isActive()) {
if (info.startMillis <= rotateBefore) {
// found active file; rotate if old enough
- if (LOGD) Slog.d(TAG, "rotating " + name);
+ if (LOGD) Log.d(TAG, "rotating " + name);
info.endMillis = currentTimeMillis;
@@ -358,7 +359,7 @@
}
} else if (info.endMillis <= deleteBefore) {
// found rotated file; delete if old enough
- if (LOGD) Slog.d(TAG, "deleting " + name);
+ if (LOGD) Log.d(TAG, "deleting " + name);
final File file = new File(mBasePath, name);
file.delete();
@@ -383,7 +384,10 @@
writer.write(bos);
bos.flush();
} finally {
- FileUtils.sync(fos);
+ try {
+ fos.getFD().sync();
+ } catch (IOException e) {
+ }
IoUtils.closeQuietly(bos);
}
}
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 2b7f8b2..354dd9a 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -4,3 +4,4 @@
per-file *ContrastColor* = file:/services/core/java/com/android/server/notification/OWNERS
per-file Protocol* = etancohen@google.com, lorenzo@google.com
per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
+per-file *Dump* = file:/core/java/com/android/internal/util/dump/OWNERS
diff --git a/core/java/com/android/internal/util/dump/OWNERS b/core/java/com/android/internal/util/dump/OWNERS
new file mode 100644
index 0000000..ce9302a
--- /dev/null
+++ b/core/java/com/android/internal/util/dump/OWNERS
@@ -0,0 +1,2 @@
+omakoto@google.com
+felipeal@google.com
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 07b16ed..dd2015d 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -195,7 +195,6 @@
"android_util_FileObserver.cpp",
"android/opengl/poly_clip.cpp", // TODO: .arm
"android/opengl/util.cpp",
- "android_server_NetworkManagementSocketTagger.cpp",
"android_ddm_DdmHandleNativeHeap.cpp",
"android_backup_BackupDataInput.cpp",
"android_backup_BackupDataOutput.cpp",
@@ -245,7 +244,6 @@
"libandroid_net",
"libandroidicu",
"libbpf_android",
- "libnetdbpf",
"libnetdutils",
"libmemtrack",
"libandroidfw",
@@ -300,6 +298,8 @@
"libdl_android",
"libtimeinstate",
"server_configurable_flags",
+ // TODO: delete when ConnectivityT moves to APEX.
+ "libframework-connectivity-tiramisu-jni",
],
export_shared_lib_headers: [
// our headers include libnativewindow's public headers
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 0f98b74..1c4107a 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -164,7 +164,6 @@
extern int register_android_text_Hyphenator(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
-extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
extern int register_android_backup_BackupDataInput(JNIEnv *env);
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
@@ -1618,7 +1617,6 @@
REG_JNI(register_android_media_midi),
REG_JNI(register_android_opengl_classes),
- REG_JNI(register_android_server_NetworkManagementSocketTagger),
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
REG_JNI(register_android_backup_BackupDataInput),
REG_JNI(register_android_backup_BackupDataOutput),
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 832c498..a17d807 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -62,6 +62,7 @@
### Graphics ###
per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
+per-file android_hardware_HardwareBuffer.cpp = file:/graphics/java/android/graphics/OWNERS
### Text ###
per-file android_text_* = file:/core/java/android/text/OWNERS
@@ -72,6 +73,9 @@
per-file AndroidRuntime.cpp = calin@google.com, ngeoffray@google.com, oth@google.com
# Although marked "view" this is mostly graphics stuff
per-file android_view_* = file:/graphics/java/android/graphics/OWNERS
+# File used for Android Studio layoutlib
+per-file LayoutlibLoader.cpp = file:/graphics/java/android/graphics/OWNERS
+per-file LayoutlibLoader.cpp = diegoperez@google.com, jgaillard@google.com
# Verity
per-file com_android_internal_security_Verity* = ebiggers@google.com, victorhsieh@google.com
diff --git a/core/jni/android/opengl/OWNERS b/core/jni/android/opengl/OWNERS
new file mode 100644
index 0000000..ce4b907
--- /dev/null
+++ b/core/jni/android/opengl/OWNERS
@@ -0,0 +1 @@
+file:/graphics/java/android/graphics/OWNERS
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index 845d65c..a022842 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -16,20 +16,19 @@
#define LOG_TAG "UsbDeviceConnectionJNI"
-#include "utils/Log.h"
-
-#include "jni.h"
+#include <fcntl.h>
#include <nativehelper/JNIPlatformHelp.h>
-#include "core_jni_helpers.h"
-
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <usbhost/usbhost.h>
+#include <usbhost/usbhost_jni.h>
#include <chrono>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
+#include "core_jni_helpers.h"
+#include "jni.h"
+#include "utils/Log.h"
using namespace android;
using namespace std::chrono;
@@ -91,22 +90,8 @@
static jbyteArray
android_hardware_UsbDeviceConnection_get_desc(JNIEnv *env, jobject thiz)
{
- char buffer[16384];
int fd = android_hardware_UsbDeviceConnection_get_fd(env, thiz);
- if (fd < 0) return NULL;
- lseek(fd, 0, SEEK_SET);
- int length = read(fd, buffer, sizeof(buffer));
- if (length < 0) return NULL;
-
- jbyteArray ret = env->NewByteArray(length);
- if (ret) {
- jbyte* bytes = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
- if (bytes) {
- memcpy(bytes, buffer, length);
- env->ReleasePrimitiveArrayCritical(ret, bytes, 0);
- }
- }
- return ret;
+ return usb_jni_read_descriptors(env, fd);
}
static jboolean
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
deleted file mode 100644
index 1be1873..0000000
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2011, 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 LOG_TAG "NMST_QTagUidNative"
-
-#include <android/multinetwork.h>
-#include <cutils/qtaguid.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <nativehelper/JNIPlatformHelp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include "jni.h"
-
-namespace android {
-
-static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor,
- jint tagNum, jint uid) {
- int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (env->ExceptionCheck()) {
- ALOGE("Can't get FileDescriptor num");
- return (jint)-1;
- }
-
- int res = android_tag_socket_with_uid(userFd, tagNum, uid);
- if (res < 0) {
- return (jint)-errno;
- }
- return (jint)res;
-}
-
-static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
- int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (env->ExceptionCheck()) {
- ALOGE("Can't get FileDescriptor num");
- return (jint)-1;
- }
-
- int res = android_untag_socket(userFd);
- if (res < 0) {
- return (jint)-errno;
- }
- return (jint)res;
-}
-
-static jint setCounterSet(JNIEnv* env, jclass, jint setNum, jint uid) {
- int res = qtaguid_setCounterSet(setNum, uid);
- if (res < 0) {
- return (jint)-errno;
- }
- return (jint)res;
-}
-
-static jint deleteTagData(JNIEnv* env, jclass, jint tagNum, jint uid) {
- int res = qtaguid_deleteTagData(tagNum, uid);
- if (res < 0) {
- return (jint)-errno;
- }
- return (jint)res;
-}
-
-static const JNINativeMethod gQTagUidMethods[] = {
- { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)tagSocketFd},
- { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)untagSocketFd},
- { "native_setCounterSet", "(II)I", (void*)setCounterSet},
- { "native_deleteTagData", "(II)I", (void*)deleteTagData},
-};
-
-int register_android_server_NetworkManagementSocketTagger(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/NetworkManagementSocketTagger", gQTagUidMethods, NELEM(gQTagUidMethods));
-}
-
-};
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 61b91dd..13ca133 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -873,7 +873,7 @@
const char* exceptionToThrow;
char msg[128];
// TransactionTooLargeException is a checked exception, only throw from certain methods.
- // FIXME: Transaction too large is the most common reason for FAILED_TRANSACTION
+ // TODO(b/28321379): Transaction size is the most common cause for FAILED_TRANSACTION
// but it is not the only one. The Binder driver can return BR_FAILED_REPLY
// for other reasons also, such as if the transaction is malformed or
// refers to an FD that has been closed. We should change the driver
@@ -890,8 +890,9 @@
exceptionToThrow = (canThrowRemoteException)
? "android/os/DeadObjectException"
: "java/lang/RuntimeException";
- snprintf(msg, sizeof(msg)-1,
- "Transaction failed on small parcel; remote process probably died");
+ snprintf(msg, sizeof(msg) - 1,
+ "Transaction failed on small parcel; remote process probably died, but "
+ "this could also be caused by running out of binder buffer space");
}
jniThrowException(env, exceptionToThrow, msg);
} break;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index aacf700..5efc4db 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -202,6 +202,8 @@
*/
static constexpr int STORAGE_DIR_CHECK_TIMEOUT_US = 1000 * 1000 * 60 * 5;
+static void WaitUntilDirReady(const std::string& target, fail_fn_t fail_fn);
+
/**
* A helper class containing accounting information for USAPs.
*/
@@ -1249,7 +1251,11 @@
auto volPath = StringPrintf("%s/%s", externalPrivateMountPath, ent->d_name);
auto cePath = StringPrintf("%s/user", volPath.c_str());
auto dePath = StringPrintf("%s/user_de", volPath.c_str());
+ // Wait until dir user is created.
+ WaitUntilDirReady(cePath.c_str(), fail_fn);
MountAppDataTmpFs(cePath.c_str(), fail_fn);
+ // Wait until dir user_de is created.
+ WaitUntilDirReady(dePath.c_str(), fail_fn);
MountAppDataTmpFs(dePath.c_str(), fail_fn);
}
closedir(dir);
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 931ef44..43d2439 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -17,7 +17,8 @@
per-file apphibernationservice.proto = file:/core/java/android/apphibernation/OWNERS
# Biometrics
-kchyn@google.com
+jaggies@google.com
+jbolinger@google.com
# Launcher
hyunyoungs@google.com
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 998ec96..51e150e 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -249,7 +249,8 @@
optional android.service.NetworkStatsServiceDumpProto netstats = 3001 [
(section).type = SECTION_DUMPSYS,
- (section).args = "netstats --proto"
+ (section).args = "netstats --proto",
+ (section).userdebug_and_eng_only = true
];
optional android.providers.settings.SettingsServiceDumpProto settings = 3002 [
diff --git a/core/proto/android/service/netstats.proto b/core/proto/android/service/netstats.proto
index c8cdfdd..ba2b6d6b 100644
--- a/core/proto/android/service/netstats.proto
+++ b/core/proto/android/service/netstats.proto
@@ -17,15 +17,11 @@
syntax = "proto2";
package android.service;
-import "frameworks/base/core/proto/android/privacy.proto";
-
option java_multiple_files = true;
option java_outer_classname = "NetworkStatsServiceProto";
// Represents dumpsys from NetworkStatsService (netstats).
message NetworkStatsServiceDumpProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
repeated NetworkInterfaceProto active_interfaces = 1;
repeated NetworkInterfaceProto active_uid_interfaces = 2;
@@ -45,8 +41,6 @@
// Corresponds to NetworkStatsService.mActiveIfaces/mActiveUidIfaces.
message NetworkInterfaceProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
// Name of the network interface (eg: wlan).
optional string interface = 1;
@@ -55,26 +49,14 @@
// Corresponds to NetworkIdentitySet.
message NetworkIdentitySetProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
repeated NetworkIdentityProto identities = 1;
}
// Corresponds to NetworkIdentity.
message NetworkIdentityProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
// Constants from ConnectivityManager.TYPE_*.
optional int32 type = 1;
- // Full subscriber ID on eng builds. The IMSI is scrubbed on user & userdebug
- // builds to only include the info about the GSM network operator (the info
- // that uniquely identifies the subscriber is removed).
- optional string subscriber_id = 2 [ (android.privacy).dest = DEST_EXPLICIT ];
-
- // Name of the network (eg: MyWifi).
- optional string network_id = 3 [ (android.privacy).dest = DEST_EXPLICIT ];
-
optional bool roaming = 4;
optional bool metered = 5;
@@ -86,8 +68,6 @@
// Corresponds to NetworkStatsRecorder.
message NetworkStatsRecorderProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
optional int64 pending_total_bytes = 1;
optional NetworkStatsCollectionProto complete_history = 2;
@@ -95,15 +75,11 @@
// Corresponds to NetworkStatsCollection.
message NetworkStatsCollectionProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
repeated NetworkStatsCollectionStatsProto stats = 1;
}
// Corresponds to NetworkStatsCollection.mStats.
message NetworkStatsCollectionStatsProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
optional NetworkStatsCollectionKeyProto key = 1;
optional NetworkStatsHistoryProto history = 2;
@@ -111,8 +87,6 @@
// Corresponds to NetworkStatsCollection.Key.
message NetworkStatsCollectionKeyProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
optional NetworkIdentitySetProto identity = 1;
optional int32 uid = 2;
@@ -124,8 +98,6 @@
// Corresponds to NetworkStatsHistory.
message NetworkStatsHistoryProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
// Duration for this bucket in milliseconds.
optional int64 bucket_duration_ms = 1;
@@ -134,8 +106,6 @@
// Corresponds to each bucket in NetworkStatsHistory.
message NetworkStatsHistoryBucketProto {
- option (android.msg_privacy).dest = DEST_AUTOMATIC;
-
// Bucket start time in milliseconds since epoch.
optional int64 bucket_start_ms = 1;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6bcaace9..111b694 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1945,6 +1945,11 @@
<permission android:name="android.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE"
android:protectionLevel="signature" />
+ <!-- @SystemApi @hide Allows an application to manage ethernet networks.
+ <p>Not for use by third-party or privileged applications. -->
+ <permission android:name="android.permission.MANAGE_ETHERNET_NETWORKS"
+ android:protectionLevel="signature" />
+
<!-- ======================================= -->
<!-- Permissions for short range, peripheral networks -->
<!-- ======================================= -->
@@ -3453,6 +3458,13 @@
<permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES"
android:protectionLevel="signature|privileged|development" />
+ <!-- @hide @SystemApi Must be required by a
+ {@link com.android.service.tracing.TraceReportService}, to ensure that only the system
+ can bind to it.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.BIND_TRACE_REPORT_SERVICE"
+ android:protectionLevel="signature" />
+
<!-- @hide @SystemApi @TestApi
Allow an application to approve incident and bug reports to be
shared off-device. There can be only one application installed on the
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2f33498..ba647d7 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -134,9 +134,6 @@
be sent during a change to the audio output device. -->
<bool name="config_sendAudioBecomingNoisy">true</bool>
- <!-- Whether Hearing Aid profile is supported -->
- <bool name="config_hearing_aid_profile_supported">false</bool>
-
<!-- Flag to disable all transition animations -->
<bool name="config_disableTransitionAnimation">false</bool>
@@ -404,10 +401,6 @@
<string-array translatable="false" name="config_tether_bluetooth_regexs">
</string-array>
- <!-- Max number of Bluetooth tethering connections allowed. If this is
- updated config_tether_dhcp_range has to be updated appropriately. -->
- <integer translatable="false" name="config_max_pan_devices">5</integer>
-
<!-- This setting is deprecated, please use
com.android.networkstack.tethering.R.array.config_dhcp_range instead. -->
<string-array translatable="false" name="config_tether_dhcp_range">
@@ -1820,53 +1813,38 @@
<!-- Integer to set a max latency the accelerometer will batch sensor requests with. -->
<integer name="config_flipToScreenOffMaxLatencyMicros">2000000</integer>
- <!-- Boolean indicating if current platform supports bluetooth SCO for off call
- use cases -->
+ <!-- Note: This config is deprecated
+ Boolean indicating if current platform supports bluetooth SCO for off call
+ use cases
+ -->
<bool name="config_bluetooth_sco_off_call">true</bool>
- <!-- Boolean indicating if current platform supports bluetooth wide band
- speech -->
- <bool name="config_bluetooth_wide_band_speech">true</bool>
-
- <!-- Boolean indicating if current platform need do one-time bluetooth address
- re-validation -->
+ <!-- Note: This config is deprecated
+ Boolean indicating if current platform need do one-time bluetooth address
+ re-validation
+ -->
<bool name="config_bluetooth_address_validation">false</bool>
- <!-- Boolean indicating if current platform supports BLE peripheral mode -->
- <bool name="config_bluetooth_le_peripheral_mode_supported">false</bool>
-
- <!-- Boolean indicating if current platform supports HFP inband ringing -->
- <bool name="config_bluetooth_hfp_inband_ringing_support">false</bool>
-
- <!-- Max number of scan filters supported by blutooth controller. 0 if the
- device does not support hardware scan filters-->
- <integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer>
-
- <!-- Max number of advertisers supported by bluetooth controller. 0 if the
- device does not support multiple advertisement-->
- <integer translatable="false" name="config_bluetooth_max_advertisers">0</integer>
-
- <!-- Idle current for bluetooth controller. 0 by default-->
+ <!-- Note: This config is deprecated, use BluetoothProperties instead.
+ Idle current for bluetooth controller. 0 by default
+ -->
<integer translatable="false" name="config_bluetooth_idle_cur_ma">0</integer>
- <!-- Rx current for bluetooth controller. 0 by default-->
+ <!-- Note: This config is deprecated, use BluetoothProperties instead.
+ Rx current for bluetooth controller. 0 by default
+ -->
<integer translatable="false" name="config_bluetooth_rx_cur_ma">0</integer>
- <!-- Tx current for bluetooth controller. 0 by default-->
+ <!-- Note: This config is deprecated, use BluetoothProperties instead.
+ Tx current for bluetooth controller. 0 by default
+ -->
<integer translatable="false" name="config_bluetooth_tx_cur_ma">0</integer>
- <!-- Operating volatage for bluetooth controller. 0 by default-->
+ <!-- Note: This config is deprecated, use BluetoothProperties instead.
+ Operating volatage for bluetooth controller. 0 by default
+ -->
<integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer>
- <!-- Max number of connected audio devices supported by Bluetooth stack -->
- <integer name="config_bluetooth_max_connected_audio_devices">5</integer>
-
- <!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
- <bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
-
- <!-- Enabling autoconnect over pan -->
- <bool name="config_bluetooth_pan_enable_autoconnect">false</bool>
-
<!-- The default data-use polling period. -->
<integer name="config_datause_polling_period_sec">600</integer>
@@ -2007,10 +1985,6 @@
<!-- The name of the package that will be allowed to change its components' label/icon. -->
<string name="config_overrideComponentUiPackage" translatable="false">com.android.stk</string>
- <!-- Enable/disable default bluetooth profiles:
- HSP_AG, ObexObjectPush, Audio, NAP -->
- <bool name="config_bluetooth_default_profiles">true</bool>
-
<!-- IP address of the dns server to use if nobody else suggests one -->
<string name="config_default_dns_server" translatable="false">8.8.8.8</string>
@@ -4141,8 +4115,6 @@
<!-- Component name that should be granted Notification Assistant access -->
<string name="config_defaultAssistantAccessComponent" translatable="false">android.ext.services/android.ext.services.notification.Assistant</string>
- <bool name="config_supportBluetoothPersistedState">true</bool>
-
<bool name="config_keepRestrictedProfilesInBackground">true</bool>
<!-- Cellular network service package name to bind to by default. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2403a60..6ef5bd4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3200,11 +3200,87 @@
<!-- @hide For use by platform and tools only. Developers should not specify this value. -->
<public type="string" name="config_defaultRingtoneVibrationSound" id="0x0104003b" />
+ <!-- ===============================================================
+ Resources added in version T of the platform
+
+ NOTE: add <public> elements within a <staging-public-group> like so:
+
+ <staging-public-group type="attr" first-id="0x01ff0000">
+ <public name="exampleAttr1" />
+ <public name="exampleAttr2" />
+ </staging-public-group>
+
+ To add a new <staging-public-group> block, find the id value for the
+ last <staging-public-group> block defined for thie API level, and
+ subtract 0x00010000 from it to get to the id of the new block.
+
+ For example, if the block closest to the end of this file has an id
+ of 0x01ee0000, the id of the new block should be 0x01ed0000
+ (0x01ee0000 - 0x00010000 = 0x01ed0000).
+ =============================================================== -->
+ <eat-comment />
+
+ <staging-public-group type="attr" first-id="0x01df0000">
+ </staging-public-group>
+
+ <staging-public-group type="id" first-id="0x01de0000">
+ </staging-public-group>
+
+ <staging-public-group type="style" first-id="0x0dfd0000">
+ </staging-public-group>
+
+ <staging-public-group type="string" first-id="0x0dfc0000">
+ </staging-public-group>
+
+ <staging-public-group type="dimen" first-id="0x01db0000">
+ </staging-public-group>
+
+ <staging-public-group type="color" first-id="0x01da0000">
+ </staging-public-group>
+
+ <staging-public-group type="array" first-id="0x01d90000">
+ <!-- @hide @SystemApi -->
+ <public name="config_optionalIpSecAlgorithms" />
+ </staging-public-group>
+
+ <staging-public-group type="drawable" first-id="0x01d80000">
+ </staging-public-group>
+
+ <staging-public-group type="layout" first-id="0x01d70000">
+ </staging-public-group>
+
+ <staging-public-group type="anim" first-id="0x01d60000">
+ </staging-public-group>
+
+ <staging-public-group type="animator" first-id="0x01d50000">
+ </staging-public-group>
+
+ <staging-public-group type="interpolator" first-id="0x01d40000">
+ </staging-public-group>
+
+ <staging-public-group type="mipmap" first-id="0x01d30000">
+ </staging-public-group>
+
+ <staging-public-group type="integer" first-id="0x01d20000">
+ </staging-public-group>
+
+ <staging-public-group type="transition" first-id="0x01d10000">
+ </staging-public-group>
+
+ <staging-public-group type="raw" first-id="0x01d00000">
+ </staging-public-group>
+
+ <staging-public-group type="bool" first-id="0x01cf0000">
+ </staging-public-group>
+
+ <staging-public-group type="fraction" first-id="0x01ce0000">
+ </staging-public-group>
+
<!-- ===============================================================
DO NOT ADD UN-GROUPED ITEMS HERE
Any new items (attrs, styles, ids, etc.) *must* be added in a
- public-group block, as the preceding comment explains.
+ staging-public-group block, as the preceding comment explains.
Items added outside of a group may have their value recalculated
every time something new is added to this file.
=============================================================== -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4db6499..590fcf4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -278,8 +278,6 @@
<java-symbol type="bool" name="config_flipToScreenOffEnabled" />
<java-symbol type="integer" name="config_flipToScreenOffMaxLatencyMicros" />
<java-symbol type="bool" name="config_bluetooth_sco_off_call" />
- <java-symbol type="bool" name="config_bluetooth_le_peripheral_mode_supported" />
- <java-symbol type="bool" name="config_bluetooth_hfp_inband_ringing_support" />
<java-symbol type="bool" name="config_cellBroadcastAppLinks" />
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_disableTransitionAnimation" />
@@ -343,7 +341,6 @@
<java-symbol type="integer" name="config_timeZoneRulesCheckRetryCount" />
<java-symbol type="bool" name="config_sendAudioBecomingNoisy" />
<java-symbol type="bool" name="config_enableScreenshotChord" />
- <java-symbol type="bool" name="config_bluetooth_default_profiles" />
<java-symbol type="bool" name="config_enableWifiDisplay" />
<java-symbol type="bool" name="config_allowAnimationsInLowPowerMode" />
<java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
@@ -417,9 +414,6 @@
<java-symbol type="dimen" name="config_pictureInPictureMaxAspectRatio" />
<java-symbol type="integer" name="config_pictureInPictureMaxNumberOfActions" />
<java-symbol type="dimen" name="config_closeToSquareDisplayMaxAspectRatio" />
- <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
- <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
- <java-symbol type="integer" name="config_bluetooth_max_connected_audio_devices" />
<java-symbol type="integer" name="config_burnInProtectionMinHorizontalOffset" />
<java-symbol type="integer" name="config_burnInProtectionMaxHorizontalOffset" />
<java-symbol type="integer" name="config_burnInProtectionMinVerticalOffset" />
@@ -429,9 +423,6 @@
<java-symbol type="integer" name="config_bluetooth_rx_cur_ma" />
<java-symbol type="integer" name="config_bluetooth_tx_cur_ma" />
<java-symbol type="integer" name="config_bluetooth_operating_voltage_mv" />
- <java-symbol type="bool" name="config_bluetooth_pan_enable_autoconnect" />
- <java-symbol type="bool" name="config_bluetooth_reload_supported_profiles_when_enabled" />
- <java-symbol type="bool" name="config_hearing_aid_profile_supported" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_drawLockTimeoutMillis" />
<java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
@@ -450,7 +441,6 @@
<java-symbol type="integer" name="config_wakeUpToLastStateTimeoutMillis" />
<java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" />
<java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" />
- <java-symbol type="integer" name="config_max_pan_devices" />
<java-symbol type="integer" name="config_ntpPollingInterval" />
<java-symbol type="integer" name="config_ntpPollingIntervalShorter" />
<java-symbol type="integer" name="config_ntpRetry" />
@@ -3782,8 +3772,6 @@
<java-symbol type="string" name="config_defaultAssistantAccessComponent" />
- <java-symbol type="bool" name="config_supportBluetoothPersistedState" />
-
<java-symbol type="string" name="slices_permission_request" />
<java-symbol type="string" name="screenshot_edit" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 4c20ae1..d1d86a7 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -154,9 +154,9 @@
<!-- Israel: 4 digits, known premium codes listed -->
<shortcode country="il" pattern="\\d{4}" premium="4422|4545" />
- <!-- Italy: 5 digits (premium=4xxxx), plus EU:
- http://clients.txtnation.com/attachments/token/di5kfblvubttvlw/?name=Italy_CASP_EN.pdf -->
- <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503" standard="43\\d{3}" />
+ <!-- Italy: 5 digits (premium=41xxx,42xxx), plus EU:
+ https://www.itu.int/dms_pub/itu-t/oth/02/02/T020200006B0001PDFE.pdf -->
+ <shortcode country="it" pattern="\\d{5}" premium="4\\d{4}" free="116\\d{3}|4112503|40\\d{0,12}" standard="430\\d{2}|431\\d{2}|434\\d{4}|435\\d{4}|439\\d{7}" />
<!-- Japan: 8083 used by SOFTBANK_DCB_2 -->
<shortcode country="jp" pattern="\\d{1,5}" free="8083" />
diff --git a/core/tests/coretests/src/android/view/OWNERS b/core/tests/coretests/src/android/view/OWNERS
index 74cdd21..10f6f1f 100644
--- a/core/tests/coretests/src/android/view/OWNERS
+++ b/core/tests/coretests/src/android/view/OWNERS
@@ -16,3 +16,6 @@
# Scroll Capture
per-file *ScrollCapture*.java = file:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS
+
+# Stylus
+per-file stylus/* = file:/core/java/android/text/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
index 74b6dbe..93910b9 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -39,6 +39,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import libcore.testing.io.TestIoUtils;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -52,8 +54,11 @@
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
private static final long MINUTE_IN_MS = 60 * 1000;
+ private final File mHistoryDir =
+ TestIoUtils.createTemporaryDirectory(getClass().getSimpleName());
+
@Rule
- public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345)
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345, mHistoryDir)
.setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0);
@Test
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index 083090c..2c6f5fa 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -40,6 +40,7 @@
import org.junit.runners.model.Statement;
import org.mockito.stubbing.Answer;
+import java.io.File;
import java.util.Arrays;
public class BatteryUsageStatsRule implements TestRule {
@@ -57,14 +58,18 @@
private boolean mScreenOn;
public BatteryUsageStatsRule() {
- this(0);
+ this(0, null);
}
public BatteryUsageStatsRule(long currentTime) {
+ this(currentTime, null);
+ }
+
+ public BatteryUsageStatsRule(long currentTime, File historyDir) {
Context context = InstrumentationRegistry.getContext();
mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
mMockClocks.currentTime = currentTime;
- mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
+ mBatteryStats = new MockBatteryStatsImpl(mMockClocks, historyDir);
mBatteryStats.setPowerProfile(mPowerProfile);
mBatteryStats.onSystemReady();
}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index db0c934..11d20f2 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -29,6 +29,7 @@
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
import com.android.internal.power.MeasuredEnergyStats;
+import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Queue;
@@ -40,10 +41,16 @@
public class MockBatteryStatsImpl extends BatteryStatsImpl {
public BatteryStatsImpl.Clocks clocks;
public boolean mForceOnBattery;
+ // The mNetworkStats will be used for both wifi and mobile categories
private NetworkStats mNetworkStats;
MockBatteryStatsImpl(Clocks clocks) {
- super(clocks);
+ this(clocks, null);
+ }
+
+ MockBatteryStatsImpl(Clocks clocks, File historyDirectory) {
+ super(clocks, historyDirectory);
+
this.clocks = mClocks;
initTimersAndCounters();
@@ -107,11 +114,16 @@
}
@Override
- protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager,
- String[] ifaces) {
+ protected NetworkStats readMobileNetworkStatsLocked(
+ @NonNull NetworkStatsManager networkStatsManager) {
return mNetworkStats;
}
+ @Override
+ protected NetworkStats readWifiNetworkStatsLocked(
+ @NonNull NetworkStatsManager networkStatsManager) {
+ return mNetworkStats;
+ }
public MockBatteryStatsImpl setPowerProfile(PowerProfile powerProfile) {
mPowerProfile = powerProfile;
return this;
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 597ea14..12e52c6 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -288,9 +288,8 @@
}
@Override
- public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
- final int deviceType) {
- }
+ public void addVendorCommandListener(
+ final IHdmiVendorCommandListener listener, final int vendorId) {}
@Override
public void sendVendorCommand(final int deviceType, final int targetAddress,
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index fefcebe..fcd1799 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -390,6 +390,10 @@
<permission name="android.permission.SET_WALLPAPER" />
<permission name="android.permission.SET_WALLPAPER_COMPONENT" />
<permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
+ <!-- Permission required for CTS test - TrustTestCases -->
+ <permission name="android.permission.PROVIDE_TRUST_AGENT" />
+ <permission name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+ <permission name="android.permission.TRUST_LISTENER" />
<!-- Permissions required for Incremental CTS tests -->
<permission name="com.android.permission.USE_INSTALLER_V2"/>
<permission name="android.permission.LOADER_USAGE_STATS"/>
@@ -458,6 +462,8 @@
<!-- Permission needed for CTS test - WifiManagerTest -->
<permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+ <permission name="android.permission.NEARBY_WIFI_DEVICES" />
+ <permission name="android.permission.OVERRIDE_WIFI_CONFIG" />
<!-- Permission required for CTS test CarrierMessagingServiceWrapperTest -->
<permission name="android.permission.BIND_CARRIER_SERVICES"/>
<!-- Permission required for CTS test - MusicRecognitionManagerTest -->
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 42e470b..5bfc321 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1611,7 +1611,7 @@
* Return the paint's Align value for drawing text. This controls how the
* text is positioned relative to its origin. LEFT align means that all of
* the text will be drawn to the right of its origin (i.e. the origin
- * specifieds the LEFT edge of the text) and so on.
+ * specifies the LEFT edge of the text) and so on.
*
* @return the paint's Align value for drawing text.
*/
@@ -1623,7 +1623,7 @@
* Set the paint's text alignment. This controls how the
* text is positioned relative to its origin. LEFT align means that all of
* the text will be drawn to the right of its origin (i.e. the origin
- * specifieds the LEFT edge of the text) and so on.
+ * specifies the LEFT edge of the text) and so on.
*
* @param align set the paint's Align value for drawing text.
*/
diff --git a/identity/java/android/security/identity/IdentityCredential.java b/identity/java/android/security/identity/IdentityCredential.java
index cdf746f..f440b69 100644
--- a/identity/java/android/security/identity/IdentityCredential.java
+++ b/identity/java/android/security/identity/IdentityCredential.java
@@ -454,7 +454,8 @@
* @param challenge is a non-empty byte array whose contents should be unique, fresh and
* provided by the issuing authority. The value provided is embedded in the
* generated CBOR and enables the issuing authority to verify that the
- * returned proof is fresh.
+ * returned proof is fresh. Implementations are required to support
+ * challenges at least 32 bytes of length.
* @return the COSE_Sign1 data structure above
*/
public @NonNull byte[] proveOwnership(@NonNull byte[] challenge) {
@@ -485,7 +486,8 @@
* @param challenge is a non-empty byte array whose contents should be unique, fresh and
* provided by the issuing authority. The value provided is embedded in the
* generated CBOR and enables the issuing authority to verify that the
- * returned proof is fresh.
+ * returned proof is fresh. Implementations are required to support
+ * challenges at least 32 bytes of length.
* @return the COSE_Sign1 data structure above
*/
public @NonNull byte[] delete(@NonNull byte[] challenge) {
diff --git a/identity/java/android/security/identity/WritableIdentityCredential.java b/identity/java/android/security/identity/WritableIdentityCredential.java
index 305d0ea..6d56964 100644
--- a/identity/java/android/security/identity/WritableIdentityCredential.java
+++ b/identity/java/android/security/identity/WritableIdentityCredential.java
@@ -59,7 +59,8 @@
* @param challenge is a non-empty byte array whose contents should be unique, fresh and
* provided by the issuing authority. The value provided is embedded in the
* attestation extension and enables the issuing authority to verify that the
- * attestation certificate is fresh.
+ * attestation certificate is fresh. Implementations are required to support
+ * challenges at least 32 bytes of length.
* @return the X.509 certificate for this credential's CredentialKey.
*/
public abstract @NonNull Collection<X509Certificate> getCredentialKeyCertificateChain(
diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java
index 1034847..3d53cfb 100644
--- a/keystore/java/android/security/KeyStore2.java
+++ b/keystore/java/android/security/KeyStore2.java
@@ -108,7 +108,7 @@
try {
return request.execute(service);
} catch (ServiceSpecificException e) {
- throw getKeyStoreException(e.errorCode);
+ throw getKeyStoreException(e.errorCode, e.getMessage());
} catch (RemoteException e) {
if (firstTry) {
Log.w(TAG, "Looks like we may have lost connection to the Keystore "
@@ -120,7 +120,7 @@
firstTry = false;
} else {
Log.e(TAG, "Cannot connect to Keystore daemon.", e);
- throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "");
+ throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
}
}
}
@@ -322,26 +322,32 @@
}
}
- static KeyStoreException getKeyStoreException(int errorCode) {
+ static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) {
if (errorCode > 0) {
// KeyStore layer error
switch (errorCode) {
case ResponseCode.LOCKED:
- return new KeyStoreException(errorCode, "User authentication required");
+ return new KeyStoreException(errorCode, "User authentication required",
+ serviceErrorMessage);
case ResponseCode.UNINITIALIZED:
- return new KeyStoreException(errorCode, "Keystore not initialized");
+ return new KeyStoreException(errorCode, "Keystore not initialized",
+ serviceErrorMessage);
case ResponseCode.SYSTEM_ERROR:
- return new KeyStoreException(errorCode, "System error");
+ return new KeyStoreException(errorCode, "System error", serviceErrorMessage);
case ResponseCode.PERMISSION_DENIED:
- return new KeyStoreException(errorCode, "Permission denied");
+ return new KeyStoreException(errorCode, "Permission denied",
+ serviceErrorMessage);
case ResponseCode.KEY_NOT_FOUND:
- return new KeyStoreException(errorCode, "Key not found");
+ return new KeyStoreException(errorCode, "Key not found", serviceErrorMessage);
case ResponseCode.VALUE_CORRUPTED:
- return new KeyStoreException(errorCode, "Key blob corrupted");
+ return new KeyStoreException(errorCode, "Key blob corrupted",
+ serviceErrorMessage);
case ResponseCode.KEY_PERMANENTLY_INVALIDATED:
- return new KeyStoreException(errorCode, "Key permanently invalidated");
+ return new KeyStoreException(errorCode, "Key permanently invalidated",
+ serviceErrorMessage);
default:
- return new KeyStoreException(errorCode, String.valueOf(errorCode));
+ return new KeyStoreException(errorCode, String.valueOf(errorCode),
+ serviceErrorMessage);
}
} else {
// Keymaster layer error
@@ -350,10 +356,12 @@
// The name of this parameter significantly differs between Keymaster and
// framework APIs. Use the framework wording to make life easier for developers.
return new KeyStoreException(errorCode,
- "Invalid user authentication validity duration");
+ "Invalid user authentication validity duration",
+ serviceErrorMessage);
default:
return new KeyStoreException(errorCode,
- KeymasterDefs.getErrorMessage(errorCode));
+ KeymasterDefs.getErrorMessage(errorCode),
+ serviceErrorMessage);
}
}
}
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index 30389a29d..54184db 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -16,25 +16,458 @@
package android.security;
+import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.security.keymaster.KeymasterDefs;
+import android.system.keystore2.ResponseCode;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
/**
- * KeyStore/keymaster exception with positive error codes coming from the KeyStore and negative
- * ones from keymaster.
+ * Exception containing information about the failure at the Keystore / KeyMint layer while
+ * generating or using a key.
*
- * @hide
+ * The public error codes indicate the cause of the error and the methods indicate whether
+ * it's a system/key issue and whether re-trying the operation (with the same key or a new key)
+ * is likely to succeed.
*/
-@TestApi
public class KeyStoreException extends Exception {
+ /**
+ * This error code is for mapping errors that the caller will not know about. If the caller is
+ * targeting an API level earlier than the one the error was introduced in, then the error will
+ * be mapped to this one.
+ * In API level 33 no errors map to this error.
+ */
+ public static final int ERROR_OTHER = 1;
+ /**
+ * Indicating the key could not be used because the user needs to authenticate first.
+ * See
+ * {@link android.security.keystore.KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}.
+ */
+ public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2;
+ /**
+ * Indicating that {@code load()} has not been called on the Keystore instance, or an attempt
+ * has been made to generate an authorization bound key while the user has not set a lock
+ * screen knowledge factor (LSKF). Instruct the user to set an LSKF and retry.
+ */
+ public static final int ERROR_KEYSTORE_UNINITIALIZED = 3;
+ /**
+ * An internal system error - refer to {@link #isTransientFailure()} to determine whether
+ * re-trying the operation is likely to yield different results.
+ */
+ public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4;
+ /**
+ * The caller has requested key parameters or operation which are only available to system
+ * or privileged apps.
+ */
+ public static final int ERROR_PERMISSION_DENIED = 5;
+ /**
+ * The key the operation refers to doesn't exist.
+ */
+ public static final int ERROR_KEY_DOES_NOT_EXIST = 6;
+ /**
+ * The key is corrupted and could not be recovered.
+ */
+ public static final int ERROR_KEY_CORRUPTED = 7;
+ /**
+ * The error related to inclusion of device identifiers in the attestation record.
+ */
+ public static final int ERROR_ID_ATTESTATION_FAILURE = 8;
+ /**
+ * The attestation challenge specified is too large.
+ */
+ public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9;
+ /**
+ * General error in the KeyMint layer.
+ */
+ public static final int ERROR_KEYMINT_FAILURE = 10;
+ /**
+ * Failure in the Keystore layer.
+ */
+ public static final int ERROR_KEYSTORE_FAILURE = 11;
+ /**
+ * The feature the caller is trying to use is not implemented by the underlying
+ * KeyMint implementation.
+ * This could happen when an unsupported algorithm is requested, or when trying to import
+ * a key in a format other than raw or PKCS#8.
+ */
+ public static final int ERROR_UNIMPLEMENTED = 12;
+ /**
+ * The feature the caller is trying to use is not compatible with the parameters used to
+ * generate the key. For example, trying to use a key generated for a different signature
+ * algorithm, or a digest not specified during key creation.
+ * Another case is the attempt to generate a symmetric AES key and requesting key attestation.
+ */
+ public static final int ERROR_INCORRECT_USAGE = 13;
+ /**
+ * The key is not currently valid: Either at has expired or it will be valid for use in the
+ * future.
+ */
+ public static final int ERROR_KEY_NOT_TEMPORALLY_VALID = 14;
+ /**
+ * The crypto object the caller has been using held a reference to a KeyMint operation that
+ * has been evacuated (likely due to other concurrent operations taking place).
+ * The caller should re-create the crypto object and try again.
+ */
+ public static final int ERROR_KEY_OPERATION_EXPIRED = 15;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = {"ERROR_"}, value = {
+ ERROR_OTHER,
+ ERROR_USER_AUTHENTICATION_REQUIRED,
+ ERROR_KEYSTORE_UNINITIALIZED,
+ ERROR_INTERNAL_SYSTEM_ERROR,
+ ERROR_PERMISSION_DENIED,
+ ERROR_KEY_DOES_NOT_EXIST,
+ ERROR_KEY_CORRUPTED,
+ ERROR_ID_ATTESTATION_FAILURE,
+ ERROR_ATTESTATION_CHALLENGE_TOO_LARGE,
+ ERROR_KEYMINT_FAILURE,
+ ERROR_KEYSTORE_FAILURE,
+ ERROR_UNIMPLEMENTED,
+ ERROR_INCORRECT_USAGE,
+ ERROR_KEY_NOT_TEMPORALLY_VALID,
+ ERROR_KEY_OPERATION_EXPIRED
+ })
+ public @interface PublicErrorCode {
+ }
+
+ // Constants for encoding information about the error encountered:
+ // Whether the error relates to the system state/implementation as a whole, or a specific key.
+ private static final int IS_SYSTEM_ERROR = 1 << 1;
+ // Whether the error is permanent.
+ private static final int IS_TRANSIENT_ERROR = 1 << 2;
+ // Whether the cause of the error is the user not having authenticated recently.
+ private static final int REQUIRES_USER_AUTHENTICATION = 1 << 3;
+
+ // The internal error code. NOT to be returned directly to callers or made part of the
+ // public API.
private final int mErrorCode;
- public KeyStoreException(int errorCode, String message) {
+ /**
+ * @hide
+ */
+ public KeyStoreException(int errorCode, @Nullable String message) {
super(message);
mErrorCode = errorCode;
}
+ /**
+ * @hide
+ */
+ public KeyStoreException(int errorCode, @Nullable String message,
+ @Nullable String keystoreErrorMessage) {
+ super(message + " (internal Keystore code: " + errorCode + " message: "
+ + keystoreErrorMessage + ")");
+ mErrorCode = errorCode;
+ }
+
+ /**
+ * Returns the internal error code. Only for use by the platform.
+ *
+ * @hide
+ */
+ @TestApi
public int getErrorCode() {
return mErrorCode;
}
+
+ /**
+ * Returns one of the error codes exported by the class.
+ *
+ * @return a public error code, one of the values in {@link PublicErrorCode}.
+ */
+ @PublicErrorCode
+ public int getNumericErrorCode() {
+ PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+ return failureInfo.errorCode;
+ }
+
+ /**
+ * Returns true if the failure is a transient failure - that is, performing the same operation
+ * again at a late time is likely to succeed.
+ *
+ * If {@link #isSystemError()} returns true, the transient nature of the failure relates to the
+ * device, otherwise relates to the key (so a permanent failure with an existing key likely
+ * requires creating another key to repeat the operation with).
+ */
+ public boolean isTransientFailure() {
+ PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+ return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0;
+ }
+
+ /**
+ * Indicates whether the failure is due to the device being locked.
+ *
+ * @return true if the key operation failed because the user has to authenticate
+ * (e.g. by unlocking the device).
+ */
+ public boolean requiresUserAuthentication() {
+ PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+ return (failureInfo.indicators & REQUIRES_USER_AUTHENTICATION) != 0;
+ }
+
+ /**
+ * Indicates whether the error related to the Keystore/KeyMint implementation and not
+ * a specific key.
+ *
+ * @return true if the error is related to the system, not the key in use. System
+ * errors indicate a feature isn't working, whereas key-related errors are likely
+ * to succeed with a new key.
+ */
+ public boolean isSystemError() {
+ PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+ return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0;
+ }
+
+ @Override
+ public String toString() {
+ String errorCodes = String.format(" (public error code: %d internal Keystore code: %d)",
+ getNumericErrorCode(), mErrorCode);
+ return super.toString() + errorCodes;
+ }
+
+ private static PublicErrorInformation getErrorInformation(int internalErrorCode) {
+ PublicErrorInformation errorInfo = sErrorCodeToFailureInfo.get(internalErrorCode);
+ if (errorInfo != null) {
+ return errorInfo;
+ }
+
+ /**
+ * KeyStore/keymaster exception with positive error codes coming from the KeyStore and
+ * negative ones from keymaster.
+ * This is a safety fall-back: All error codes should be present in the map.
+ */
+ if (internalErrorCode > 0) {
+ return GENERAL_KEYSTORE_ERROR;
+ } else {
+ return GENERAL_KEYMINT_ERROR;
+ }
+ }
+
+ private static final class PublicErrorInformation {
+ public final int indicators;
+ public final int errorCode;
+
+ PublicErrorInformation(int indicators, @PublicErrorCode int errorCode) {
+ this.indicators = indicators;
+ this.errorCode = errorCode;
+ }
+ }
+
+ private static final PublicErrorInformation GENERAL_KEYMINT_ERROR =
+ new PublicErrorInformation(0, ERROR_KEYMINT_FAILURE);
+
+ private static final PublicErrorInformation GENERAL_KEYSTORE_ERROR =
+ new PublicErrorInformation(0, ERROR_KEYSTORE_FAILURE);
+
+ private static final PublicErrorInformation KEYMINT_UNIMPLEMENTED_ERROR =
+ new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_UNIMPLEMENTED);
+
+ private static final PublicErrorInformation KEYMINT_RETRYABLE_ERROR =
+ new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR,
+ ERROR_KEYMINT_FAILURE);
+
+ private static final PublicErrorInformation KEYMINT_INCORRECT_USAGE_ERROR =
+ new PublicErrorInformation(0, ERROR_INCORRECT_USAGE);
+
+ private static final PublicErrorInformation KEYMINT_TEMPORAL_VALIDITY_ERROR =
+ new PublicErrorInformation(0, ERROR_KEY_NOT_TEMPORALLY_VALID);
+
+
+ private static final Map<Integer, PublicErrorInformation> sErrorCodeToFailureInfo =
+ new HashMap();
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public static boolean hasFailureInfoForError(int internalErrorCode) {
+ return sErrorCodeToFailureInfo.containsKey(internalErrorCode);
+ }
+
+ static {
+ // KeyMint error codes
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OK, GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ROOT_OF_TRUST_ALREADY_SET,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_PURPOSE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_PURPOSE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_ALGORITHM,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_ALGORITHM,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_SIZE,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_BLOCK_MODE,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_BLOCK_MODE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MAC_LENGTH,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_PADDING_MODE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_PADDING_MODE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_DIGEST,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_DIGEST,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_EXPIRATION_TIME,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_USER_ID,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_FORMAT,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_KEY_FORMAT,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KEY_VERIFICATION_ALGORITHM,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_EXPORT_OPTIONS_INVALID,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DELEGATION_NOT_ALLOWED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID,
+ KEYMINT_TEMPORAL_VALIDITY_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_EXPIRED,
+ KEYMINT_TEMPORAL_VALIDITY_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED,
+ new PublicErrorInformation(REQUIRES_USER_AUTHENTICATION,
+ ERROR_USER_AUTHENTICATION_REQUIRED));
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OUTPUT_PARAMETER_NULL,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE,
+ new PublicErrorInformation(IS_SYSTEM_ERROR | IS_TRANSIENT_ERROR,
+ ERROR_KEY_OPERATION_EXPIRED));
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INSUFFICIENT_BUFFER_SPACE,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_VERIFICATION_FAILED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_TOO_MANY_OPERATIONS,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNEXPECTED_NULL_POINTER,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_KEY_BLOB,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_NOT_ENCRYPTED,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_DECRYPTION_FAILED,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_NOT_SIGNED,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORTED_KEY_VERIFICATION_FAILED,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_ARGUMENT,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_TAG,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_TAG,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MEMORY_ALLOCATION_FAILED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_IMPORT_PARAMETER_MISMATCH,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_ACCESS_DENIED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_OPERATION_CANCELLED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CONCURRENT_ACCESS_CONFLICT,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_BUSY,
+ KEYMINT_RETRYABLE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_SECURE_HW_COMMUNICATION_FAILED,
+ KEYMINT_RETRYABLE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_EC_FIELD,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NONCE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_NONCE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_MAC_LENGTH,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_RATE_LIMIT_EXCEEDED,
+ KEYMINT_RETRYABLE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CALLER_NONCE_PROHIBITED,
+ GENERAL_KEYMINT_ERROR);
+ // Error related to MAX_USES_PER_BOOT, restricting the number of uses per boot.
+ // It is not re-tryable.
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEY_MAX_OPS_EXCEEDED,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INVALID_MAC_LENGTH,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_MIN_MAC_LENGTH,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_KDF,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_EC_CURVE,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_CHALLENGE_MISSING,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_KEYMINT_NOT_CONFIGURED,
+ new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_KEYMINT_FAILURE));
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ATTESTATION_APPLICATION_ID_MISSING,
+ KEYMINT_RETRYABLE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_CANNOT_ATTEST_IDS,
+ new PublicErrorInformation(IS_SYSTEM_ERROR,
+ ERROR_ID_ATTESTATION_FAILURE));
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_DEVICE_LOCKED,
+ new PublicErrorInformation(IS_SYSTEM_ERROR | REQUIRES_USER_AUTHENTICATION,
+ ERROR_USER_AUTHENTICATION_REQUIRED));
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_STORAGE_KEY_UNSUPPORTED,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_INCOMPATIBLE_MGF_DIGEST,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNSUPPORTED_MGF_DIGEST,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_BEFORE,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_MISSING_NOT_AFTER,
+ KEYMINT_INCORRECT_USAGE_ERROR);
+ // This should not be exposed to apps as it's handled by Keystore.
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_HARDWARE_NOT_YET_AVAILABLE,
+ GENERAL_KEYMINT_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNIMPLEMENTED,
+ KEYMINT_UNIMPLEMENTED_ERROR);
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR,
+ new PublicErrorInformation(IS_SYSTEM_ERROR,
+ ERROR_KEYMINT_FAILURE));
+ sErrorCodeToFailureInfo.put(KeymasterDefs.KM_ERROR_VERSION_MISMATCH, GENERAL_KEYMINT_ERROR);
+
+ // Keystore error codes
+ sErrorCodeToFailureInfo.put(ResponseCode.LOCKED,
+ new PublicErrorInformation(REQUIRES_USER_AUTHENTICATION,
+ ERROR_USER_AUTHENTICATION_REQUIRED));
+ sErrorCodeToFailureInfo.put(ResponseCode.UNINITIALIZED,
+ new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_KEYSTORE_UNINITIALIZED));
+ sErrorCodeToFailureInfo.put(ResponseCode.SYSTEM_ERROR,
+ new PublicErrorInformation(IS_SYSTEM_ERROR,
+ ERROR_INTERNAL_SYSTEM_ERROR));
+ sErrorCodeToFailureInfo.put(ResponseCode.PERMISSION_DENIED,
+ new PublicErrorInformation(0, ERROR_PERMISSION_DENIED));
+ sErrorCodeToFailureInfo.put(ResponseCode.KEY_NOT_FOUND,
+ new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
+ sErrorCodeToFailureInfo.put(ResponseCode.VALUE_CORRUPTED,
+ new PublicErrorInformation(0, ERROR_KEY_CORRUPTED));
+ sErrorCodeToFailureInfo.put(ResponseCode.KEY_PERMANENTLY_INVALIDATED,
+ new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
+ }
}
diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java
index e6c1ea8..737ff2b 100644
--- a/keystore/java/android/security/KeyStoreOperation.java
+++ b/keystore/java/android/security/KeyStoreOperation.java
@@ -75,7 +75,7 @@
);
}
default:
- throw KeyStore2.getKeyStoreException(e.errorCode);
+ throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
}
} catch (RemoteException e) {
// Log exception and report invalid operation handle.
@@ -85,7 +85,8 @@
"Remote exception while advancing a KeyStoreOperation.",
e
);
- throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "");
+ throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, "",
+ e.getMessage());
}
}
diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java
index b85dd74..9c0b46c 100644
--- a/keystore/java/android/security/KeyStoreSecurityLevel.java
+++ b/keystore/java/android/security/KeyStoreSecurityLevel.java
@@ -54,12 +54,12 @@
try {
return request.execute();
} catch (ServiceSpecificException e) {
- throw KeyStore2.getKeyStoreException(e.errorCode);
+ throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
} catch (RemoteException e) {
// Log exception and report invalid operation handle.
// This should prompt the caller drop the reference to this operation and retry.
Log.e(TAG, "Could not connect to Keystore.", e);
- throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "");
+ throw new KeyStoreException(ResponseCode.SYSTEM_ERROR, "", e.getMessage());
}
}
@@ -117,7 +117,7 @@
break;
}
default:
- throw KeyStore2.getKeyStoreException(e.errorCode);
+ throw KeyStore2.getKeyStoreException(e.errorCode, e.getMessage());
}
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);
diff --git a/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java
new file mode 100644
index 0000000..31c7422
--- /dev/null
+++ b/keystore/tests/src/android/security/keystore/KeyStoreExceptionTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 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 android.security.keystore;
+
+import static org.junit.Assert.assertTrue;
+
+import android.security.KeyStoreException;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class KeyStoreExceptionTest {
+ @Test
+ public void testKeystoreMessageIsIncluded() {
+ final String primaryMessage = "some_message";
+ final String keystoreMessage = "ks_message";
+ KeyStoreException exception = new KeyStoreException(-1, primaryMessage, keystoreMessage);
+
+ String exceptionMessage = exception.getMessage();
+ assertTrue(exceptionMessage.contains(primaryMessage));
+ assertTrue(exceptionMessage.contains(keystoreMessage));
+
+ String exceptionString = exception.toString();
+ assertTrue(exceptionString.contains(primaryMessage));
+ assertTrue(exceptionString.contains(keystoreMessage));
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/OWNERS
new file mode 100644
index 0000000..8446b37
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Split Screen
+# Bug component: 928697
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OWNERS
new file mode 100644
index 0000000..566acc8
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Bubbles
+# Bug component: 555586
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OWNERS
new file mode 100644
index 0000000..8446b37
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Split Screen
+# Bug component: 928697
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/OWNERS b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/OWNERS
new file mode 100644
index 0000000..172e24bf
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/OWNERS
@@ -0,0 +1,2 @@
+# window manager > wm shell > Picture-In-Picture
+# Bug component: 316251
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index d17c328..8150e78 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -686,6 +686,12 @@
std::unordered_set<uint32_t> finalized_ids;
const auto lib_alias = child_chunk.header<ResTable_staged_alias_header>();
if (!lib_alias) {
+ LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small.";
+ return {};
+ }
+ if ((child_chunk.data_size() / sizeof(ResTable_staged_alias_entry))
+ < dtohl(lib_alias->count)) {
+ LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small to hold entries.";
return {};
}
const auto entry_begin = child_chunk.data_ptr().convert<ResTable_staged_alias_entry>();
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index f8d6c07..a743d30 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -32,8 +32,6 @@
using namespace android::uirenderer::renderthread;
-static constexpr bool sEnableExtraCropInset = true;
-
namespace android {
namespace uirenderer {
@@ -66,20 +64,6 @@
ALOGW("Surface doesn't have any previously queued frames, nothing to readback from");
return CopyResult::SourceEmpty;
}
-
- if (sEnableExtraCropInset &&
- (cropRect.right - cropRect.left != bitmap->width() ||
- cropRect.bottom - cropRect.top != bitmap->height())) {
- /*
- * When we need use filtering, we should also make border shrink here like gui.
- * But we could not check format for YUV or RGB here... Just use 1 pix.
- */
- cropRect.left += 0.5f;
- cropRect.top += 0.5f;
- cropRect.right -= 0.5f;
- cropRect.bottom -= 0.5f;
- }
-
UniqueAHardwareBuffer sourceBuffer{rawSourceBuffer};
AHardwareBuffer_Desc description;
AHardwareBuffer_describe(sourceBuffer.get(), &description);
diff --git a/libs/tracingproxy/Android.bp b/libs/tracingproxy/Android.bp
index 7126bfa..23d107b 100644
--- a/libs/tracingproxy/Android.bp
+++ b/libs/tracingproxy/Android.bp
@@ -37,6 +37,7 @@
srcs: [
":ITracingServiceProxy.aidl",
+ ":TraceReportParams.aidl",
],
shared_libs: [
diff --git a/media/Android.bp b/media/Android.bp
index 1b7bef5..b7c3a9c 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -100,6 +100,11 @@
vndk: {
enabled: true,
},
+ min_sdk_version: "29",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.bluetooth",
+ ],
},
},
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index b7e8c8c..d8893cb 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -5806,13 +5806,14 @@
* @param newDevice Bluetooth device connected or null if there is no new devices
* @param previousDevice Bluetooth device disconnected or null if there is no disconnected
* devices
- * @param info contain all info related to the device. {@link BtProfileConnectionInfo}
+ * @param info contain all info related to the device. {@link BluetoothProfileConnectionInfo}
* {@hide}
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.BLUETOOTH_STACK)
public void handleBluetoothActiveDeviceChanged(@Nullable BluetoothDevice newDevice,
- @Nullable BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
+ @Nullable BluetoothDevice previousDevice,
+ @NonNull BluetoothProfileConnectionInfo info) {
final IAudioService service = getService();
try {
service.handleBluetoothActiveDeviceChanged(newDevice, previousDevice, info);
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index f0e42c0..143b11f 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -242,7 +242,8 @@
AUDIO_FORMAT_SBC,
AUDIO_FORMAT_APTX,
AUDIO_FORMAT_APTX_HD,
- AUDIO_FORMAT_LDAC}
+ AUDIO_FORMAT_LDAC,
+ AUDIO_FORMAT_LC3}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioFormatNativeEnumForBtCodec {}
@@ -274,6 +275,7 @@
case AUDIO_FORMAT_APTX: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
case AUDIO_FORMAT_APTX_HD: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
case AUDIO_FORMAT_LDAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
+ case AUDIO_FORMAT_LC3: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3;
default:
Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat)
+ " for conversion to BT codec");
@@ -314,6 +316,8 @@
return AudioSystem.AUDIO_FORMAT_APTX_HD;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
return AudioSystem.AUDIO_FORMAT_LDAC;
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3:
+ return AudioSystem.AUDIO_FORMAT_LC3;
default:
Log.e(TAG, "Unknown BT codec 0x" + Integer.toHexString(btCodec)
+ " for conversion to audio format");
@@ -414,6 +418,8 @@
return "AUDIO_FORMAT_LHDC_LL";
case /* AUDIO_FORMAT_APTX_TWSP */ 0x2A000000:
return "AUDIO_FORMAT_APTX_TWSP";
+ case /* AUDIO_FORMAT_LC3 */ 0x2B000000:
+ return "AUDIO_FORMAT_LC3";
/* Aliases */
case /* AUDIO_FORMAT_PCM_16_BIT */ 0x1:
diff --git a/media/java/android/media/BtProfileConnectionInfo.aidl b/media/java/android/media/BluetoothProfileConnectionInfo.aidl
similarity index 93%
rename from media/java/android/media/BtProfileConnectionInfo.aidl
rename to media/java/android/media/BluetoothProfileConnectionInfo.aidl
index 047f06b..0617084 100644
--- a/media/java/android/media/BtProfileConnectionInfo.aidl
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.aidl
@@ -16,5 +16,5 @@
package android.media;
-parcelable BtProfileConnectionInfo;
+parcelable BluetoothProfileConnectionInfo;
diff --git a/media/java/android/media/BtProfileConnectionInfo.java b/media/java/android/media/BluetoothProfileConnectionInfo.java
similarity index 60%
rename from media/java/android/media/BtProfileConnectionInfo.java
rename to media/java/android/media/BluetoothProfileConnectionInfo.java
index d1bb41e..c148846 100644
--- a/media/java/android/media/BtProfileConnectionInfo.java
+++ b/media/java/android/media/BluetoothProfileConnectionInfo.java
@@ -15,40 +15,25 @@
*/
package android.media;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.bluetooth.BluetoothProfile;
import android.os.Parcel;
import android.os.Parcelable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
/**
* Contains information about Bluetooth profile connection state changed
* {@hide}
*/
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
-public final class BtProfileConnectionInfo implements Parcelable {
- /** @hide */
- @IntDef({
- BluetoothProfile.A2DP,
- BluetoothProfile.A2DP_SINK,
- BluetoothProfile.HEADSET, // Can only be set by BtHelper
- BluetoothProfile.HEARING_AID,
- BluetoothProfile.LE_AUDIO,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface BtProfile {}
-
- private final @BtProfile int mProfile;
+public final class BluetoothProfileConnectionInfo implements Parcelable {
+ private final int mProfile;
private final boolean mSupprNoisy;
private final int mVolume;
private final boolean mIsLeOutput;
- private BtProfileConnectionInfo(@BtProfile int profile, boolean suppressNoisyIntent, int volume,
- boolean isLeOutput) {
+ private BluetoothProfileConnectionInfo(int profile, boolean suppressNoisyIntent,
+ int volume, boolean isLeOutput) {
mProfile = profile;
mSupprNoisy = suppressNoisyIntent;
mVolume = volume;
@@ -59,21 +44,21 @@
* Constructor used by BtHelper when a profile is connected
* {@hide}
*/
- public BtProfileConnectionInfo(@BtProfile int profile) {
+ public BluetoothProfileConnectionInfo(int profile) {
this(profile, false, -1, false);
}
- public static final @NonNull Parcelable.Creator<BtProfileConnectionInfo> CREATOR =
- new Parcelable.Creator<BtProfileConnectionInfo>() {
+ public static final @NonNull Parcelable.Creator<BluetoothProfileConnectionInfo> CREATOR =
+ new Parcelable.Creator<BluetoothProfileConnectionInfo>() {
@Override
- public BtProfileConnectionInfo createFromParcel(Parcel source) {
- return new BtProfileConnectionInfo(source.readInt(), source.readBoolean(),
- source.readInt(), source.readBoolean());
+ public BluetoothProfileConnectionInfo createFromParcel(Parcel source) {
+ return new BluetoothProfileConnectionInfo(source.readInt(),
+ source.readBoolean(), source.readInt(), source.readBoolean());
}
@Override
- public BtProfileConnectionInfo[] newArray(int size) {
- return new BtProfileConnectionInfo[size];
+ public BluetoothProfileConnectionInfo[] newArray(int size) {
+ return new BluetoothProfileConnectionInfo[size];
}
};
@@ -98,10 +83,10 @@
*
* @param volume of device -1 to ignore value
*/
- public static @NonNull BtProfileConnectionInfo a2dpInfo(boolean suppressNoisyIntent,
- int volume) {
- return new BtProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent, volume,
- false);
+ public static @NonNull BluetoothProfileConnectionInfo createA2dpInfo(
+ boolean suppressNoisyIntent, int volume) {
+ return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP, suppressNoisyIntent,
+ volume, false);
}
/**
@@ -110,8 +95,8 @@
*
* @param volume of device -1 to ignore value
*/
- public static @NonNull BtProfileConnectionInfo a2dpSinkInfo(int volume) {
- return new BtProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false);
+ public static @NonNull BluetoothProfileConnectionInfo createA2dpSinkInfo(int volume) {
+ return new BluetoothProfileConnectionInfo(BluetoothProfile.A2DP_SINK, true, volume, false);
}
/**
@@ -120,9 +105,10 @@
* @param suppressNoisyIntent if true the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY}
* intent will not be sent.
*/
- public static @NonNull BtProfileConnectionInfo hearingAidInfo(boolean suppressNoisyIntent) {
- return new BtProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent, -1,
- false);
+ public static @NonNull BluetoothProfileConnectionInfo createHearingAidInfo(
+ boolean suppressNoisyIntent) {
+ return new BluetoothProfileConnectionInfo(BluetoothProfile.HEARING_AID, suppressNoisyIntent,
+ -1, false);
}
/**
@@ -133,16 +119,16 @@
*
* @param isLeOutput if true mean the device is an output device, if false it's an input device
*/
- public static @NonNull BtProfileConnectionInfo leAudio(boolean suppressNoisyIntent,
- boolean isLeOutput) {
- return new BtProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent, -1,
- isLeOutput);
+ public static @NonNull BluetoothProfileConnectionInfo createLeAudioInfo(
+ boolean suppressNoisyIntent, boolean isLeOutput) {
+ return new BluetoothProfileConnectionInfo(BluetoothProfile.LE_AUDIO, suppressNoisyIntent,
+ -1, isLeOutput);
}
/**
* @return The profile connection
*/
- public @BtProfile int getProfile() {
+ public int getProfile() {
return mProfile;
}
@@ -150,7 +136,7 @@
* @return {@code true} if {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be
* sent
*/
- public boolean getSuppressNoisyIntent() {
+ public boolean isSuppressNoisyIntent() {
return mSupprNoisy;
}
@@ -167,7 +153,7 @@
* @return {@code true} is the LE device is an output device, {@code false} if it's an input
* device
*/
- public boolean getIsLeOutput() {
+ public boolean isLeOutput() {
return mIsLeOutput;
}
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 5ff56f9..d5a2d07 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -24,7 +24,7 @@
import android.media.AudioPlaybackConfiguration;
import android.media.AudioRecordingConfiguration;
import android.media.AudioRoutesInfo;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioModeDispatcher;
import android.media.IAudioRoutesObserver;
@@ -268,7 +268,7 @@
oneway void playerHasOpPlayAudio(in int piid, in boolean hasOpPlayAudio);
void handleBluetoothActiveDeviceChanged(in BluetoothDevice newDevice,
- in BluetoothDevice previousDevice, in BtProfileConnectionInfo info);
+ in BluetoothDevice previousDevice, in BluetoothProfileConnectionInfo info);
oneway void setFocusRequestResultFromExtPolicy(in AudioFocusInfo afi, int requestResult,
in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 3c152fb..77709d7 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -426,10 +426,30 @@
/** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
public static final int COLOR_Format24BitABGR6666 = 43;
- /** @hide
- * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
- * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
- * little-endian value, with the lower 6 bits set to zero. */
+ /**
+ * P010 is 10-bit-per component 4:2:0 YCbCr semiplanar format.
+ * <p>
+ * This format uses 24 allocated bits per pixel with 15 bits of
+ * data per pixel. Chroma planes are subsampled by 2 both
+ * horizontally and vertically. Each chroma and luma component
+ * has 16 allocated bits in little-endian configuration with 10
+ * MSB of actual data.
+ *
+ * <pre>
+ * byte byte
+ * <--------- i --------> | <------ i + 1 ------>
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * | UNUSED | Y/Cb/Cr |
+ * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+ * 0 5 6 7 0 7
+ * bit
+ * </pre>
+ *
+ * Use this format with {@link Image}. This format corresponds
+ * to {@link android.graphics.ImageFormat#YCBCR_P010}.
+ * <p>
+ */
+ @SuppressLint("AllUpper")
public static final int COLOR_FormatYUVP010 = 54;
/** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
@@ -439,6 +459,25 @@
public static final int COLOR_FormatSurface = 0x7F000789;
/**
+ * 64 bits per pixel RGBA color format, with 16-bit signed
+ * floating point red, green, blue, and alpha components.
+ * <p>
+ *
+ * <pre>
+ * byte byte byte byte
+ * <-- i -->|<- i+1 ->|<- i+2 ->|<- i+3 ->|<- i+4 ->|<- i+5 ->|<- i+6 ->|<- i+7 ->
+ * +---------+---------+-------------------+---------+---------+---------+---------+
+ * | RED | GREEN | BLUE | ALPHA |
+ * +---------+---------+-------------------+---------+---------+---------+---------+
+ * 0 7 0 7 0 7 0 7 0 7 0 7 0 7 0 7
+ * </pre>
+ *
+ * This corresponds to {@link android.graphics.PixelFormat#RGBA_F16}.
+ */
+ @SuppressLint("AllUpper")
+ public static final int COLOR_Format64bitABGRFloat = 0x7F000F16;
+
+ /**
* 32 bits per pixel RGBA color format, with 8-bit red, green, blue, and alpha components.
* <p>
* Using 32-bit little-endian representation, colors stored as Red 7:0, Green 15:8,
@@ -456,6 +495,26 @@
public static final int COLOR_Format32bitABGR8888 = 0x7F00A000;
/**
+ * 32 bits per pixel RGBA color format, with 10-bit red, green,
+ * blue, and 2-bit alpha components.
+ * <p>
+ * Using 32-bit little-endian representation, colors stored as
+ * Red 9:0, Green 19:10, Blue 29:20, and Alpha 31:30.
+ * <pre>
+ * byte byte byte byte
+ * <------ i -----> | <---- i+1 ----> | <---- i+2 ----> | <---- i+3 ----->
+ * +-----------------+---+-------------+-------+---------+-----------+-----+
+ * | RED | GREEN | BLUE |ALPHA|
+ * +-----------------+---+-------------+-------+---------+-----------+-----+
+ * 0 7 0 1 2 7 0 3 4 7 0 5 6 7
+ * </pre>
+ *
+ * This corresponds to {@link android.graphics.PixelFormat#RGBA_1010102}.
+ */
+ @SuppressLint("AllUpper")
+ public static final int COLOR_Format32bitABGR2101010 = 0x7F00AAA2;
+
+ /**
* Flexible 12 bits per pixel, subsampled YUV color format with 8-bit chroma and luma
* components.
* <p>
@@ -603,6 +662,18 @@
public static final String FEATURE_QpBounds = "qp-bounds";
/**
+ * <b>video encoder only</b>: codec supports exporting encoding statistics.
+ * Encoders with this feature can provide the App clients with the encoding statistics
+ * information about the frame.
+ * The scope of encoding statistics is controlled by
+ * {@link MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL}.
+ *
+ * @see MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL
+ */
+ @SuppressLint("AllUpper") // for consistency with other FEATURE_* constants
+ public static final String FEATURE_EncodingStatistics = "encoding-statistics";
+
+ /**
* Query codec feature capabilities.
* <p>
* These features are supported to be used by the codec. These
@@ -641,6 +712,7 @@
new Feature(FEATURE_MultipleFrames, (1 << 1), false),
new Feature(FEATURE_DynamicTimestamp, (1 << 2), false),
new Feature(FEATURE_QpBounds, (1 << 3), false),
+ new Feature(FEATURE_EncodingStatistics, (1 << 4), false),
// feature to exclude codec from REGULAR codec list
new Feature(FEATURE_SpecialCodec, (1 << 30), false, true),
};
@@ -3953,6 +4025,12 @@
public static final int DolbyVisionLevelUhd30 = 0x40;
public static final int DolbyVisionLevelUhd48 = 0x80;
public static final int DolbyVisionLevelUhd60 = 0x100;
+ @SuppressLint("AllUpper")
+ public static final int DolbyVisionLevelUhd120 = 0x200;
+ @SuppressLint("AllUpper")
+ public static final int DolbyVisionLevel8k30 = 0x400;
+ @SuppressLint("AllUpper")
+ public static final int DolbyVisionLevel8k60 = 0x800;
// Profiles and levels for AV1 Codec, corresponding to the definitions in
// "AV1 Bitstream & Decoding Process Specification", Annex A
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 9bf0db5..aa5c404 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -1102,6 +1102,76 @@
public static final String KEY_VIDEO_QP_B_MIN = "video-qp-b-min";
/**
+ * A key describing the level of encoding statistics information emitted from video encoder.
+ *
+ * The associated value is an integer.
+ */
+ public static final String KEY_VIDEO_ENCODING_STATISTICS_LEVEL =
+ "video-encoding-statistics-level";
+
+ /**
+ * Encoding Statistics Level None.
+ * Encoder generates no information about Encoding statistics.
+ */
+ public static final int VIDEO_ENCODING_STATISTICS_LEVEL_NONE = 0;
+
+ /**
+ * Encoding Statistics Level 1.
+ * Encoder generates {@link MediaFormat#KEY_PICTURE_TYPE} and
+ * {@link MediaFormat#KEY_VIDEO_QP_AVERAGE} for each frame.
+ */
+ public static final int VIDEO_ENCODING_STATISTICS_LEVEL_1 = 1;
+
+ /** @hide */
+ @IntDef({
+ VIDEO_ENCODING_STATISTICS_LEVEL_NONE,
+ VIDEO_ENCODING_STATISTICS_LEVEL_1,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VideoEncodingStatisticsLevel {}
+
+ /**
+ * A key describing the per-frame average block QP (Quantization Parameter).
+ * This is a part of a video 'Encoding Statistics' export feature.
+ * This value is emitted from video encoder for a video frame.
+ * The average value is rounded down (using floor()) to integer value.
+ *
+ * The associated value is an integer.
+ */
+ public static final String KEY_VIDEO_QP_AVERAGE = "video-qp-average";
+
+ /**
+ * A key describing the picture type of the encoded frame.
+ * This is a part of a video 'Encoding Statistics' export feature.
+ * This value is emitted from video encoder for a video frame.
+ *
+ * The associated value is an integer.
+ */
+ public static final String KEY_PICTURE_TYPE = "picture-type";
+
+ /** Picture Type is unknown. */
+ public static final int PICTURE_TYPE_UNKNOWN = 0;
+
+ /** Picture Type is I Frame. */
+ public static final int PICTURE_TYPE_I = 1;
+
+ /** Picture Type is P Frame. */
+ public static final int PICTURE_TYPE_P = 2;
+
+ /** Picture Type is B Frame. */
+ public static final int PICTURE_TYPE_B = 3;
+
+ /** @hide */
+ @IntDef({
+ PICTURE_TYPE_UNKNOWN,
+ PICTURE_TYPE_I,
+ PICTURE_TYPE_P,
+ PICTURE_TYPE_B,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PictureType {}
+
+ /**
* A key describing the audio session ID of the AudioTrack associated
* to a tunneled video codec.
* The associated value is an integer.
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 3cf0341..86a94a9 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -504,49 +504,51 @@
}
private boolean playFallbackRingtone() {
- if (mAudioManager.getStreamVolume(AudioAttributes.toLegacyStreamType(mAudioAttributes))
- != 0) {
- int ringtoneType = RingtoneManager.getDefaultType(mUri);
- if (ringtoneType == -1 ||
- RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) != null) {
- // Default ringtone, try fallback ringtone.
- try {
- AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
- com.android.internal.R.raw.fallbackring);
- if (afd != null) {
- mLocalPlayer = new MediaPlayer();
- if (afd.getDeclaredLength() < 0) {
- mLocalPlayer.setDataSource(afd.getFileDescriptor());
- } else {
- mLocalPlayer.setDataSource(afd.getFileDescriptor(),
- afd.getStartOffset(),
- afd.getDeclaredLength());
- }
- mLocalPlayer.setAudioAttributes(mAudioAttributes);
- synchronized (mPlaybackSettingsLock) {
- applyPlaybackProperties_sync();
- }
- if (mVolumeShaperConfig != null) {
- mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
- }
- mLocalPlayer.prepare();
- startLocalPlayer();
- afd.close();
- return true;
- } else {
- Log.e(TAG, "Could not load fallback ringtone");
- }
- } catch (IOException ioe) {
- destroyLocalPlayer();
- Log.e(TAG, "Failed to open fallback ringtone");
- } catch (NotFoundException nfe) {
- Log.e(TAG, "Fallback ringtone does not exist");
- }
- } else {
- Log.w(TAG, "not playing fallback for " + mUri);
- }
+ int streamType = AudioAttributes.toLegacyStreamType(mAudioAttributes);
+ if (mAudioManager.getStreamVolume(streamType) == 0) {
+ return false;
}
- return false;
+ int ringtoneType = RingtoneManager.getDefaultType(mUri);
+ if (ringtoneType != -1 &&
+ RingtoneManager.getActualDefaultRingtoneUri(mContext, ringtoneType) == null) {
+ Log.w(TAG, "not playing fallback for " + mUri);
+ return false;
+ }
+ // Default ringtone, try fallback ringtone.
+ try {
+ AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(
+ com.android.internal.R.raw.fallbackring);
+ if (afd == null) {
+ Log.e(TAG, "Could not load fallback ringtone");
+ return false;
+ }
+ mLocalPlayer = new MediaPlayer();
+ if (afd.getDeclaredLength() < 0) {
+ mLocalPlayer.setDataSource(afd.getFileDescriptor());
+ } else {
+ mLocalPlayer.setDataSource(afd.getFileDescriptor(),
+ afd.getStartOffset(),
+ afd.getDeclaredLength());
+ }
+ mLocalPlayer.setAudioAttributes(mAudioAttributes);
+ synchronized (mPlaybackSettingsLock) {
+ applyPlaybackProperties_sync();
+ }
+ if (mVolumeShaperConfig != null) {
+ mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig);
+ }
+ mLocalPlayer.prepare();
+ startLocalPlayer();
+ afd.close();
+ } catch (IOException ioe) {
+ destroyLocalPlayer();
+ Log.e(TAG, "Failed to open fallback ringtone");
+ return false;
+ } catch (NotFoundException nfe) {
+ Log.e(TAG, "Fallback ringtone does not exist");
+ return false;
+ }
+ return true;
}
void setTitle(String title) {
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index d8f48c2..20d711c 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -103,6 +103,7 @@
private int mDeviceType;
private String mHostType;
private boolean mSkipThumbForHost = false;
+ private volatile boolean mHostIsWindows = false;
private MtpServer mServer;
private MtpStorageManager mManager;
@@ -358,7 +359,7 @@
}
public void addStorage(StorageVolume storage) {
- MtpStorage mtpStorage = mManager.addMtpStorage(storage);
+ MtpStorage mtpStorage = mManager.addMtpStorage(storage, () -> mHostIsWindows);
mStorageMap.put(storage.getPath(), mtpStorage);
if (mServer != null) {
mServer.addStorage(mtpStorage);
@@ -413,6 +414,7 @@
}
mHostType = "";
mSkipThumbForHost = false;
+ mHostIsWindows = false;
}
@VisibleForNative
@@ -736,10 +738,12 @@
: MtpConstants.RESPONSE_GENERAL_ERROR);
case MtpConstants.DEVICE_PROPERTY_SESSION_INITIATOR_VERSION_INFO:
mHostType = stringValue;
+ Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
+ + "=" + stringValue);
if (stringValue.startsWith("Android/")) {
- Log.d(TAG, "setDeviceProperty." + Integer.toHexString(property)
- + "=" + stringValue);
mSkipThumbForHost = true;
+ } else if (stringValue.startsWith("Windows/")) {
+ mHostIsWindows = true;
}
return MtpConstants.RESPONSE_OK;
}
diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java
index 88c32a3..a3754e90 100644
--- a/media/java/android/mtp/MtpStorage.java
+++ b/media/java/android/mtp/MtpStorage.java
@@ -19,6 +19,8 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.os.storage.StorageVolume;
+import java.util.function.Supplier;
+
/**
* This class represents a storage unit on an MTP device.
* Used only for MTP support in USB responder mode.
@@ -33,14 +35,16 @@
private final boolean mRemovable;
private final long mMaxFileSize;
private final String mVolumeName;
+ private final Supplier<Boolean> mIsHostWindows;
- public MtpStorage(StorageVolume volume, int storageId) {
+ public MtpStorage(StorageVolume volume, int storageId, Supplier<Boolean> isHostWindows) {
mStorageId = storageId;
mPath = volume.getPath();
mDescription = volume.getDescription(null);
mRemovable = volume.isRemovable();
mMaxFileSize = volume.getMaxFileSize();
mVolumeName = volume.getMediaStoreVolumeName();
+ mIsHostWindows = isHostWindows;
}
/**
@@ -93,4 +97,13 @@
public String getVolumeName() {
return mVolumeName;
}
+
+ /**
+ * Returns true if the mtp host of this storage is Windows.
+ *
+ * @return is host Windows
+ */
+ public boolean isHostWindows() {
+ return mIsHostWindows.get();
+ }
}
diff --git a/media/java/android/mtp/MtpStorageManager.java b/media/java/android/mtp/MtpStorageManager.java
index 0bede0d..e9426cf 100644
--- a/media/java/android/mtp/MtpStorageManager.java
+++ b/media/java/android/mtp/MtpStorageManager.java
@@ -18,7 +18,11 @@
import android.media.MediaFile;
import android.os.FileObserver;
+import android.os.SystemProperties;
import android.os.storage.StorageVolume;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -35,6 +39,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Supplier;
/**
* MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of
@@ -199,7 +204,38 @@
}
public long getSize() {
- return mIsDir ? 0 : getPath().toFile().length();
+ return mIsDir ? 0 : maybeApplyTranscodeLengthWorkaround(getPath().toFile().length());
+ }
+
+ private long maybeApplyTranscodeLengthWorkaround(long length) {
+ // Windows truncates transferred files to the size advertised in the object property.
+ if (mStorage.isHostWindows() && isTranscodeMtpEnabled() && isFileTranscodeSupported()) {
+ // If the file supports transcoding, we double the returned size to accommodate
+ // the increase in size from transcoding to AVC. This is the same heuristic
+ // applied in the FUSE daemon (MediaProvider).
+ return length * 2;
+ }
+ return length;
+ }
+
+ private boolean isTranscodeMtpEnabled() {
+ return SystemProperties.getBoolean("sys.fuse.transcode_mtp", false);
+ }
+
+ private boolean isFileTranscodeSupported() {
+ // Check if the file supports transcoding by reading the |st_nlinks| struct stat
+ // field. This will be > 1 if the file supports transcoding. The FUSE daemon
+ // sets the field accordingly to enable the MTP stack workaround some Windows OS
+ // MTP client bug where they ignore the size returned as part of getting the MTP
+ // object, see MtpServer#doGetObject.
+ final Path path = getPath();
+ try {
+ StructStat stat = Os.stat(path.toString());
+ return stat.st_nlink > 1;
+ } catch (ErrnoException e) {
+ Log.w(TAG, "Failed to stat path: " + getPath() + ". Ignoring transcoding.");
+ return false;
+ }
}
public Path getPath() {
@@ -420,10 +456,12 @@
* @param volume Storage to add.
* @return the associated MtpStorage
*/
- public synchronized MtpStorage addMtpStorage(StorageVolume volume) {
+ public synchronized MtpStorage addMtpStorage(StorageVolume volume,
+ Supplier<Boolean> isHostWindows) {
int storageId = ((getNextStorageId() & 0x0000FFFF) << 16) + 1;
- MtpStorage storage = new MtpStorage(volume, storageId);
- MtpObject root = new MtpObject(storage.getPath(), storageId, storage, null, true);
+ MtpStorage storage = new MtpStorage(volume, storageId, isHostWindows);
+ MtpObject root = new MtpObject(storage.getPath(), storageId, storage, /* parent= */ null,
+ /* isDir= */ true);
mRoots.put(storageId, root);
return storage;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
similarity index 66%
rename from media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java
rename to media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
index fd66d3b..f23794b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BtProfileConnectionInfoTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/BluetoothProfileConnectionInfoTest.java
@@ -19,7 +19,7 @@
import static org.junit.Assert.assertEquals;
import android.bluetooth.BluetoothProfile;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
import androidx.test.runner.AndroidJUnit4;
@@ -27,22 +27,24 @@
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
-public class BtProfileConnectionInfoTest {
+public class BluetoothProfileConnectionInfoTest {
@Test
public void testCoverageA2dp() {
final boolean supprNoisy = false;
final int volume = 42;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpInfo(supprNoisy, volume);
+ final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+ .createA2dpInfo(supprNoisy, volume);
assertEquals(info.getProfile(), BluetoothProfile.A2DP);
- assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
+ assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
assertEquals(info.getVolume(), volume);
}
@Test
public void testCoverageA2dpSink() {
final int volume = 42;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.a2dpSinkInfo(volume);
+ final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+ .createA2dpSinkInfo(volume);
assertEquals(info.getProfile(), BluetoothProfile.A2DP_SINK);
assertEquals(info.getVolume(), volume);
}
@@ -50,20 +52,21 @@
@Test
public void testCoveragehearingAid() {
final boolean supprNoisy = true;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.hearingAidInfo(supprNoisy);
+ final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+ .createHearingAidInfo(supprNoisy);
assertEquals(info.getProfile(), BluetoothProfile.HEARING_AID);
- assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
+ assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
}
@Test
public void testCoverageLeAudio() {
final boolean supprNoisy = false;
final boolean isLeOutput = true;
- final BtProfileConnectionInfo info = BtProfileConnectionInfo.leAudio(supprNoisy,
- isLeOutput);
+ final BluetoothProfileConnectionInfo info = BluetoothProfileConnectionInfo
+ .createLeAudioInfo(supprNoisy, isLeOutput);
assertEquals(info.getProfile(), BluetoothProfile.LE_AUDIO);
- assertEquals(info.getSuppressNoisyIntent(), supprNoisy);
- assertEquals(info.getIsLeOutput(), isLeOutput);
+ assertEquals(info.isSuppressNoisyIntent(), supprNoisy);
+ assertEquals(info.isLeOutput(), isLeOutput);
}
}
diff --git a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
index fdf6582..eb357f6 100644
--- a/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
+++ b/media/tests/MtpTests/src/android/mtp/MtpStorageManagerTest.java
@@ -159,10 +159,11 @@
Log.d(TAG, "sendObjectInfoChanged: " + id);
objectsInfoChanged.add(id);
}
- }, null);
+ }, /* subdirectories= */ null);
- mainMtpStorage = manager.addMtpStorage(mainStorage);
- secondaryMtpStorage = manager.addMtpStorage(secondaryStorage);
+ mainMtpStorage = manager.addMtpStorage(mainStorage, /* isHostWindows= */ () -> false);
+ secondaryMtpStorage = manager.addMtpStorage(secondaryStorage,
+ /* isHostWindows= */ () -> false);
}
@After
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index f33e118..2201753 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -300,6 +300,9 @@
android_res_nquery; # introduced=29
android_res_nresult; # introduced=29
android_res_nsend; # introduced=29
+ android_tag_socket_with_uid; # introduced=Tiramisu
+ android_tag_socket; # introduced=Tiramisu
+ android_untag_socket; # introduced=Tiramisu
AThermal_acquireManager; # introduced=30
AThermal_releaseManager; # introduced=30
AThermal_getCurrentThermalStatus; # introduced=30
diff --git a/omapi/OWNERS b/omapi/OWNERS
new file mode 100644
index 0000000..5682fd3
--- /dev/null
+++ b/omapi/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 456592
+
+zachoverflow@google.com
+alisher@google.com
+jackcwyu@google.com
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 90bb76a..54538d9 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -39,7 +39,6 @@
"src/android/net/TrafficStats.java",
"src/android/net/UnderlyingNetworkInfo.*",
"src/android/net/netstats/**/*.*",
- "src/com/android/server/NetworkManagementSocketTagger.java",
],
path: "src",
visibility: [
@@ -126,8 +125,13 @@
name: "framework-connectivity-ethernet-sources",
srcs: [
"src/android/net/EthernetManager.java",
+ "src/android/net/EthernetNetworkManagementException.java",
+ "src/android/net/EthernetNetworkManagementException.aidl",
"src/android/net/EthernetNetworkSpecifier.java",
+ "src/android/net/EthernetNetworkUpdateRequest.java",
+ "src/android/net/EthernetNetworkUpdateRequest.aidl",
"src/android/net/IEthernetManager.aidl",
+ "src/android/net/IEthernetNetworkManagementListener.aidl",
"src/android/net/IEthernetServiceListener.aidl",
"src/android/net/ITetheredInterfaceCallback.aidl",
],
@@ -156,8 +160,49 @@
":framework-connectivity-ethernet-sources",
":framework-connectivity-ipsec-sources",
":framework-connectivity-netstats-sources",
+ ],
+ visibility: ["//frameworks/base"],
+}
+
+filegroup {
+ name: "framework-connectivity-tiramisu-updatable-sources",
+ srcs: [
":framework-connectivity-nsd-sources",
":framework-connectivity-tiramisu-internal-sources",
],
- visibility: ["//frameworks/base"],
+ visibility: [
+ "//frameworks/base",
+ "//packages/modules/Connectivity:__subpackages__",
+ ],
+}
+
+cc_library_shared {
+ name: "libframework-connectivity-tiramisu-jni",
+ min_sdk_version: "30",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ // Don't warn about S API usage even with
+ // min_sdk 30: the library is only loaded
+ // on S+ devices
+ "-Wno-unguarded-availability",
+ "-Wthread-safety",
+ ],
+ srcs: [
+ "jni/android_net_TrafficStats.cpp",
+ "jni/onload.cpp",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ static_libs: [
+ "libnativehelper_compat_libc++",
+ ],
+ stl: "none",
+ apex_available: [
+ "com.android.tethering",
+ // TODO: remove when ConnectivityT moves to APEX.
+ "//apex_available:platform",
+ ],
}
diff --git a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
new file mode 100644
index 0000000..f3c58b1
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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 <android/file_descriptor_jni.h>
+#include <android/multinetwork.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) {
+ int fd = AFileDescriptor_getFd(env, fileDescriptor);
+ if (fd == -1) return -EBADF;
+ return android_tag_socket_with_uid(fd, tag, uid);
+}
+
+static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
+ int fd = AFileDescriptor_getFd(env, fileDescriptor);
+ if (fd == -1) return -EBADF;
+ return android_untag_socket(fd);
+}
+
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd },
+ { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd },
+};
+
+int register_android_net_TrafficStats(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
+
diff --git a/packages/ConnectivityT/framework-t/jni/onload.cpp b/packages/ConnectivityT/framework-t/jni/onload.cpp
new file mode 100644
index 0000000..1fb42c6
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/jni/onload.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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 LOG_TAG "FrameworkConnectivityJNI"
+
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+int register_android_net_TrafficStats(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_android_net_TrafficStats(env) < 0) return JNI_ERR;
+
+ return JNI_VERSION_1_6;
+}
+
+}; // namespace android
+
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
index d33666d..2b6570a 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStats.java
@@ -556,7 +556,7 @@
/**
* Collects history results for uid and resets history enumeration index.
*/
- void startHistoryEnumeration(int uid, int tag, int state) {
+ void startHistoryUidEnumeration(int uid, int tag, int state) {
mHistory = null;
try {
mHistory = mSession.getHistoryIntervalForUid(mTemplate, uid,
@@ -571,6 +571,20 @@
}
/**
+ * Collects history results for network and resets history enumeration index.
+ */
+ void startHistoryDeviceEnumeration() {
+ try {
+ mHistory = mSession.getHistoryIntervalForNetwork(
+ mTemplate, NetworkStatsHistory.FIELD_ALL, mStartTimeStamp, mEndTimeStamp);
+ } catch (RemoteException e) {
+ Log.w(TAG, e);
+ mHistory = null;
+ }
+ mEnumerationIndex = 0;
+ }
+
+ /**
* Starts uid enumeration for current user.
* @throws RemoteException
*/
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index f74edb1..5ce7e59 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -17,7 +17,11 @@
package android.app.usage;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import android.Manifest;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -36,14 +40,12 @@
import android.net.NetworkStateSnapshot;
import android.net.NetworkTemplate;
import android.net.UnderlyingNetworkInfo;
+import android.net.netstats.IUsageCallback;
+import android.net.netstats.NetworkStatsDataMigrationUtils;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
-import android.os.Binder;
import android.os.Build;
import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.Messenger;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -54,7 +56,7 @@
import java.util.List;
import java.util.Objects;
-import java.util.Set;
+import java.util.concurrent.Executor;
/**
* Provides access to network usage history and statistics. Usage data is collected in
@@ -124,6 +126,14 @@
private final Context mContext;
private final INetworkStatsService mService;
+ /**
+ * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT}
+ * instead.
+ * @hide
+ */
+ @Deprecated
+ public static final String PREFIX_DEV = "dev";
+
/** @hide */
public static final int FLAG_POLL_ON_OPEN = 1 << 0;
/** @hide */
@@ -131,6 +141,18 @@
/** @hide */
public static final int FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN = 1 << 2;
+ /**
+ * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
+ * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
+ * with NR state as connected. This is a concept added by NetworkStats on top of the telephony
+ * constants for backward compatibility of metrics so this should not be overlapped with any of
+ * the {@code TelephonyManager.NETWORK_TYPE_*} constants.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int NETWORK_TYPE_5G_NSA = -2;
+
private int mFlags;
/** @hide */
@@ -142,6 +164,11 @@
setAugmentWithSubscriptionPlan(true);
}
+ /** @hide */
+ public INetworkStatsService getBinder() {
+ return mService;
+ }
+
/**
* Set poll on open flag to indicate the poll is needed before service gets statistics
* result. This is default enabled. However, for any non-privileged caller, the poll might
@@ -150,7 +177,13 @@
* @param pollOnOpen true if poll is needed.
* @hide
*/
- // @SystemApi(client = MODULE_LIBRARIES)
+ // The system will ignore any non-default values for non-privileged
+ // processes, so processes that don't hold the appropriate permissions
+ // can make no use of this API.
+ @SystemApi(client = MODULE_LIBRARIES)
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK})
public void setPollOnOpen(boolean pollOnOpen) {
if (pollOnOpen) {
mFlags |= FLAG_POLL_ON_OPEN;
@@ -204,9 +237,10 @@
*/
@NonNull
@WorkerThread
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
public Bucket querySummaryForDevice(@NonNull NetworkTemplate template,
long startTime, long endTime) {
+ Objects.requireNonNull(template);
try {
NetworkStats stats =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -378,10 +412,11 @@
* @hide
*/
@NonNull
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@WorkerThread
public NetworkStats querySummary(@NonNull NetworkTemplate template, long startTime,
long endTime) throws SecurityException {
+ Objects.requireNonNull(template);
try {
NetworkStats result =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -411,10 +446,11 @@
* @hide
*/
@NonNull
- // @SystemApi(client = MODULE_LIBRARIES)
+ @SystemApi(client = MODULE_LIBRARIES)
@WorkerThread
public NetworkStats queryTaggedSummary(@NonNull NetworkTemplate template, long startTime,
long endTime) throws SecurityException {
+ Objects.requireNonNull(template);
try {
NetworkStats result =
new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
@@ -427,6 +463,43 @@
}
/**
+ * Query usage statistics details for networks matching a given {@link NetworkTemplate}.
+ *
+ * Result is not aggregated over time. This means buckets' start and
+ * end timestamps will be between 'startTime' and 'endTime' parameters.
+ * <p>Only includes buckets whose entire time period is included between
+ * startTime and endTime. Doesn't interpolate or return partial buckets.
+ * Since bucket length is in the order of hours, this
+ * method cannot be used to measure data usage on a fine grained time scale.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @return Statistics which is described above.
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = MODULE_LIBRARIES)
+ @WorkerThread
+ public NetworkStats queryDetailsForDevice(@NonNull NetworkTemplate template,
+ long startTime, long endTime) {
+ Objects.requireNonNull(template);
+ try {
+ final NetworkStats result =
+ new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
+ result.startHistoryDeviceEnumeration();
+ return result;
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
+ return null; // To make the compiler happy.
+ }
+
+ /**
* Query network usage statistics details for a given uid.
* This may take a long time, and apps should avoid calling this on their main thread.
*
@@ -492,7 +565,8 @@
* @param endTime End of period. Defined in terms of "Unix time", see
* {@link java.lang.System#currentTimeMillis}.
* @param uid UID of app
- * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for no tags.
+ * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
+ * across all the tags.
* @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
* traffic from all states.
* @return Statistics object or null if an error happened during statistics collection.
@@ -507,21 +581,52 @@
return queryDetailsForUidTagState(template, startTime, endTime, uid, tag, state);
}
- /** @hide */
- public NetworkStats queryDetailsForUidTagState(NetworkTemplate template,
+ /**
+ * Query network usage statistics details for a given template, uid, tag, and state.
+ *
+ * Only usable for uids belonging to calling user. Result is not aggregated over time.
+ * This means buckets' start and end timestamps are going to be between 'startTime' and
+ * 'endTime' parameters. The uid is going to be the same as the 'uid' parameter, the tag
+ * the same as the 'tag' parameter, and the state the same as the 'state' parameter.
+ * defaultNetwork is going to be {@link NetworkStats.Bucket#DEFAULT_NETWORK_ALL},
+ * metered is going to be {@link NetworkStats.Bucket#METERED_ALL}, and
+ * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}.
+ * <p>Only includes buckets that atomically occur in the inclusive time range. Doesn't
+ * interpolate across partial buckets. Since bucket length is in the order of hours, this
+ * method cannot be used to measure data usage on a fine grained time scale.
+ * This may take a long time, and apps should avoid calling this on their main thread.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param startTime Start of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param endTime End of period, in milliseconds since the Unix epoch, see
+ * {@link java.lang.System#currentTimeMillis}.
+ * @param uid UID of app
+ * @param tag TAG of interest. Use {@link NetworkStats.Bucket#TAG_NONE} for aggregated data
+ * across all the tags.
+ * @param state state of interest. Use {@link NetworkStats.Bucket#STATE_ALL} to aggregate
+ * traffic from all states.
+ * @return Statistics which is described above.
+ * @hide
+ */
+ @NonNull
+ @SystemApi(client = MODULE_LIBRARIES)
+ @WorkerThread
+ public NetworkStats queryDetailsForUidTagState(@NonNull NetworkTemplate template,
long startTime, long endTime, int uid, int tag, int state) throws SecurityException {
-
- NetworkStats result;
+ Objects.requireNonNull(template);
try {
- result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
- result.startHistoryEnumeration(uid, tag, state);
+ final NetworkStats result = new NetworkStats(
+ mContext, template, mFlags, startTime, endTime, mService);
+ result.startHistoryUidEnumeration(uid, tag, state);
+ return result;
} catch (RemoteException e) {
Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag
+ " state=" + state, e);
- return null;
+ e.rethrowFromSystemServer();
}
- return result;
+ return null; // To make the compiler happy.
}
/**
@@ -578,50 +683,83 @@
}
/**
- * Query realtime network usage statistics details with interfaces constrains.
- * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING},
- * video calling data usage and count of network operations that set by
- * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any
- * statistics that is reported by {@link NetworkStatsProvider}.
+ * Query realtime mobile network usage statistics.
*
- * @param requiredIfaces A list of interfaces the stats should be restricted to, or
- * {@link NetworkStats#INTERFACES_ALL}.
+ * Return a snapshot of current UID network statistics, as it applies
+ * to the mobile radios of the device. The snapshot will include any
+ * tethering traffic, video calling data usage and count of
+ * network operations set by {@link TrafficStats#incrementOperationCount}
+ * made over a mobile radio.
+ * The snapshot will not include any statistics that cannot be seen by
+ * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
*
* @hide
*/
- //@SystemApi
+ @SystemApi
@RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
- @NonNull public android.net.NetworkStats getDetailedUidStats(
- @NonNull Set<String> requiredIfaces) {
- Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null");
+ @NonNull public android.net.NetworkStats getMobileUidStats() {
try {
- return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0]));
+ return mService.getUidStatsForTransport(TRANSPORT_CELLULAR);
} catch (RemoteException e) {
- if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats");
+ if (DBG) Log.d(TAG, "Remote exception when get Mobile uid stats");
throw e.rethrowFromSystemServer();
}
}
- /** @hide */
- public void registerUsageCallback(NetworkTemplate template, int networkType,
- long thresholdBytes, UsageCallback callback, @Nullable Handler handler) {
- Objects.requireNonNull(callback, "UsageCallback cannot be null");
-
- final Looper looper;
- if (handler == null) {
- looper = Looper.myLooper();
- } else {
- looper = handler.getLooper();
+ /**
+ * Query realtime Wi-Fi network usage statistics.
+ *
+ * Return a snapshot of current UID network statistics, as it applies
+ * to the Wi-Fi radios of the device. The snapshot will include any
+ * tethering traffic, video calling data usage and count of
+ * network operations set by {@link TrafficStats#incrementOperationCount}
+ * made over a Wi-Fi radio.
+ * The snapshot will not include any statistics that cannot be seen by
+ * the kernel, e.g. statistics reported by {@link NetworkStatsProvider}s.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK)
+ @NonNull public android.net.NetworkStats getWifiUidStats() {
+ try {
+ return mService.getUidStatsForTransport(TRANSPORT_WIFI);
+ } catch (RemoteException e) {
+ if (DBG) Log.d(TAG, "Remote exception when get WiFi uid stats");
+ throw e.rethrowFromSystemServer();
}
+ }
- DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
+ /**
+ * Registers to receive notifications about data usage on specified networks.
+ *
+ * <p>The callbacks will continue to be called as long as the process is alive or
+ * {@link #unregisterUsageCallback} is called.
+ *
+ * @param template Template used to match networks. See {@link NetworkTemplate}.
+ * @param thresholdBytes Threshold in bytes to be notified on. The provided value that lower
+ * than 2MiB will be clamped for non-privileged callers.
+ * @param executor The executor on which callback will be invoked. The provided {@link Executor}
+ * must run callback sequentially, otherwise the order of callbacks cannot be
+ * guaranteed.
+ * @param callback The {@link UsageCallback} that the system will call when data usage
+ * has exceeded the specified threshold.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void registerUsageCallback(@NonNull NetworkTemplate template, long thresholdBytes,
+ @NonNull @CallbackExecutor Executor executor, @NonNull UsageCallback callback) {
+ Objects.requireNonNull(template, "NetworkTemplate cannot be null");
+ Objects.requireNonNull(callback, "UsageCallback cannot be null");
+ Objects.requireNonNull(executor, "Executor cannot be null");
+
+ final DataUsageRequest request = new DataUsageRequest(DataUsageRequest.REQUEST_ID_UNSET,
template, thresholdBytes);
try {
- CallbackHandler callbackHandler = new CallbackHandler(looper, networkType,
- template.getSubscriberId(), callback);
+ final UsageCallbackWrapper callbackWrapper =
+ new UsageCallbackWrapper(executor, callback);
callback.request = mService.registerUsageCallback(
- mContext.getOpPackageName(), request, new Messenger(callbackHandler),
- new Binder());
+ mContext.getOpPackageName(), request, callbackWrapper);
if (DBG) Log.d(TAG, "registerUsageCallback returned " + callback.request);
if (callback.request == null) {
@@ -674,12 +812,15 @@
NetworkTemplate template = createTemplate(networkType, subscriberId);
if (DBG) {
Log.d(TAG, "registerUsageCallback called with: {"
- + " networkType=" + networkType
- + " subscriberId=" + subscriberId
- + " thresholdBytes=" + thresholdBytes
- + " }");
+ + " networkType=" + networkType
+ + " subscriberId=" + subscriberId
+ + " thresholdBytes=" + thresholdBytes
+ + " }");
}
- registerUsageCallback(template, networkType, thresholdBytes, callback, handler);
+
+ final Executor executor = handler == null ? r -> r.run() : r -> handler.post(r);
+
+ registerUsageCallback(template, thresholdBytes, executor, callback);
}
/**
@@ -704,6 +845,26 @@
* Base class for usage callbacks. Should be extended by applications wanting notifications.
*/
public static abstract class UsageCallback {
+ /**
+ * Called when data usage has reached the given threshold.
+ *
+ * Called by {@code NetworkStatsService} when the registered threshold is reached.
+ * If a caller implements {@link #onThresholdReached(NetworkTemplate)}, the system
+ * will not call {@link #onThresholdReached(int, String)}.
+ *
+ * @param template The {@link NetworkTemplate} that associated with this callback.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public void onThresholdReached(@NonNull NetworkTemplate template) {
+ // Backward compatibility for those who didn't override this function.
+ final int networkType = networkTypeForTemplate(template);
+ if (networkType != ConnectivityManager.TYPE_NONE) {
+ final String subscriberId = template.getSubscriberIds().isEmpty() ? null
+ : template.getSubscriberIds().iterator().next();
+ onThresholdReached(networkType, subscriberId);
+ }
+ }
/**
* Called when data usage has reached the given threshold.
@@ -714,6 +875,25 @@
* @hide used for internal bookkeeping
*/
private DataUsageRequest request;
+
+ /**
+ * Get network type from a template if feasible.
+ *
+ * @param template the target {@link NetworkTemplate}.
+ * @return legacy network type, only supports for the types which is already supported in
+ * {@link #registerUsageCallback(int, String, long, UsageCallback, Handler)}.
+ * {@link ConnectivityManager#TYPE_NONE} for other types.
+ */
+ private static int networkTypeForTemplate(@NonNull NetworkTemplate template) {
+ switch (template.getMatchRule()) {
+ case NetworkTemplate.MATCH_MOBILE:
+ return ConnectivityManager.TYPE_MOBILE;
+ case NetworkTemplate.MATCH_WIFI:
+ return ConnectivityManager.TYPE_WIFI;
+ default:
+ return ConnectivityManager.TYPE_NONE;
+ }
+ }
}
/**
@@ -832,43 +1012,32 @@
}
}
- private static class CallbackHandler extends Handler {
- private final int mNetworkType;
- private final String mSubscriberId;
- private UsageCallback mCallback;
+ private static class UsageCallbackWrapper extends IUsageCallback.Stub {
+ // Null if unregistered.
+ private volatile UsageCallback mCallback;
- CallbackHandler(Looper looper, int networkType, String subscriberId,
- UsageCallback callback) {
- super(looper);
- mNetworkType = networkType;
- mSubscriberId = subscriberId;
+ private final Executor mExecutor;
+
+ UsageCallbackWrapper(@NonNull Executor executor, @NonNull UsageCallback callback) {
mCallback = callback;
+ mExecutor = executor;
}
@Override
- public void handleMessage(Message message) {
- DataUsageRequest request =
- (DataUsageRequest) getObject(message, DataUsageRequest.PARCELABLE_KEY);
-
- switch (message.what) {
- case CALLBACK_LIMIT_REACHED: {
- if (mCallback != null) {
- mCallback.onThresholdReached(mNetworkType, mSubscriberId);
- } else {
- Log.e(TAG, "limit reached with released callback for " + request);
- }
- break;
- }
- case CALLBACK_RELEASED: {
- if (DBG) Log.d(TAG, "callback released for " + request);
- mCallback = null;
- break;
- }
+ public void onThresholdReached(DataUsageRequest request) {
+ // Copy it to a local variable in case mCallback changed inside the if condition.
+ final UsageCallback callback = mCallback;
+ if (callback != null) {
+ mExecutor.execute(() -> callback.onThresholdReached(request.template));
+ } else {
+ Log.e(TAG, "onThresholdReached with released callback for " + request);
}
}
- private static Object getObject(Message msg, String key) {
- return msg.getData().getParcelable(key);
+ @Override
+ public void onCallbackReleased(DataUsageRequest request) {
+ if (DBG) Log.d(TAG, "callback released for " + request);
+ mCallback = null;
}
}
@@ -877,7 +1046,7 @@
*
* @hide
*/
- // @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -890,17 +1059,18 @@
}
/**
- * Advise persistence threshold; may be overridden internally.
+ * Set default value of global alert bytes, the value will be clamped to [128kB, 2MB].
*
* @hide
*/
- // @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
- android.Manifest.permission.NETWORK_STACK})
- public void advisePersistThreshold(long thresholdBytes) {
+ Manifest.permission.NETWORK_STACK})
+ public void setDefaultGlobalAlert(long alertBytes) {
try {
- mService.advisePersistThreshold(thresholdBytes);
+ // TODO: Sync internal naming with the API surface.
+ mService.advisePersistThreshold(alertBytes);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -911,7 +1081,7 @@
*
* @hide
*/
- // @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -927,9 +1097,17 @@
* Set the warning and limit to all registered custom network stats providers.
* Note that invocation of any interface will be sent to all providers.
*
+ * Asynchronicity notes : because traffic may be happening on the device at the same time, it
+ * doesn't make sense to wait for the warning and limit to be set – a caller still wouldn't
+ * know when exactly it was effective. All that can matter is that it's done quickly. Also,
+ * this method can't fail, so there is no status to return. All providers will see the new
+ * values soon.
+ * As such, this method returns immediately and sends the warning and limit to all providers
+ * as soon as possible through a one-way binder call.
+ *
* @hide
*/
- // @SystemApi
+ @SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(anyOf = {
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
android.Manifest.permission.NETWORK_STACK})
@@ -941,4 +1119,52 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Get a RAT type representative of a group of RAT types for network statistics.
+ *
+ * Collapse the given Radio Access Technology (RAT) type into a bucket that
+ * is representative of the original RAT type for network statistics. The
+ * mapping mostly corresponds to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}
+ * but with adaptations specific to the virtual types introduced by
+ * networks stats.
+ *
+ * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static int getCollapsedRatType(int ratType) {
+ switch (ratType) {
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_GSM:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ return TelephonyManager.NETWORK_TYPE_GSM;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
+ return TelephonyManager.NETWORK_TYPE_UMTS;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ case TelephonyManager.NETWORK_TYPE_IWLAN:
+ return TelephonyManager.NETWORK_TYPE_LTE;
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return TelephonyManager.NETWORK_TYPE_NR;
+ // Virtual RAT type for 5G NSA mode, see
+ // {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
+ case NetworkStatsManager.NETWORK_TYPE_5G_NSA:
+ return NetworkStatsManager.NETWORK_TYPE_5G_NSA;
+ default:
+ return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ }
+ }
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
index ece54df..1f67f6d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetManager.java
@@ -19,12 +19,14 @@
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.RemoteException;
@@ -320,15 +322,15 @@
}
private static final class InternalNetworkManagementListener
- extends IInternalNetworkManagementListener.Stub {
+ extends IEthernetNetworkManagementListener.Stub {
@NonNull
private final Executor mExecutor;
@NonNull
- private final BiConsumer<Network, InternalNetworkManagementException> mListener;
+ private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
InternalNetworkManagementListener(
@NonNull final Executor executor,
- @NonNull final BiConsumer<Network, InternalNetworkManagementException> listener) {
+ @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) {
Objects.requireNonNull(executor, "Pass a non-null executor");
Objects.requireNonNull(listener, "Pass a non-null listener");
mExecutor = executor;
@@ -338,14 +340,14 @@
@Override
public void onComplete(
@Nullable final Network network,
- @Nullable final InternalNetworkManagementException e) {
+ @Nullable final EthernetNetworkManagementException e) {
mExecutor.execute(() -> mListener.accept(network, e));
}
}
private InternalNetworkManagementListener getInternalNetworkManagementListener(
@Nullable final Executor executor,
- @Nullable final BiConsumer<Network, InternalNetworkManagementException> listener) {
+ @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) {
if (null != listener) {
Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
}
@@ -358,11 +360,43 @@
return proxy;
}
- private void updateConfiguration(
+ /**
+ * Updates the configuration of an automotive device's ethernet network.
+ *
+ * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
+ * configuration for this network.
+ * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
+ * this network to put inside the {@code request}.
+ * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
+ * object for this network to put inside the {@code request}.
+ *
+ * If non-null, the listener will be called exactly once after this is called, unless
+ * a synchronous exception was thrown.
+ *
+ * @param iface the name of the interface to act upon.
+ * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
+ * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
+ * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
+ * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+ * @throws SecurityException if the process doesn't hold
+ * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
+ * @throws UnsupportedOperationException if called on a non-automotive device or on an
+ * unsupported interface.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK,
+ android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
+ @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ public void updateConfiguration(
@NonNull String iface,
- @NonNull InternalNetworkUpdateRequest request,
+ @NonNull EthernetNetworkUpdateRequest request,
@Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+ @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ Objects.requireNonNull(iface, "iface must be non-null");
+ Objects.requireNonNull(request, "request must be non-null");
final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
executor, listener);
try {
@@ -372,10 +406,34 @@
}
}
- private void connectNetwork(
+ /**
+ * Set an ethernet network's link state up.
+ *
+ * When the link is successfully turned up, the listener will be called with the resulting
+ * network. If any error or unexpected condition happens while the system tries to turn the
+ * interface up, the listener will be called with an appropriate exception.
+ * The listener is guaranteed to be called exactly once for each call to this method, but this
+ * may take an unbounded amount of time depending on the actual network conditions.
+ *
+ * @param iface the name of the interface to act upon.
+ * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
+ * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+ * @throws SecurityException if the process doesn't hold
+ * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
+ * @throws UnsupportedOperationException if called on a non-automotive device.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK,
+ android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
+ @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ public void connectNetwork(
@NonNull String iface,
@Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+ @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ Objects.requireNonNull(iface, "iface must be non-null");
final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
executor, listener);
try {
@@ -385,10 +443,33 @@
}
}
- private void disconnectNetwork(
+ /**
+ * Set an ethernet network's link state down.
+ *
+ * When the link is successfully turned down, the listener will be called with the network that
+ * was torn down, if any. If any error or unexpected condition happens while the system tries to
+ * turn the interface down, the listener will be called with an appropriate exception.
+ * The listener is guaranteed to be called exactly once for each call to this method.
+ *
+ * @param iface the name of the interface to act upon.
+ * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
+ * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
+ * @throws SecurityException if the process doesn't hold
+ * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
+ * @throws UnsupportedOperationException if called on a non-automotive device.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK,
+ android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
+ @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ public void disconnectNetwork(
@NonNull String iface,
@Nullable @CallbackExecutor Executor executor,
- @Nullable BiConsumer<Network, InternalNetworkManagementException> listener) {
+ @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
+ Objects.requireNonNull(iface, "iface must be non-null");
final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
executor, listener);
try {
diff --git a/core/java/android/net/InternalNetworkManagementException.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
similarity index 92%
rename from core/java/android/net/InternalNetworkManagementException.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
index dcce706..adf9e5a 100644
--- a/core/java/android/net/InternalNetworkManagementException.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.aidl
@@ -16,4 +16,4 @@
package android.net;
- parcelable InternalNetworkManagementException;
\ No newline at end of file
+ parcelable EthernetNetworkManagementException;
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
new file mode 100644
index 0000000..a69cc55
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkManagementException.java
@@ -0,0 +1,73 @@
+/*
+ * 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 android.net;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/** @hide */
+@SystemApi
+public final class EthernetNetworkManagementException
+ extends RuntimeException implements Parcelable {
+
+ /* @hide */
+ public EthernetNetworkManagementException(@NonNull final String errorMessage) {
+ super(errorMessage);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getMessage());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ final EthernetNetworkManagementException that = (EthernetNetworkManagementException) obj;
+
+ return Objects.equals(getMessage(), that.getMessage());
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(getMessage());
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<EthernetNetworkManagementException> CREATOR =
+ new Parcelable.Creator<EthernetNetworkManagementException>() {
+ @Override
+ public EthernetNetworkManagementException[] newArray(int size) {
+ return new EthernetNetworkManagementException[size];
+ }
+
+ @Override
+ public EthernetNetworkManagementException createFromParcel(@NonNull Parcel source) {
+ return new EthernetNetworkManagementException(source.readString());
+ }
+ };
+}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
index 62c5761..925d12b 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkSpecifier.java
@@ -23,8 +23,6 @@
import android.os.Parcelable;
import android.text.TextUtils;
-import com.android.internal.util.Preconditions;
-
import java.util.Objects;
/**
@@ -47,7 +45,9 @@
* @param interfaceName Name of the ethernet interface the specifier refers to.
*/
public EthernetNetworkSpecifier(@NonNull String interfaceName) {
- Preconditions.checkStringNotEmpty(interfaceName);
+ if (TextUtils.isEmpty(interfaceName)) {
+ throw new IllegalArgumentException();
+ }
mInterfaceName = interfaceName;
}
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.aidl b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
similarity index 93%
rename from core/java/android/net/InternalNetworkUpdateRequest.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
index da00cb9..debc348 100644
--- a/core/java/android/net/InternalNetworkUpdateRequest.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.aidl
@@ -16,4 +16,4 @@
package android.net;
- parcelable InternalNetworkUpdateRequest;
\ No newline at end of file
+ parcelable EthernetNetworkUpdateRequest;
\ No newline at end of file
diff --git a/core/java/android/net/InternalNetworkUpdateRequest.java b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
similarity index 78%
rename from core/java/android/net/InternalNetworkUpdateRequest.java
rename to packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
index f42c4b7..e879e40 100644
--- a/core/java/android/net/InternalNetworkUpdateRequest.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/EthernetNetworkUpdateRequest.java
@@ -17,13 +17,15 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/** @hide */
-public final class InternalNetworkUpdateRequest implements Parcelable {
+@SystemApi
+public final class EthernetNetworkUpdateRequest implements Parcelable {
@NonNull
private final StaticIpConfiguration mIpConfig;
@NonNull
@@ -39,8 +41,7 @@
return new NetworkCapabilities(mNetworkCapabilities);
}
- /** @hide */
- public InternalNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
+ public EthernetNetworkUpdateRequest(@NonNull final StaticIpConfiguration ipConfig,
@NonNull final NetworkCapabilities networkCapabilities) {
Objects.requireNonNull(ipConfig);
Objects.requireNonNull(networkCapabilities);
@@ -48,7 +49,7 @@
mNetworkCapabilities = new NetworkCapabilities(networkCapabilities);
}
- private InternalNetworkUpdateRequest(@NonNull final Parcel source) {
+ private EthernetNetworkUpdateRequest(@NonNull final Parcel source) {
Objects.requireNonNull(source);
mIpConfig = StaticIpConfiguration.CREATOR.createFromParcel(source);
mNetworkCapabilities = NetworkCapabilities.CREATOR.createFromParcel(source);
@@ -56,7 +57,7 @@
@Override
public String toString() {
- return "InternalNetworkUpdateRequest{"
+ return "EthernetNetworkUpdateRequest{"
+ "mIpConfig=" + mIpConfig
+ ", mNetworkCapabilities=" + mNetworkCapabilities + '}';
}
@@ -65,7 +66,7 @@
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- InternalNetworkUpdateRequest that = (InternalNetworkUpdateRequest) o;
+ EthernetNetworkUpdateRequest that = (EthernetNetworkUpdateRequest) o;
return Objects.equals(that.getIpConfig(), mIpConfig)
&& Objects.equals(that.getNetworkCapabilities(), mNetworkCapabilities);
@@ -88,16 +89,16 @@
}
@NonNull
- public static final Parcelable.Creator<InternalNetworkUpdateRequest> CREATOR =
- new Parcelable.Creator<InternalNetworkUpdateRequest>() {
+ public static final Parcelable.Creator<EthernetNetworkUpdateRequest> CREATOR =
+ new Parcelable.Creator<EthernetNetworkUpdateRequest>() {
@Override
- public InternalNetworkUpdateRequest[] newArray(int size) {
- return new InternalNetworkUpdateRequest[size];
+ public EthernetNetworkUpdateRequest[] newArray(int size) {
+ return new EthernetNetworkUpdateRequest[size];
}
@Override
- public InternalNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
- return new InternalNetworkUpdateRequest(source);
+ public EthernetNetworkUpdateRequest createFromParcel(@NonNull Parcel source) {
+ return new EthernetNetworkUpdateRequest(source);
}
};
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
index e688bea..544d02b 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetManager.aidl
@@ -18,8 +18,8 @@
import android.net.IpConfiguration;
import android.net.IEthernetServiceListener;
-import android.net.IInternalNetworkManagementListener;
-import android.net.InternalNetworkUpdateRequest;
+import android.net.IEthernetNetworkManagementListener;
+import android.net.EthernetNetworkUpdateRequest;
import android.net.ITetheredInterfaceCallback;
/**
@@ -38,8 +38,8 @@
void setIncludeTestInterfaces(boolean include);
void requestTetheredInterface(in ITetheredInterfaceCallback callback);
void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
- void updateConfiguration(String iface, in InternalNetworkUpdateRequest request,
- in IInternalNetworkManagementListener listener);
- void connectNetwork(String iface, in IInternalNetworkManagementListener listener);
- void disconnectNetwork(String iface, in IInternalNetworkManagementListener listener);
+ void updateConfiguration(String iface, in EthernetNetworkUpdateRequest request,
+ in IEthernetNetworkManagementListener listener);
+ void connectNetwork(String iface, in IEthernetNetworkManagementListener listener);
+ void disconnectNetwork(String iface, in IEthernetNetworkManagementListener listener);
}
diff --git a/core/java/android/net/IInternalNetworkManagementListener.aidl b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
similarity index 80%
rename from core/java/android/net/IInternalNetworkManagementListener.aidl
rename to packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
index 69cde3b..93edccf 100644
--- a/core/java/android/net/IInternalNetworkManagementListener.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/IEthernetNetworkManagementListener.aidl
@@ -16,10 +16,10 @@
package android.net;
-import android.net.InternalNetworkManagementException;
+import android.net.EthernetNetworkManagementException;
import android.net.Network;
/** @hide */
-oneway interface IInternalNetworkManagementListener {
- void onComplete(in Network network, in InternalNetworkManagementException exception);
+oneway interface IEthernetNetworkManagementListener {
+ void onComplete(in Network network, in EthernetNetworkManagementException exception);
}
\ No newline at end of file
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
index a4babb5..efe626d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsService.aidl
@@ -24,6 +24,7 @@
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.UnderlyingNetworkInfo;
+import android.net.netstats.IUsageCallback;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.os.IBinder;
@@ -49,14 +50,8 @@
@UnsupportedAppUsage
NetworkStats getDataLayerSnapshotForUid(int uid);
- /** Get a detailed snapshot of stats since boot for all UIDs.
- *
- * <p>Results will not always be limited to stats on requiredIfaces when specified: stats for
- * interfaces stacked on the specified interfaces, or for interfaces on which the specified
- * interfaces are stacked on, will also be included.
- * @param requiredIfaces Interface names to get data for, or {@link NetworkStats#INTERFACES_ALL}.
- */
- NetworkStats getDetailedUidStats(in String[] requiredIfaces);
+ /** Get the transport NetworkStats for all UIDs since boot. */
+ NetworkStats getUidStatsForTransport(int transport);
/** Return set of any ifaces associated with mobile networks since boot. */
@UnsupportedAppUsage
@@ -77,7 +72,7 @@
/** Registers a callback on data usage. */
DataUsageRequest registerUsageCallback(String callingPackage,
- in DataUsageRequest request, in Messenger messenger, in IBinder binder);
+ in DataUsageRequest request, in IUsageCallback callback);
/** Unregisters a callback on data usage. */
void unregisterUsageRequest(in DataUsageRequest request);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
index babe0bf..ab70be8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
+++ b/packages/ConnectivityT/framework-t/src/android/net/INetworkStatsSession.aidl
@@ -32,6 +32,11 @@
/** Return historical network layer stats for traffic that matches template. */
@UnsupportedAppUsage
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
+ /**
+ * Return historical network layer stats for traffic that matches template, start and end
+ * timestamp.
+ */
+ NetworkStatsHistory getHistoryIntervalForNetwork(in NetworkTemplate template, int fields, long start, long end);
/**
* Return network layer usage summary per UID for traffic that matches template.
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
index a84e7a9..10a22ac 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecAlgorithm.java
@@ -343,7 +343,7 @@
// Load and validate the optional algorithm resource. Undefined or duplicate algorithms in
// the resource are not allowed.
final String[] resourceAlgos = systemResources.getStringArray(
- com.android.internal.R.array.config_optionalIpSecAlgorithms);
+ android.R.array.config_optionalIpSecAlgorithms);
for (String str : resourceAlgos) {
if (!ALGO_TO_REQUIRED_FIRST_SDK.containsKey(str) || !enabledAlgos.add(str)) {
// This error should be caught by CTS and never be thrown to API callers
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
index 49aa99b..a423783 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecManager.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -988,6 +989,29 @@
}
/**
+ * @hide
+ */
+ public IpSecTransformResponse createTransform(IpSecConfig config, IBinder binder,
+ String callingPackage) {
+ try {
+ return mService.createTransform(config, binder, callingPackage);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void deleteTransform(int resourceId) {
+ try {
+ mService.deleteTransform(resourceId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Construct an instance of IpSecManager within an application context.
*
* @param context the application context for this manager
diff --git a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
index 36199a0..68ae5de 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/IpSecTransform.java
@@ -26,9 +26,6 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.util.Log;
@@ -93,16 +90,9 @@
mResourceId = INVALID_RESOURCE_ID;
}
- private IIpSecService getIpSecService() {
- IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
- if (b == null) {
- throw new RemoteException("Failed to connect to IpSecService")
- .rethrowAsRuntimeException();
- }
-
- return IIpSecService.Stub.asInterface(b);
+ private IpSecManager getIpSecManager(Context context) {
+ return context.getSystemService(IpSecManager.class);
}
-
/**
* Checks the result status and throws an appropriate exception if the status is not Status.OK.
*/
@@ -130,8 +120,7 @@
IpSecManager.SpiUnavailableException {
synchronized (this) {
try {
- IIpSecService svc = getIpSecService();
- IpSecTransformResponse result = svc.createTransform(
+ IpSecTransformResponse result = getIpSecManager(mContext).createTransform(
mConfig, new Binder(), mContext.getOpPackageName());
int status = result.status;
checkResultStatus(status);
@@ -140,8 +129,6 @@
mCloseGuard.open("build");
} catch (ServiceSpecificException e) {
throw IpSecManager.rethrowUncheckedExceptionFromServiceSpecificException(e);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
}
}
@@ -177,10 +164,7 @@
return;
}
try {
- IIpSecService svc = getIpSecService();
- svc.deleteTransform(mResourceId);
- } catch (RemoteException e) {
- throw e.rethrowAsRuntimeException();
+ getIpSecManager(mContext).deleteTransform(mResourceId);
} catch (Exception e) {
// On close we swallow all random exceptions since failure to close is not
// actionable by the user.
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
index 8f1115e..56faa52 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentity.java
@@ -16,18 +16,29 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.service.NetworkIdentityProto;
-import android.telephony.Annotation.NetworkType;
+import android.telephony.TelephonyManager;
import android.util.proto.ProtoOutputStream;
+import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.NetworkCapabilitiesUtils;
import com.android.net.module.util.NetworkIdentityUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Objects;
@@ -37,11 +48,24 @@
*
* @hide
*/
-public class NetworkIdentity implements Comparable<NetworkIdentity> {
+@SystemApi(client = MODULE_LIBRARIES)
+public class NetworkIdentity {
private static final String TAG = "NetworkIdentity";
+ /** @hide */
+ // TODO: Remove this after migrating all callers to use
+ // {@link NetworkTemplate#NETWORK_TYPE_ALL} instead.
public static final int SUBTYPE_COMBINED = -1;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "OEM_MANAGED_" }, flag = true, value = {
+ NetworkTemplate.OEM_MANAGED_NO,
+ NetworkTemplate.OEM_MANAGED_PAID,
+ NetworkTemplate.OEM_MANAGED_PRIVATE
+ })
+ public @interface OemManaged{}
+
/**
* Network has no {@code NetworkCapabilities#NET_CAPABILITY_OEM_*}.
* @hide
@@ -51,29 +75,32 @@
* Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}.
* @hide
*/
- public static final int OEM_PAID = 0x1;
+ public static final int OEM_PAID = 1 << 0;
/**
* Network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}.
* @hide
*/
- public static final int OEM_PRIVATE = 0x2;
+ public static final int OEM_PRIVATE = 1 << 1;
+
+ private static final long SUPPORTED_OEM_MANAGED_TYPES = OEM_PAID | OEM_PRIVATE;
final int mType;
- final int mSubType;
+ final int mRatType;
final String mSubscriberId;
- final String mNetworkId;
+ final String mWifiNetworkKey;
final boolean mRoaming;
final boolean mMetered;
final boolean mDefaultNetwork;
final int mOemManaged;
+ /** @hide */
public NetworkIdentity(
- int type, int subType, String subscriberId, String networkId, boolean roaming,
- boolean metered, boolean defaultNetwork, int oemManaged) {
+ int type, int ratType, @Nullable String subscriberId, @Nullable String wifiNetworkKey,
+ boolean roaming, boolean metered, boolean defaultNetwork, int oemManaged) {
mType = type;
- mSubType = subType;
+ mRatType = ratType;
mSubscriberId = subscriberId;
- mNetworkId = networkId;
+ mWifiNetworkKey = wifiNetworkKey;
mRoaming = roaming;
mMetered = metered;
mDefaultNetwork = defaultNetwork;
@@ -82,7 +109,7 @@
@Override
public int hashCode() {
- return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered,
+ return Objects.hash(mType, mRatType, mSubscriberId, mWifiNetworkKey, mRoaming, mMetered,
mDefaultNetwork, mOemManaged);
}
@@ -90,9 +117,9 @@
public boolean equals(@Nullable Object obj) {
if (obj instanceof NetworkIdentity) {
final NetworkIdentity ident = (NetworkIdentity) obj;
- return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
+ return mType == ident.mType && mRatType == ident.mRatType && mRoaming == ident.mRoaming
&& Objects.equals(mSubscriberId, ident.mSubscriberId)
- && Objects.equals(mNetworkId, ident.mNetworkId)
+ && Objects.equals(mWifiNetworkKey, ident.mWifiNetworkKey)
&& mMetered == ident.mMetered
&& mDefaultNetwork == ident.mDefaultNetwork
&& mOemManaged == ident.mOemManaged;
@@ -104,18 +131,18 @@
public String toString() {
final StringBuilder builder = new StringBuilder("{");
builder.append("type=").append(mType);
- builder.append(", subType=");
- if (mSubType == SUBTYPE_COMBINED) {
+ builder.append(", ratType=");
+ if (mRatType == NETWORK_TYPE_ALL) {
builder.append("COMBINED");
} else {
- builder.append(mSubType);
+ builder.append(mRatType);
}
if (mSubscriberId != null) {
builder.append(", subscriberId=")
.append(NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
}
- if (mNetworkId != null) {
- builder.append(", networkId=").append(mNetworkId);
+ if (mWifiNetworkKey != null) {
+ builder.append(", wifiNetworkKey=").append(mWifiNetworkKey);
}
if (mRoaming) {
builder.append(", ROAMING");
@@ -153,18 +180,14 @@
}
}
+ /** @hide */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
proto.write(NetworkIdentityProto.TYPE, mType);
- // Not dumping mSubType, subtypes are no longer supported.
+ // TODO: dump mRatType as well.
- if (mSubscriberId != null) {
- proto.write(NetworkIdentityProto.SUBSCRIBER_ID,
- NetworkIdentityUtils.scrubSubscriberId(mSubscriberId));
- }
- proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId);
proto.write(NetworkIdentityProto.ROAMING, mRoaming);
proto.write(NetworkIdentityProto.METERED, mMetered);
proto.write(NetworkIdentityProto.DEFAULT_NETWORK, mDefaultNetwork);
@@ -173,77 +196,98 @@
proto.end(start);
}
+ /** Get the network type of this instance. */
public int getType() {
return mType;
}
- public int getSubType() {
- return mSubType;
+ /** Get the Radio Access Technology(RAT) type of this instance. */
+ public int getRatType() {
+ return mRatType;
}
+ /** Get the Subscriber Id of this instance. */
+ @Nullable
public String getSubscriberId() {
return mSubscriberId;
}
- public String getNetworkId() {
- return mNetworkId;
+ /** Get the Wifi Network Key of this instance. See {@link WifiInfo#getNetworkKey()}. */
+ @Nullable
+ public String getWifiNetworkKey() {
+ return mWifiNetworkKey;
}
+ /** @hide */
+ // TODO: Remove this function after all callers are removed.
public boolean getRoaming() {
return mRoaming;
}
+ /** Return whether this network is roaming. */
+ public boolean isRoaming() {
+ return mRoaming;
+ }
+
+ /** @hide */
+ // TODO: Remove this function after all callers are removed.
public boolean getMetered() {
return mMetered;
}
+ /** Return whether this network is metered. */
+ public boolean isMetered() {
+ return mMetered;
+ }
+
+ /** @hide */
+ // TODO: Remove this function after all callers are removed.
public boolean getDefaultNetwork() {
return mDefaultNetwork;
}
+ /** Return whether this network is the default network. */
+ public boolean isDefaultNetwork() {
+ return mDefaultNetwork;
+ }
+
+ /** Get the OEM managed type of this instance. */
public int getOemManaged() {
return mOemManaged;
}
/**
- * Build a {@link NetworkIdentity} from the given {@link NetworkStateSnapshot} and
- * {@code subType}, assuming that any mobile networks are using the current IMSI.
- * The subType if applicable, should be set as one of the TelephonyManager.NETWORK_TYPE_*
- * constants, or {@link android.telephony.TelephonyManager#NETWORK_TYPE_UNKNOWN} if not.
+ * Assemble a {@link NetworkIdentity} from the passed arguments.
+ *
+ * This methods builds an identity based on the capabilities of the network in the
+ * snapshot and other passed arguments. The identity is used as a key to record data usage.
+ *
+ * @param snapshot the snapshot of network state. See {@link NetworkStateSnapshot}.
+ * @param defaultNetwork whether the network is a default network.
+ * @param ratType the Radio Access Technology(RAT) type of the network. Or
+ * {@link TelephonyManager#NETWORK_TYPE_UNKNOWN} if not applicable.
+ * See {@code TelephonyManager.NETWORK_TYPE_*}.
+ * @hide
+ * @deprecated See {@link NetworkIdentity.Builder}.
*/
+ // TODO: Remove this after all callers are migrated to use new Api.
+ @Deprecated
+ @NonNull
public static NetworkIdentity buildNetworkIdentity(Context context,
- NetworkStateSnapshot snapshot, boolean defaultNetwork, @NetworkType int subType) {
- final int legacyType = snapshot.getLegacyType();
-
- final String subscriberId = snapshot.getSubscriberId();
- String networkId = null;
- boolean roaming = !snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
- boolean metered = !(snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
- || snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED));
-
- final int oemManaged = getOemBitfield(snapshot.getNetworkCapabilities());
-
- if (legacyType == TYPE_WIFI) {
- final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
- .getTransportInfo();
- if (transportInfo instanceof WifiInfo) {
- final WifiInfo info = (WifiInfo) transportInfo;
- networkId = info != null ? info.getCurrentNetworkKey() : null;
- }
+ @NonNull NetworkStateSnapshot snapshot, boolean defaultNetwork, int ratType) {
+ final NetworkIdentity.Builder builder = new NetworkIdentity.Builder()
+ .setNetworkStateSnapshot(snapshot).setDefaultNetwork(defaultNetwork);
+ if (snapshot.getLegacyType() == TYPE_MOBILE && ratType != NETWORK_TYPE_ALL) {
+ builder.setRatType(ratType);
}
-
- return new NetworkIdentity(legacyType, subType, subscriberId, networkId, roaming, metered,
- defaultNetwork, oemManaged);
+ return builder.build();
}
/**
* Builds a bitfield of {@code NetworkIdentity.OEM_*} based on {@link NetworkCapabilities}.
* @hide
*/
- public static int getOemBitfield(NetworkCapabilities nc) {
+ public static int getOemBitfield(@NonNull NetworkCapabilities nc) {
int oemManaged = OEM_NONE;
if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_OEM_PAID)) {
@@ -256,30 +300,266 @@
return oemManaged;
}
- @Override
- public int compareTo(NetworkIdentity another) {
- int res = Integer.compare(mType, another.mType);
+ /** @hide */
+ public static int compare(@NonNull NetworkIdentity left, @NonNull NetworkIdentity right) {
+ Objects.requireNonNull(right);
+ int res = Integer.compare(left.mType, right.mType);
if (res == 0) {
- res = Integer.compare(mSubType, another.mSubType);
+ res = Integer.compare(left.mRatType, right.mRatType);
}
- if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) {
- res = mSubscriberId.compareTo(another.mSubscriberId);
+ if (res == 0 && left.mSubscriberId != null && right.mSubscriberId != null) {
+ res = left.mSubscriberId.compareTo(right.mSubscriberId);
}
- if (res == 0 && mNetworkId != null && another.mNetworkId != null) {
- res = mNetworkId.compareTo(another.mNetworkId);
+ if (res == 0 && left.mWifiNetworkKey != null && right.mWifiNetworkKey != null) {
+ res = left.mWifiNetworkKey.compareTo(right.mWifiNetworkKey);
}
if (res == 0) {
- res = Boolean.compare(mRoaming, another.mRoaming);
+ res = Boolean.compare(left.mRoaming, right.mRoaming);
}
if (res == 0) {
- res = Boolean.compare(mMetered, another.mMetered);
+ res = Boolean.compare(left.mMetered, right.mMetered);
}
if (res == 0) {
- res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork);
+ res = Boolean.compare(left.mDefaultNetwork, right.mDefaultNetwork);
}
if (res == 0) {
- res = Integer.compare(mOemManaged, another.mOemManaged);
+ res = Integer.compare(left.mOemManaged, right.mOemManaged);
}
return res;
}
+
+ /**
+ * Builder class for {@link NetworkIdentity}.
+ */
+ public static final class Builder {
+ // Need to be synchronized with ConnectivityManager.
+ // TODO: Use {@link ConnectivityManager#MAX_NETWORK_TYPE} when this file is in the module.
+ private static final int MAX_NETWORK_TYPE = 18; // TYPE_TEST
+ private static final int MIN_NETWORK_TYPE = TYPE_MOBILE;
+
+ private int mType;
+ private int mRatType;
+ private String mSubscriberId;
+ private String mWifiNetworkKey;
+ private boolean mRoaming;
+ private boolean mMetered;
+ private boolean mDefaultNetwork;
+ private int mOemManaged;
+
+ /**
+ * Creates a new Builder.
+ */
+ public Builder() {
+ // Initialize with default values. Will be overwritten by setters.
+ mType = ConnectivityManager.TYPE_NONE;
+ mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
+ mSubscriberId = null;
+ mWifiNetworkKey = null;
+ mRoaming = false;
+ mMetered = false;
+ mDefaultNetwork = false;
+ mOemManaged = NetworkTemplate.OEM_MANAGED_NO;
+ }
+
+ /**
+ * Add an {@link NetworkStateSnapshot} into the {@link NetworkIdentity} instance.
+ * This is a useful shorthand that will read from the snapshot and set the
+ * following fields, if they are set in the snapshot :
+ * - type
+ * - subscriberId
+ * - roaming
+ * - metered
+ * - oemManaged
+ * - wifiNetworkKey
+ *
+ * @param snapshot The target {@link NetworkStateSnapshot} object.
+ * @return The builder object.
+ */
+ @SuppressLint("MissingGetterMatchingBuilder")
+ @NonNull
+ public Builder setNetworkStateSnapshot(@NonNull NetworkStateSnapshot snapshot) {
+ setType(snapshot.getLegacyType());
+
+ setSubscriberId(snapshot.getSubscriberId());
+ setRoaming(!snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING));
+ setMetered(!(snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
+ || snapshot.getNetworkCapabilities().hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED)));
+
+ setOemManaged(getOemBitfield(snapshot.getNetworkCapabilities()));
+
+ if (mType == TYPE_WIFI) {
+ final TransportInfo transportInfo = snapshot.getNetworkCapabilities()
+ .getTransportInfo();
+ if (transportInfo instanceof WifiInfo) {
+ final WifiInfo info = (WifiInfo) transportInfo;
+ setWifiNetworkKey(info.getNetworkKey());
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Set the network type of the network.
+ *
+ * @param type the network type. See {@link ConnectivityManager#TYPE_*}.
+ *
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setType(int type) {
+ // Include TYPE_NONE for compatibility, type field might not be filled by some
+ // networks such as test networks.
+ if ((type < MIN_NETWORK_TYPE || MAX_NETWORK_TYPE < type)
+ && type != ConnectivityManager.TYPE_NONE) {
+ throw new IllegalArgumentException("Invalid network type: " + type);
+ }
+ mType = type;
+ return this;
+ }
+
+ /**
+ * Set the Radio Access Technology(RAT) type of the network.
+ *
+ * No RAT type is specified by default. Call clearRatType to reset.
+ *
+ * @param ratType the Radio Access Technology(RAT) type if applicable. See
+ * {@code TelephonyManager.NETWORK_TYPE_*}.
+ *
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRatType(int ratType) {
+ if (!CollectionUtils.contains(TelephonyManager.getAllNetworkTypes(), ratType)
+ && ratType != TelephonyManager.NETWORK_TYPE_UNKNOWN
+ && ratType != NetworkStatsManager.NETWORK_TYPE_5G_NSA) {
+ throw new IllegalArgumentException("Invalid ratType " + ratType);
+ }
+ mRatType = ratType;
+ return this;
+ }
+
+ /**
+ * Clear the Radio Access Technology(RAT) type of the network.
+ *
+ * @return this builder.
+ */
+ @NonNull
+ public Builder clearRatType() {
+ mRatType = NetworkTemplate.NETWORK_TYPE_ALL;
+ return this;
+ }
+
+ /**
+ * Set the Subscriber Id.
+ *
+ * @param subscriberId the Subscriber Id of the network. Or null if not applicable.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setSubscriberId(@Nullable String subscriberId) {
+ mSubscriberId = subscriberId;
+ return this;
+ }
+
+ /**
+ * Set the Wifi Network Key.
+ *
+ * @param wifiNetworkKey Wifi Network Key of the network,
+ * see {@link WifiInfo#getNetworkKey()}.
+ * Or null if not applicable.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setWifiNetworkKey(@Nullable String wifiNetworkKey) {
+ mWifiNetworkKey = wifiNetworkKey;
+ return this;
+ }
+
+ /**
+ * Set whether this network is roaming.
+ *
+ * This field is false by default. Call with false to reset.
+ *
+ * @param roaming the roaming status of the network.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setRoaming(boolean roaming) {
+ mRoaming = roaming;
+ return this;
+ }
+
+ /**
+ * Set whether this network is metered.
+ *
+ * This field is false by default. Call with false to reset.
+ *
+ * @param metered the meteredness of the network.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setMetered(boolean metered) {
+ mMetered = metered;
+ return this;
+ }
+
+ /**
+ * Set whether this network is the default network.
+ *
+ * This field is false by default. Call with false to reset.
+ *
+ * @param defaultNetwork the default network status of the network.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setDefaultNetwork(boolean defaultNetwork) {
+ mDefaultNetwork = defaultNetwork;
+ return this;
+ }
+
+ /**
+ * Set the OEM managed type.
+ *
+ * @param oemManaged Type of OEM managed network or unmanaged networks.
+ * See {@code NetworkTemplate#OEM_MANAGED_*}.
+ * @return this builder.
+ */
+ @NonNull
+ public Builder setOemManaged(@OemManaged int oemManaged) {
+ // Assert input does not contain illegal oemManage bits.
+ if ((~SUPPORTED_OEM_MANAGED_TYPES & oemManaged) != 0) {
+ throw new IllegalArgumentException("Invalid value for OemManaged : " + oemManaged);
+ }
+ mOemManaged = oemManaged;
+ return this;
+ }
+
+ private void ensureValidParameters() {
+ // Assert non-mobile network cannot have a ratType.
+ if (mType != TYPE_MOBILE && mRatType != NetworkTemplate.NETWORK_TYPE_ALL) {
+ throw new IllegalArgumentException(
+ "Invalid ratType " + mRatType + " for type " + mType);
+ }
+
+ // Assert non-wifi network cannot have a wifi network key.
+ if (mType != TYPE_WIFI && mWifiNetworkKey != null) {
+ throw new IllegalArgumentException("Invalid wifi network key for type " + mType);
+ }
+ }
+
+ /**
+ * Builds the instance of the {@link NetworkIdentity}.
+ *
+ * @return the built instance of {@link NetworkIdentity}.
+ */
+ @NonNull
+ public NetworkIdentity build() {
+ ensureValidParameters();
+ return new NetworkIdentity(mType, mRatType, mSubscriberId, mWifiNetworkKey,
+ mRoaming, mMetered, mDefaultNetwork, mOemManaged);
+ }
+ }
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
index abbebef..dfa347f 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkIdentitySet.java
@@ -18,6 +18,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE;
+import android.annotation.NonNull;
import android.service.NetworkIdentitySetProto;
import android.util.proto.ProtoOutputStream;
@@ -25,6 +26,8 @@
import java.io.DataOutput;
import java.io.IOException;
import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
/**
* Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
@@ -32,8 +35,7 @@
*
* @hide
*/
-public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements
- Comparable<NetworkIdentitySet> {
+public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_ROAMING = 2;
private static final int VERSION_ADD_NETWORK_ID = 3;
@@ -41,9 +43,19 @@
private static final int VERSION_ADD_DEFAULT_NETWORK = 5;
private static final int VERSION_ADD_OEM_MANAGED_NETWORK = 6;
+ /**
+ * Construct a {@link NetworkIdentitySet} object.
+ */
public NetworkIdentitySet() {
+ super();
}
+ /** @hide */
+ public NetworkIdentitySet(@NonNull Set<NetworkIdentity> ident) {
+ super(ident);
+ }
+
+ /** @hide */
public NetworkIdentitySet(DataInput in) throws IOException {
final int version = in.readInt();
final int size = in.readInt();
@@ -52,7 +64,7 @@
final int ignored = in.readInt();
}
final int type = in.readInt();
- final int subType = in.readInt();
+ final int ratType = in.readInt();
final String subscriberId = readOptionalString(in);
final String networkId;
if (version >= VERSION_ADD_NETWORK_ID) {
@@ -91,63 +103,73 @@
oemNetCapabilities = NetworkIdentity.OEM_NONE;
}
- add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered,
+ add(new NetworkIdentity(type, ratType, subscriberId, networkId, roaming, metered,
defaultNetwork, oemNetCapabilities));
}
}
/**
* Method to serialize this object into a {@code DataOutput}.
+ * @hide
*/
public void writeToStream(DataOutput out) throws IOException {
out.writeInt(VERSION_ADD_OEM_MANAGED_NETWORK);
out.writeInt(size());
for (NetworkIdentity ident : this) {
out.writeInt(ident.getType());
- out.writeInt(ident.getSubType());
+ out.writeInt(ident.getRatType());
writeOptionalString(out, ident.getSubscriberId());
- writeOptionalString(out, ident.getNetworkId());
- out.writeBoolean(ident.getRoaming());
- out.writeBoolean(ident.getMetered());
- out.writeBoolean(ident.getDefaultNetwork());
+ writeOptionalString(out, ident.getWifiNetworkKey());
+ out.writeBoolean(ident.isRoaming());
+ out.writeBoolean(ident.isMetered());
+ out.writeBoolean(ident.isDefaultNetwork());
out.writeInt(ident.getOemManaged());
}
}
- /** @return whether any {@link NetworkIdentity} in this set is considered metered. */
+ /**
+ * @return whether any {@link NetworkIdentity} in this set is considered metered.
+ * @hide
+ */
public boolean isAnyMemberMetered() {
if (isEmpty()) {
return false;
}
for (NetworkIdentity ident : this) {
- if (ident.getMetered()) {
+ if (ident.isMetered()) {
return true;
}
}
return false;
}
- /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */
+ /**
+ * @return whether any {@link NetworkIdentity} in this set is considered roaming.
+ * @hide
+ */
public boolean isAnyMemberRoaming() {
if (isEmpty()) {
return false;
}
for (NetworkIdentity ident : this) {
- if (ident.getRoaming()) {
+ if (ident.isRoaming()) {
return true;
}
}
return false;
}
- /** @return whether any {@link NetworkIdentity} in this set is considered on the default
- network. */
+ /**
+ * @return whether any {@link NetworkIdentity} in this set is considered on the default
+ * network.
+ * @hide
+ */
public boolean areAllMembersOnDefaultNetwork() {
if (isEmpty()) {
return true;
}
for (NetworkIdentity ident : this) {
- if (!ident.getDefaultNetwork()) {
+ if (!ident.isDefaultNetwork()) {
return false;
}
}
@@ -171,18 +193,20 @@
}
}
- @Override
- public int compareTo(NetworkIdentitySet another) {
- if (isEmpty()) return -1;
- if (another.isEmpty()) return 1;
+ public static int compare(@NonNull NetworkIdentitySet left, @NonNull NetworkIdentitySet right) {
+ Objects.requireNonNull(left);
+ Objects.requireNonNull(right);
+ if (left.isEmpty()) return -1;
+ if (right.isEmpty()) return 1;
- final NetworkIdentity ident = iterator().next();
- final NetworkIdentity anotherIdent = another.iterator().next();
- return ident.compareTo(anotherIdent);
+ final NetworkIdentity leftIdent = left.iterator().next();
+ final NetworkIdentity rightIdent = right.iterator().next();
+ return NetworkIdentity.compare(leftIdent, rightIdent);
}
/**
* Method to dump this object into proto debug file.
+ * @hide
*/
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
index 9d532e7..9175809 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStats.java
@@ -41,6 +41,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -57,7 +58,7 @@
*/
// @NotThreadSafe
@SystemApi
-public final class NetworkStats implements Parcelable {
+public final class NetworkStats implements Parcelable, Iterable<NetworkStats.Entry> {
private static final String TAG = "NetworkStats";
/**
@@ -678,6 +679,35 @@
}
/**
+ * Iterate over Entry objects.
+ *
+ * Return an iterator of this object that will iterate through all contained Entry objects.
+ *
+ * This iterator does not support concurrent modification and makes no guarantee of fail-fast
+ * behavior. If any method that can mutate the contents of this object is called while
+ * iteration is in progress, either inside the loop or in another thread, then behavior is
+ * undefined.
+ * The remove() method is not implemented and will throw UnsupportedOperationException.
+ * @hide
+ */
+ @SystemApi
+ @NonNull public Iterator<Entry> iterator() {
+ return new Iterator<Entry>() {
+ int mIndex = 0;
+
+ @Override
+ public boolean hasNext() {
+ return mIndex < size;
+ }
+
+ @Override
+ public Entry next() {
+ return getValues(mIndex++, null);
+ }
+ };
+ }
+
+ /**
* Return specific stats entry.
* @hide
*/
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
index 9f9d73f..735c44d 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsCollection.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
import static android.net.NetworkStats.DEFAULT_NETWORK_YES;
import static android.net.NetworkStats.IFACE_ALL;
@@ -32,6 +33,10 @@
import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.NetworkStatsHistory.Entry;
import android.os.Binder;
import android.service.NetworkStatsCollectionKeyProto;
import android.service.NetworkStatsCollectionProto;
@@ -69,7 +74,10 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import java.util.Objects;
+import java.util.Set;
/**
* Collection of {@link NetworkStatsHistory}, stored based on combined key of
@@ -77,6 +85,7 @@
*
* @hide
*/
+@SystemApi(client = MODULE_LIBRARIES)
public class NetworkStatsCollection implements FileRotator.Reader, FileRotator.Writer {
private static final String TAG = NetworkStatsCollection.class.getSimpleName();
/** File header magic number: "ANET" */
@@ -100,15 +109,23 @@
private long mTotalBytes;
private boolean mDirty;
+ /**
+ * Construct a {@link NetworkStatsCollection} object.
+ *
+ * @param bucketDuration duration of the buckets in this object, in milliseconds.
+ * @hide
+ */
public NetworkStatsCollection(long bucketDuration) {
mBucketDuration = bucketDuration;
reset();
}
+ /** @hide */
public void clear() {
reset();
}
+ /** @hide */
public void reset() {
mStats.clear();
mStartMillis = Long.MAX_VALUE;
@@ -117,6 +134,7 @@
mDirty = false;
}
+ /** @hide */
public long getStartMillis() {
return mStartMillis;
}
@@ -124,6 +142,7 @@
/**
* Return first atomic bucket in this collection, which is more conservative
* than {@link #mStartMillis}.
+ * @hide
*/
public long getFirstAtomicBucketMillis() {
if (mStartMillis == Long.MAX_VALUE) {
@@ -133,26 +152,32 @@
}
}
+ /** @hide */
public long getEndMillis() {
return mEndMillis;
}
+ /** @hide */
public long getTotalBytes() {
return mTotalBytes;
}
+ /** @hide */
public boolean isDirty() {
return mDirty;
}
+ /** @hide */
public void clearDirty() {
mDirty = false;
}
+ /** @hide */
public boolean isEmpty() {
return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
}
+ /** @hide */
@VisibleForTesting
public long roundUp(long time) {
if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
@@ -168,6 +193,7 @@
}
}
+ /** @hide */
@VisibleForTesting
public long roundDown(long time) {
if (time == Long.MIN_VALUE || time == Long.MAX_VALUE
@@ -182,10 +208,12 @@
}
}
+ /** @hide */
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel) {
return getRelevantUids(accessLevel, Binder.getCallingUid());
}
+ /** @hide */
public int[] getRelevantUids(@NetworkStatsAccess.Level int accessLevel,
final int callerUid) {
final ArrayList<Integer> uids = new ArrayList<>();
@@ -206,6 +234,7 @@
/**
* Combine all {@link NetworkStatsHistory} in this collection which match
* the requested parameters.
+ * @hide
*/
public NetworkStatsHistory getHistory(NetworkTemplate template, SubscriptionPlan augmentPlan,
int uid, int set, int tag, int fields, long start, long end,
@@ -331,6 +360,7 @@
* @param end - end of the range, timestamp in milliseconds since the epoch.
* @param accessLevel - caller access level.
* @param callerUid - caller UID.
+ * @hide
*/
public NetworkStats getSummary(NetworkTemplate template, long start, long end,
@NetworkStatsAccess.Level int accessLevel, int callerUid) {
@@ -377,6 +407,7 @@
/**
* Record given {@link android.net.NetworkStats.Entry} into this collection.
+ * @hide
*/
public void recordData(NetworkIdentitySet ident, int uid, int set, int tag, long start,
long end, NetworkStats.Entry entry) {
@@ -387,8 +418,12 @@
/**
* Record given {@link NetworkStatsHistory} into this collection.
+ *
+ * @hide
*/
- private void recordHistory(Key key, NetworkStatsHistory history) {
+ public void recordHistory(@NonNull Key key, @NonNull NetworkStatsHistory history) {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(history);
if (history.size() == 0) return;
noteRecordedHistory(history.getStart(), history.getEnd(), history.getTotalBytes());
@@ -403,8 +438,11 @@
/**
* Record all {@link NetworkStatsHistory} contained in the given collection
* into this collection.
+ *
+ * @hide
*/
- public void recordCollection(NetworkStatsCollection another) {
+ public void recordCollection(@NonNull NetworkStatsCollection another) {
+ Objects.requireNonNull(another);
for (int i = 0; i < another.mStats.size(); i++) {
final Key key = another.mStats.keyAt(i);
final NetworkStatsHistory value = another.mStats.valueAt(i);
@@ -433,6 +471,7 @@
}
}
+ /** @hide */
@Override
public void read(InputStream in) throws IOException {
read((DataInput) new DataInputStream(in));
@@ -472,6 +511,7 @@
}
}
+ /** @hide */
@Override
public void write(OutputStream out) throws IOException {
write((DataOutput) new DataOutputStream(out));
@@ -514,6 +554,7 @@
* See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
*
* @deprecated
+ * @hide
*/
@Deprecated
public void readLegacyNetwork(File file) throws IOException {
@@ -559,6 +600,7 @@
* See {@code NetworkStatsService#maybeUpgradeLegacyStatsLocked}.
*
* @deprecated
+ * @hide
*/
@Deprecated
public void readLegacyUid(File file, boolean onlyTags) throws IOException {
@@ -629,6 +671,7 @@
* Remove any {@link NetworkStatsHistory} attributed to the requested UID,
* moving any {@link NetworkStats#TAG_NONE} series to
* {@link TrafficStats#UID_REMOVED}.
+ * @hide
*/
public void removeUids(int[] uids) {
final ArrayList<Key> knownKeys = new ArrayList<>();
@@ -665,10 +708,11 @@
private ArrayList<Key> getSortedKeys() {
final ArrayList<Key> keys = new ArrayList<>();
keys.addAll(mStats.keySet());
- Collections.sort(keys);
+ Collections.sort(keys, (left, right) -> Key.compare(left, right));
return keys;
}
+ /** @hide */
public void dump(IndentingPrintWriter pw) {
for (Key key : getSortedKeys()) {
pw.print("ident="); pw.print(key.ident.toString());
@@ -683,6 +727,7 @@
}
}
+ /** @hide */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
@@ -706,6 +751,7 @@
proto.end(start);
}
+ /** @hide */
public void dumpCheckin(PrintWriter pw, long start, long end) {
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell");
dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi");
@@ -768,16 +814,102 @@
return false;
}
- private static class Key implements Comparable<Key> {
+ /**
+ * Get the all historical stats of the collection {@link NetworkStatsCollection}.
+ *
+ * @return All {@link NetworkStatsHistory} in this collection.
+ */
+ @NonNull
+ public Map<Key, NetworkStatsHistory> getEntries() {
+ return new ArrayMap(mStats);
+ }
+
+ /**
+ * Builder class for {@link NetworkStatsCollection}.
+ */
+ public static final class Builder {
+ private final long mBucketDuration;
+ private final ArrayMap<Key, NetworkStatsHistory> mEntries = new ArrayMap<>();
+
+ /**
+ * Creates a new Builder with given bucket duration.
+ *
+ * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+ */
+ public Builder(long bucketDuration) {
+ mBucketDuration = bucketDuration;
+ }
+
+ /**
+ * Add association of the history with the specified key in this map.
+ *
+ * @param key The object used to identify a network, see {@link Key}.
+ * @param history {@link NetworkStatsHistory} instance associated to the given {@link Key}.
+ * @return The builder object.
+ */
+ @NonNull
+ public NetworkStatsCollection.Builder addEntry(@NonNull Key key,
+ @NonNull NetworkStatsHistory history) {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(history);
+ final List<Entry> historyEntries = history.getEntries();
+
+ final NetworkStatsHistory.Builder historyBuilder =
+ new NetworkStatsHistory.Builder(mBucketDuration, historyEntries.size());
+ for (Entry entry : historyEntries) {
+ historyBuilder.addEntry(entry);
+ }
+
+ mEntries.put(key, historyBuilder.build());
+ return this;
+ }
+
+ /**
+ * Builds the instance of the {@link NetworkStatsCollection}.
+ *
+ * @return the built instance of {@link NetworkStatsCollection}.
+ */
+ @NonNull
+ public NetworkStatsCollection build() {
+ final NetworkStatsCollection collection = new NetworkStatsCollection(mBucketDuration);
+ for (int i = 0; i < mEntries.size(); i++) {
+ collection.recordHistory(mEntries.keyAt(i), mEntries.valueAt(i));
+ }
+ return collection;
+ }
+ }
+
+ /**
+ * the identifier that associate with the {@link NetworkStatsHistory} object to identify
+ * a certain record in the {@link NetworkStatsCollection} object.
+ */
+ public static class Key {
+ /** @hide */
public final NetworkIdentitySet ident;
+ /** @hide */
public final int uid;
+ /** @hide */
public final int set;
+ /** @hide */
public final int tag;
private final int mHashCode;
- Key(NetworkIdentitySet ident, int uid, int set, int tag) {
- this.ident = ident;
+ /**
+ * Construct a {@link Key} object.
+ *
+ * @param ident a Set of {@link NetworkIdentity} that associated with the record.
+ * @param uid Uid of the record.
+ * @param set Set of the record, see {@code NetworkStats#SET_*}.
+ * @param tag Tag of the record, see {@link TrafficStats#setThreadStatsTag(int)}.
+ */
+ public Key(@NonNull Set<NetworkIdentity> ident, int uid, int set, int tag) {
+ this(new NetworkIdentitySet(Objects.requireNonNull(ident)), uid, set, tag);
+ }
+
+ /** @hide */
+ public Key(@NonNull NetworkIdentitySet ident, int uid, int set, int tag) {
+ this.ident = Objects.requireNonNull(ident);
this.uid = uid;
this.set = set;
this.tag = tag;
@@ -790,7 +922,7 @@
}
@Override
- public boolean equals(Object obj) {
+ public boolean equals(@Nullable Object obj) {
if (obj instanceof Key) {
final Key key = (Key) obj;
return uid == key.uid && set == key.set && tag == key.tag
@@ -799,20 +931,22 @@
return false;
}
- @Override
- public int compareTo(Key another) {
+ /** @hide */
+ public static int compare(@NonNull Key left, @NonNull Key right) {
+ Objects.requireNonNull(left);
+ Objects.requireNonNull(right);
int res = 0;
- if (ident != null && another.ident != null) {
- res = ident.compareTo(another.ident);
+ if (left.ident != null && right.ident != null) {
+ res = NetworkIdentitySet.compare(left.ident, right.ident);
}
if (res == 0) {
- res = Integer.compare(uid, another.uid);
+ res = Integer.compare(left.uid, right.uid);
}
if (res == 0) {
- res = Integer.compare(set, another.set);
+ res = Integer.compare(left.set, right.set);
}
if (res == 0) {
- res = Integer.compare(tag, another.tag);
+ res = Integer.compare(left.tag, right.tag);
}
return res;
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
index 428bc6d..78c1370 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkStatsHistory.java
@@ -16,6 +16,7 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
@@ -30,6 +31,8 @@
import static com.android.net.module.util.NetworkStatsUtils.multiplySafeByRational;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Parcel;
@@ -50,7 +53,9 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ProtocolException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.Random;
/**
@@ -64,18 +69,25 @@
*
* @hide
*/
-public class NetworkStatsHistory implements Parcelable {
+@SystemApi(client = MODULE_LIBRARIES)
+public final class NetworkStatsHistory implements Parcelable {
private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_PACKETS = 2;
private static final int VERSION_ADD_ACTIVE = 3;
+ /** @hide */
public static final int FIELD_ACTIVE_TIME = 0x01;
+ /** @hide */
public static final int FIELD_RX_BYTES = 0x02;
+ /** @hide */
public static final int FIELD_RX_PACKETS = 0x04;
+ /** @hide */
public static final int FIELD_TX_BYTES = 0x08;
+ /** @hide */
public static final int FIELD_TX_PACKETS = 0x10;
+ /** @hide */
public static final int FIELD_OPERATIONS = 0x20;
-
+ /** @hide */
public static final int FIELD_ALL = 0xFFFFFFFF;
private long bucketDuration;
@@ -89,34 +101,171 @@
private long[] operations;
private long totalBytes;
- public static class Entry {
- public static final long UNKNOWN = -1;
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long bucketDuration;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long bucketStart;
- public long activeTime;
- @UnsupportedAppUsage
- public long rxBytes;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long rxPackets;
- @UnsupportedAppUsage
- public long txBytes;
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public long txPackets;
- public long operations;
+ /** @hide */
+ public NetworkStatsHistory(long bucketDuration, long[] bucketStart, long[] activeTime,
+ long[] rxBytes, long[] rxPackets, long[] txBytes, long[] txPackets,
+ long[] operations, int bucketCount, long totalBytes) {
+ this.bucketDuration = bucketDuration;
+ this.bucketStart = bucketStart;
+ this.activeTime = activeTime;
+ this.rxBytes = rxBytes;
+ this.rxPackets = rxPackets;
+ this.txBytes = txBytes;
+ this.txPackets = txPackets;
+ this.operations = operations;
+ this.bucketCount = bucketCount;
+ this.totalBytes = totalBytes;
}
+ /**
+ * An instance to represent a single record in a {@link NetworkStatsHistory} object.
+ */
+ public static final class Entry {
+ /** @hide */
+ public static final long UNKNOWN = -1;
+
+ /** @hide */
+ // TODO: Migrate all callers to get duration from the history object and remove this field.
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long bucketDuration;
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long bucketStart;
+ /** @hide */
+ public long activeTime;
+ /** @hide */
+ @UnsupportedAppUsage
+ public long rxBytes;
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long rxPackets;
+ /** @hide */
+ @UnsupportedAppUsage
+ public long txBytes;
+ /** @hide */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public long txPackets;
+ /** @hide */
+ public long operations;
+ /** @hide */
+ Entry() {}
+
+ /**
+ * Construct a {@link Entry} instance to represent a single record in a
+ * {@link NetworkStatsHistory} object.
+ *
+ * @param bucketStart Start of period for this {@link Entry}, in milliseconds since the
+ * Unix epoch, see {@link java.lang.System#currentTimeMillis}.
+ * @param activeTime Active time for this {@link Entry}, in milliseconds.
+ * @param rxBytes Number of bytes received for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param rxPackets Number of packets received for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param txBytes Number of bytes transmitted for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param txPackets Number of bytes transmitted for this {@link Entry}. Statistics should
+ * represent the contents of IP packets, including IP headers.
+ * @param operations count of network operations performed for this {@link Entry}. This can
+ * be used to derive bytes-per-operation.
+ */
+ public Entry(long bucketStart, long activeTime, long rxBytes,
+ long rxPackets, long txBytes, long txPackets, long operations) {
+ this.bucketStart = bucketStart;
+ this.activeTime = activeTime;
+ this.rxBytes = rxBytes;
+ this.rxPackets = rxPackets;
+ this.txBytes = txBytes;
+ this.txPackets = txPackets;
+ this.operations = operations;
+ }
+
+ /**
+ * Get start timestamp of the bucket's time interval, in milliseconds since the Unix epoch.
+ */
+ public long getBucketStart() {
+ return bucketStart;
+ }
+
+ /**
+ * Get active time of the bucket's time interval, in milliseconds.
+ */
+ public long getActiveTime() {
+ return activeTime;
+ }
+
+ /** Get number of bytes received for this {@link Entry}. */
+ public long getRxBytes() {
+ return rxBytes;
+ }
+
+ /** Get number of packets received for this {@link Entry}. */
+ public long getRxPackets() {
+ return rxPackets;
+ }
+
+ /** Get number of bytes transmitted for this {@link Entry}. */
+ public long getTxBytes() {
+ return txBytes;
+ }
+
+ /** Get number of packets transmitted for this {@link Entry}. */
+ public long getTxPackets() {
+ return txPackets;
+ }
+
+ /** Get count of network operations performed for this {@link Entry}. */
+ public long getOperations() {
+ return operations;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o.getClass() != getClass()) return false;
+ Entry entry = (Entry) o;
+ return bucketStart == entry.bucketStart
+ && activeTime == entry.activeTime && rxBytes == entry.rxBytes
+ && rxPackets == entry.rxPackets && txBytes == entry.txBytes
+ && txPackets == entry.txPackets && operations == entry.operations;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (bucketStart * 2
+ + activeTime * 3
+ + rxBytes * 5
+ + rxPackets * 7
+ + txBytes * 11
+ + txPackets * 13
+ + operations * 17);
+ }
+
+ @Override
+ public String toString() {
+ return "Entry{"
+ + "bucketStart=" + bucketStart
+ + ", activeTime=" + activeTime
+ + ", rxBytes=" + rxBytes
+ + ", rxPackets=" + rxPackets
+ + ", txBytes=" + txBytes
+ + ", txPackets=" + txPackets
+ + ", operations=" + operations
+ + "}";
+ }
+ }
+
+ /** @hide */
@UnsupportedAppUsage
public NetworkStatsHistory(long bucketDuration) {
this(bucketDuration, 10, FIELD_ALL);
}
+ /** @hide */
public NetworkStatsHistory(long bucketDuration, int initialSize) {
this(bucketDuration, initialSize, FIELD_ALL);
}
+ /** @hide */
public NetworkStatsHistory(long bucketDuration, int initialSize, int fields) {
this.bucketDuration = bucketDuration;
bucketStart = new long[initialSize];
@@ -130,11 +279,13 @@
totalBytes = 0;
}
+ /** @hide */
public NetworkStatsHistory(NetworkStatsHistory existing, long bucketDuration) {
this(bucketDuration, existing.estimateResizeBuckets(bucketDuration));
recordEntireHistory(existing);
}
+ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
@@ -150,7 +301,7 @@
}
@Override
- public void writeToParcel(Parcel out, int flags) {
+ public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
writeLongArray(out, activeTime, bucketCount);
@@ -162,6 +313,7 @@
out.writeLong(totalBytes);
}
+ /** @hide */
public NetworkStatsHistory(DataInput in) throws IOException {
final int version = in.readInt();
switch (version) {
@@ -204,6 +356,7 @@
}
}
+ /** @hide */
public void writeToStream(DataOutput out) throws IOException {
out.writeInt(VERSION_ADD_ACTIVE);
out.writeLong(bucketDuration);
@@ -221,15 +374,18 @@
return 0;
}
+ /** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int size() {
return bucketCount;
}
+ /** @hide */
public long getBucketDuration() {
return bucketDuration;
}
+ /** @hide */
@UnsupportedAppUsage
public long getStart() {
if (bucketCount > 0) {
@@ -239,6 +395,7 @@
}
}
+ /** @hide */
@UnsupportedAppUsage
public long getEnd() {
if (bucketCount > 0) {
@@ -250,6 +407,7 @@
/**
* Return total bytes represented by this history.
+ * @hide
*/
public long getTotalBytes() {
return totalBytes;
@@ -258,6 +416,7 @@
/**
* Return index of bucket that contains or is immediately before the
* requested time.
+ * @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int getIndexBefore(long time) {
@@ -273,6 +432,7 @@
/**
* Return index of bucket that contains or is immediately after the
* requested time.
+ * @hide
*/
public int getIndexAfter(long time) {
int index = Arrays.binarySearch(bucketStart, 0, bucketCount, time);
@@ -286,6 +446,7 @@
/**
* Return specific stats entry.
+ * @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public Entry getValues(int i, Entry recycle) {
@@ -301,6 +462,23 @@
return entry;
}
+ /**
+ * Get List of {@link Entry} of the {@link NetworkStatsHistory} instance.
+ *
+ * @return
+ */
+ @NonNull
+ public List<Entry> getEntries() {
+ // TODO: Return a wrapper that uses this list instead, to prevent the returned result
+ // from being changed.
+ final ArrayList<Entry> ret = new ArrayList<>(size());
+ for (int i = 0; i < size(); i++) {
+ ret.add(getValues(i, null /* recycle */));
+ }
+ return ret;
+ }
+
+ /** @hide */
public void setValues(int i, Entry entry) {
// Unwind old values
if (rxBytes != null) totalBytes -= rxBytes[i];
@@ -322,6 +500,7 @@
/**
* Record that data traffic occurred in the given time range. Will
* distribute across internal buckets, creating new buckets as needed.
+ * @hide
*/
@Deprecated
public void recordData(long start, long end, long rxBytes, long txBytes) {
@@ -332,6 +511,7 @@
/**
* Record that data traffic occurred in the given time range. Will
* distribute across internal buckets, creating new buckets as needed.
+ * @hide
*/
public void recordData(long start, long end, NetworkStats.Entry entry) {
long rxBytes = entry.rxBytes;
@@ -392,6 +572,7 @@
/**
* Record an entire {@link NetworkStatsHistory} into this history. Usually
* for combining together stats for external reporting.
+ * @hide
*/
@UnsupportedAppUsage
public void recordEntireHistory(NetworkStatsHistory input) {
@@ -402,6 +583,7 @@
* Record given {@link NetworkStatsHistory} into this history, copying only
* buckets that atomically occur in the inclusive time range. Doesn't
* interpolate across partial buckets.
+ * @hide
*/
public void recordHistory(NetworkStatsHistory input, long start, long end) {
final NetworkStats.Entry entry = new NetworkStats.Entry(
@@ -483,6 +665,7 @@
/**
* Clear all data stored in this object.
+ * @hide
*/
public void clear() {
bucketStart = EmptyArray.LONG;
@@ -498,9 +681,10 @@
/**
* Remove buckets older than requested cutoff.
+ * @hide
*/
- @Deprecated
public void removeBucketsBefore(long cutoff) {
+ // TODO: Consider use getIndexBefore.
int i;
for (i = 0; i < bucketCount; i++) {
final long curStart = bucketStart[i];
@@ -522,7 +706,9 @@
if (operations != null) operations = Arrays.copyOfRange(operations, i, length);
bucketCount -= i;
- // TODO: subtract removed values from totalBytes
+ totalBytes = 0;
+ if (rxBytes != null) totalBytes += CollectionUtils.total(rxBytes);
+ if (txBytes != null) totalBytes += CollectionUtils.total(txBytes);
}
}
@@ -536,6 +722,7 @@
* @param start - start of the range, timestamp in milliseconds since the epoch.
* @param end - end of the range, timestamp in milliseconds since the epoch.
* @param recycle - entry instance for performance, could be null.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getValues(long start, long end, Entry recycle) {
@@ -550,6 +737,7 @@
* @param end - end of the range, timestamp in milliseconds since the epoch.
* @param now - current timestamp in milliseconds since the epoch (wall clock).
* @param recycle - entry instance for performance, could be null.
+ * @hide
*/
@UnsupportedAppUsage
public Entry getValues(long start, long end, long now, Entry recycle) {
@@ -613,6 +801,7 @@
/**
* @deprecated only for temporary testing
+ * @hide
*/
@Deprecated
public void generateRandom(long start, long end, long bytes) {
@@ -631,6 +820,7 @@
/**
* @deprecated only for temporary testing
+ * @hide
*/
@Deprecated
public void generateRandom(long start, long end, long rxBytes, long rxPackets, long txBytes,
@@ -660,12 +850,14 @@
}
}
+ /** @hide */
public static long randomLong(Random r, long start, long end) {
return (long) (start + (r.nextFloat() * (end - start)));
}
/**
* Quickly determine if this history intersects with given window.
+ * @hide
*/
public boolean intersects(long start, long end) {
final long dataStart = getStart();
@@ -677,6 +869,7 @@
return false;
}
+ /** @hide */
public void dump(IndentingPrintWriter pw, boolean fullHistory) {
pw.print("NetworkStatsHistory: bucketDuration=");
pw.println(bucketDuration / SECOND_IN_MILLIS);
@@ -700,6 +893,7 @@
pw.decreaseIndent();
}
+ /** @hide */
public void dumpCheckin(PrintWriter pw) {
pw.print("d,");
pw.print(bucketDuration / SECOND_IN_MILLIS);
@@ -717,6 +911,7 @@
}
}
+ /** @hide */
public void dumpDebug(ProtoOutputStream proto, long tag) {
final long start = proto.start(tag);
@@ -776,6 +971,7 @@
if (array != null) array[i] += value;
}
+ /** @hide */
public int estimateResizeBuckets(long newBucketDuration) {
return (int) (size() * getBucketDuration() / newBucketDuration);
}
@@ -783,6 +979,7 @@
/**
* Utility methods for interacting with {@link DataInputStream} and
* {@link DataOutputStream}, mostly dealing with writing partial arrays.
+ * @hide
*/
public static class DataStreamUtils {
@Deprecated
@@ -857,6 +1054,7 @@
/**
* Utility methods for interacting with {@link Parcel} structures, mostly
* dealing with writing partial arrays.
+ * @hide
*/
public static class ParcelUtils {
public static long[] readLongArray(Parcel in) {
@@ -884,4 +1082,80 @@
}
}
+ /**
+ * Builder class for {@link NetworkStatsHistory}.
+ */
+ public static final class Builder {
+ private final long mBucketDuration;
+ private final List<Long> mBucketStart;
+ private final List<Long> mActiveTime;
+ private final List<Long> mRxBytes;
+ private final List<Long> mRxPackets;
+ private final List<Long> mTxBytes;
+ private final List<Long> mTxPackets;
+ private final List<Long> mOperations;
+
+ /**
+ * Creates a new Builder with given bucket duration and initial capacity to construct
+ * {@link NetworkStatsHistory} objects.
+ *
+ * @param bucketDuration Duration of the buckets of the object, in milliseconds.
+ * @param initialCapacity Estimated number of records.
+ */
+ public Builder(long bucketDuration, int initialCapacity) {
+ mBucketDuration = bucketDuration;
+ mBucketStart = new ArrayList<>(initialCapacity);
+ mActiveTime = new ArrayList<>(initialCapacity);
+ mRxBytes = new ArrayList<>(initialCapacity);
+ mRxPackets = new ArrayList<>(initialCapacity);
+ mTxBytes = new ArrayList<>(initialCapacity);
+ mTxPackets = new ArrayList<>(initialCapacity);
+ mOperations = new ArrayList<>(initialCapacity);
+ }
+
+ /**
+ * Add an {@link Entry} into the {@link NetworkStatsHistory} instance.
+ *
+ * @param entry The target {@link Entry} object.
+ * @return The builder object.
+ */
+ @NonNull
+ public Builder addEntry(@NonNull Entry entry) {
+ mBucketStart.add(entry.bucketStart);
+ mActiveTime.add(entry.activeTime);
+ mRxBytes.add(entry.rxBytes);
+ mRxPackets.add(entry.rxPackets);
+ mTxBytes.add(entry.txBytes);
+ mTxPackets.add(entry.txPackets);
+ mOperations.add(entry.operations);
+ return this;
+ }
+
+ private static long sum(@NonNull List<Long> list) {
+ long sum = 0;
+ for (long entry : list) {
+ sum += entry;
+ }
+ return sum;
+ }
+
+ /**
+ * Builds the instance of the {@link NetworkStatsHistory}.
+ *
+ * @return the built instance of {@link NetworkStatsHistory}.
+ */
+ @NonNull
+ public NetworkStatsHistory build() {
+ return new NetworkStatsHistory(mBucketDuration,
+ CollectionUtils.toLongArray(mBucketStart),
+ CollectionUtils.toLongArray(mActiveTime),
+ CollectionUtils.toLongArray(mRxBytes),
+ CollectionUtils.toLongArray(mRxPackets),
+ CollectionUtils.toLongArray(mTxBytes),
+ CollectionUtils.toLongArray(mTxPackets),
+ CollectionUtils.toLongArray(mOperations),
+ mBucketStart.size(),
+ sum(mRxBytes) + sum(mTxBytes));
+ }
+ }
}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
index e9084b0..9b58b01 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/NetworkTemplate.java
@@ -41,13 +41,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.app.usage.NetworkStatsManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.wifi.WifiInfo;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
-import android.telephony.Annotation.NetworkType;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArraySet;
@@ -58,9 +57,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Comparator;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -136,15 +133,6 @@
* {@code TelephonyManager.NETWORK_TYPE_*} constants, and thus needs to stay in sync.
*/
public static final int NETWORK_TYPE_ALL = -1;
- /**
- * Virtual RAT type to represent 5G NSA (Non Stand Alone) mode, where the primary cell is
- * still LTE and network allocates a secondary 5G cell so telephony reports RAT = LTE along
- * with NR state as connected. This should not be overlapped with any of the
- * {@code TelephonyManager.NETWORK_TYPE_*} constants.
- *
- * @hide
- */
- public static final int NETWORK_TYPE_5G_NSA = -2;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -214,7 +202,7 @@
* @hide
*/
public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
- @NetworkType int ratType, int metered) {
+ int ratType, int metered) {
if (TextUtils.isEmpty(subscriberId)) {
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null /* subscriberId */,
null /* matchSubscriberIds */,
@@ -263,7 +251,7 @@
* Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
* given key of the wifi network.
*
- * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
* to know details about the key.
* @hide
*/
@@ -283,7 +271,7 @@
* Call with {@link #WIFI_NETWORK_KEY_ALL} for {@code wifiNetworkKey} to get result regardless
* of key of the wifi network.
*
- * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
* to know details about the key.
* @param subscriberId the IMSI associated to this wifi network.
*
@@ -364,7 +352,7 @@
private final int mMetered;
private final int mRoaming;
private final int mDefaultNetwork;
- private final int mSubType;
+ private final int mRatType;
/**
* The subscriber Id match rule defines how the template should match networks with
* specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
@@ -413,18 +401,18 @@
/** @hide */
// TODO: Remove it after updating all of the caller.
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
- String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int subType,
+ String wifiNetworkKey, int metered, int roaming, int defaultNetwork, int ratType,
int oemManaged) {
this(matchRule, subscriberId, matchSubscriberIds,
wifiNetworkKey != null ? new String[] { wifiNetworkKey } : new String[0],
- metered, roaming, defaultNetwork, subType, oemManaged,
+ metered, roaming, defaultNetwork, ratType, oemManaged,
NetworkStatsUtils.SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
/** @hide */
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String[] matchWifiNetworkKeys, int metered, int roaming,
- int defaultNetwork, int subType, int oemManaged, int subscriberIdMatchRule) {
+ int defaultNetwork, int ratType, int oemManaged, int subscriberIdMatchRule) {
Objects.requireNonNull(matchWifiNetworkKeys);
mMatchRule = matchRule;
mSubscriberId = subscriberId;
@@ -435,7 +423,7 @@
mMetered = metered;
mRoaming = roaming;
mDefaultNetwork = defaultNetwork;
- mSubType = subType;
+ mRatType = ratType;
mOemManaged = oemManaged;
mSubscriberIdMatchRule = subscriberIdMatchRule;
checkValidSubscriberIdMatchRule(matchRule, subscriberIdMatchRule);
@@ -453,7 +441,7 @@
mMetered = in.readInt();
mRoaming = in.readInt();
mDefaultNetwork = in.readInt();
- mSubType = in.readInt();
+ mRatType = in.readInt();
mOemManaged = in.readInt();
mSubscriberIdMatchRule = in.readInt();
}
@@ -467,7 +455,7 @@
dest.writeInt(mMetered);
dest.writeInt(mRoaming);
dest.writeInt(mDefaultNetwork);
- dest.writeInt(mSubType);
+ dest.writeInt(mRatType);
dest.writeInt(mOemManaged);
dest.writeInt(mSubscriberIdMatchRule);
}
@@ -500,8 +488,8 @@
builder.append(", defaultNetwork=").append(NetworkStats.defaultNetworkToString(
mDefaultNetwork));
}
- if (mSubType != NETWORK_TYPE_ALL) {
- builder.append(", subType=").append(mSubType);
+ if (mRatType != NETWORK_TYPE_ALL) {
+ builder.append(", ratType=").append(mRatType);
}
if (mOemManaged != OEM_MANAGED_ALL) {
builder.append(", oemManaged=").append(getOemManagedNames(mOemManaged));
@@ -514,7 +502,7 @@
@Override
public int hashCode() {
return Objects.hash(mMatchRule, mSubscriberId, Arrays.hashCode(mMatchWifiNetworkKeys),
- mMetered, mRoaming, mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
+ mMetered, mRoaming, mDefaultNetwork, mRatType, mOemManaged, mSubscriberIdMatchRule);
}
@Override
@@ -526,7 +514,7 @@
&& mMetered == other.mMetered
&& mRoaming == other.mRoaming
&& mDefaultNetwork == other.mDefaultNetwork
- && mSubType == other.mSubType
+ && mRatType == other.mRatType
&& mOemManaged == other.mOemManaged
&& mSubscriberIdMatchRule == other.mSubscriberIdMatchRule
&& Arrays.equals(mMatchWifiNetworkKeys, other.mMatchWifiNetworkKeys);
@@ -593,7 +581,7 @@
/**
* Get the set of Wifi Network Keys of the template.
- * See {@link WifiInfo#getCurrentNetworkKey()}.
+ * See {@link WifiInfo#getNetworkKey()}.
*/
@NonNull
public Set<String> getWifiNetworkKeys() {
@@ -635,7 +623,7 @@
* Get the Radio Access Technology(RAT) type filter of the template.
*/
public int getRatType() {
- return mSubType;
+ return mRatType;
}
/**
@@ -652,7 +640,9 @@
*
* @hide
*/
- public boolean matches(NetworkIdentity ident) {
+ @SystemApi(client = MODULE_LIBRARIES)
+ public boolean matches(@NonNull NetworkIdentity ident) {
+ Objects.requireNonNull(ident);
if (!matchesMetered(ident)) return false;
if (!matchesRoaming(ident)) return false;
if (!matchesDefaultNetwork(ident)) return false;
@@ -708,8 +698,9 @@
}
private boolean matchesCollapsedRatType(NetworkIdentity ident) {
- return mSubType == NETWORK_TYPE_ALL
- || getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
+ return mRatType == NETWORK_TYPE_ALL
+ || NetworkStatsManager.getCollapsedRatType(mRatType)
+ == NetworkStatsManager.getCollapsedRatType(ident.mRatType);
}
/**
@@ -729,7 +720,7 @@
* Returns true when the key matches, or when {@code mMatchWifiNetworkKeys} is
* empty.
*
- * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getCurrentNetworkKey()}
+ * @param wifiNetworkKey key of the wifi network. see {@link WifiInfo#getNetworkKey()}
* to know details about the key.
*/
private boolean matchesWifiNetworkKey(@NonNull String wifiNetworkKey) {
@@ -753,91 +744,13 @@
}
/**
- * Get a Radio Access Technology(RAT) type that is representative of a group of RAT types.
- * The mapping is corresponding to {@code TelephonyManager#NETWORK_CLASS_BIT_MASK_*}.
- *
- * @param ratType An integer defined in {@code TelephonyManager#NETWORK_TYPE_*}.
- *
- * @hide
- */
- // TODO: 1. Consider move this to TelephonyManager if used by other modules.
- // 2. Consider make this configurable.
- // 3. Use TelephonyManager APIs when available.
- // TODO: @SystemApi when ready.
- public static int getCollapsedRatType(int ratType) {
- switch (ratType) {
- case TelephonyManager.NETWORK_TYPE_GPRS:
- case TelephonyManager.NETWORK_TYPE_GSM:
- case TelephonyManager.NETWORK_TYPE_EDGE:
- case TelephonyManager.NETWORK_TYPE_IDEN:
- case TelephonyManager.NETWORK_TYPE_CDMA:
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- return TelephonyManager.NETWORK_TYPE_GSM;
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- case TelephonyManager.NETWORK_TYPE_UMTS:
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
- return TelephonyManager.NETWORK_TYPE_UMTS;
- case TelephonyManager.NETWORK_TYPE_LTE:
- case TelephonyManager.NETWORK_TYPE_IWLAN:
- return TelephonyManager.NETWORK_TYPE_LTE;
- case TelephonyManager.NETWORK_TYPE_NR:
- return TelephonyManager.NETWORK_TYPE_NR;
- // Virtual RAT type for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
- case NetworkTemplate.NETWORK_TYPE_5G_NSA:
- return NetworkTemplate.NETWORK_TYPE_5G_NSA;
- default:
- return TelephonyManager.NETWORK_TYPE_UNKNOWN;
- }
- }
-
- /**
- * Return all supported collapsed RAT types that could be returned by
- * {@link #getCollapsedRatType(int)}.
- *
- * @hide
- */
- // TODO: @SystemApi when ready.
- @NonNull
- public static final int[] getAllCollapsedRatTypes() {
- final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
- final HashSet<Integer> collapsedRatTypes = new HashSet<>();
- for (final int ratType : ratTypes) {
- collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(ratType));
- }
- // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
- // it is not in TelephonyManager#NETWORK_TYPE_* constants.
- // See {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
- collapsedRatTypes.add(NetworkTemplate.getCollapsedRatType(NETWORK_TYPE_5G_NSA));
- // Ensure that unknown type is returned.
- collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
- return toIntArray(collapsedRatTypes);
- }
-
- @NonNull
- private static int[] toIntArray(@NonNull Collection<Integer> list) {
- final int[] array = new int[list.size()];
- int i = 0;
- for (final Integer item : list) {
- array[i++] = item;
- }
- return array;
- }
-
- /**
* Check if matches Wi-Fi network template.
*/
private boolean matchesWifi(NetworkIdentity ident) {
switch (ident.mType) {
case TYPE_WIFI:
return matchesSubscriberId(ident.mSubscriberId)
- && matchesWifiNetworkKey(ident.mNetworkId);
+ && matchesWifiNetworkKey(ident.mWifiNetworkKey);
default:
return false;
}
@@ -1059,9 +972,9 @@
* the intention of matching any Wifi Network Key.
*
* @param wifiNetworkKeys the list of Wifi Network Key,
- * see {@link WifiInfo#getCurrentNetworkKey()}.
+ * see {@link WifiInfo#getNetworkKey()}.
* Or an empty list to match all networks.
- * Note that {@code getCurrentNetworkKey()} might get null key
+ * Note that {@code getNetworkKey()} might get null key
* when wifi disconnects. However, the caller should never invoke
* this function with a null Wifi Network Key since such statistics
* never exists.
@@ -1125,7 +1038,7 @@
* @return this builder.
*/
@NonNull
- public Builder setRatType(@NetworkType int ratType) {
+ public Builder setRatType(int ratType) {
// Input will be validated with the match rule when building the template.
mRatType = ratType;
return this;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
index 1af32bf..bc836d8 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
@@ -16,8 +16,9 @@
package android.net;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -27,18 +28,14 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.media.MediaPlayer;
+import android.os.Binder;
import android.os.Build;
-import android.os.IBinder;
import android.os.RemoteException;
-
-import com.android.server.NetworkManagementSocketTagger;
-
-import dalvik.system.SocketTagger;
+import android.os.StrictMode;
+import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.net.DatagramSocket;
import java.net.Socket;
import java.net.SocketException;
@@ -56,6 +53,10 @@
* use {@link NetworkStatsManager} instead.
*/
public class TrafficStats {
+ static {
+ System.loadLibrary("framework-connectivity-tiramisu-jni");
+ }
+
private static final String TAG = TrafficStats.class.getSimpleName();
/**
* The return value to indicate that the device does not support the statistic.
@@ -177,25 +178,12 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 130143562)
private synchronized static INetworkStatsService getStatsService() {
if (sStatsService == null) {
- sStatsService = getStatsBinder();
+ throw new IllegalStateException("TrafficStats not initialized, uid="
+ + Binder.getCallingUid());
}
return sStatsService;
}
- @Nullable
- private static INetworkStatsService getStatsBinder() {
- try {
- final Method getServiceMethod = Class.forName("android.os.ServiceManager")
- .getDeclaredMethod("getService", new Class[]{String.class});
- final IBinder binder = (IBinder) getServiceMethod.invoke(
- null, Context.NETWORK_STATS_SERVICE);
- return INetworkStatsService.Stub.asInterface(binder);
- } catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException
- | InvocationTargetException e) {
- throw new NullPointerException("Cannot get INetworkStatsService: " + e);
- }
- }
-
/**
* Snapshot of {@link NetworkStats} when the currently active profiling
* session started, or {@code null} if no session active.
@@ -210,6 +198,104 @@
private static final String LOOPBACK_IFACE = "lo";
/**
+ * Initialization {@link TrafficStats} with the context, to
+ * allow {@link TrafficStats} to fetch the needed binder.
+ *
+ * @param context a long-lived context, such as the application context or system
+ * server context.
+ * @hide
+ */
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ @SuppressLint("VisiblySynchronized")
+ public static synchronized void init(@NonNull final Context context) {
+ if (sStatsService != null) {
+ throw new IllegalStateException("TrafficStats is already initialized, uid="
+ + Binder.getCallingUid());
+ }
+ final NetworkStatsManager statsManager =
+ context.getSystemService(NetworkStatsManager.class);
+ if (statsManager == null) {
+ // TODO: Currently Process.isSupplemental is not working yet, because it depends on
+ // process to run in a certain UID range, which is not true for now. Change this
+ // to Log.wtf once Process.isSupplemental is ready.
+ Log.e(TAG, "TrafficStats not initialized, uid=" + Binder.getCallingUid());
+ return;
+ }
+ sStatsService = statsManager.getBinder();
+ }
+
+ /**
+ * Attach the socket tagger implementation to the current process, to
+ * get notified when a socket's {@link FileDescriptor} is assigned to
+ * a thread. See {@link SocketTagger#set(SocketTagger)}.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void attachSocketTagger() {
+ dalvik.system.SocketTagger.set(new SocketTagger());
+ }
+
+ private static class SocketTagger extends dalvik.system.SocketTagger {
+
+ // TODO: set to false
+ private static final boolean LOGD = true;
+
+ SocketTagger() {
+ }
+
+ @Override
+ public void tag(FileDescriptor fd) throws SocketException {
+ final UidTag tagInfo = sThreadUidTag.get();
+ if (LOGD) {
+ Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
+ + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid);
+ }
+ if (tagInfo.tag == -1) {
+ StrictMode.noteUntaggedSocket();
+ }
+
+ if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+ final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid);
+ if (errno < 0) {
+ Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
+ + tagInfo.tag + ", "
+ + tagInfo.uid + ") failed with errno" + errno);
+ }
+ }
+
+ @Override
+ public void untag(FileDescriptor fd) throws SocketException {
+ if (LOGD) {
+ Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
+ }
+
+ final UidTag tagInfo = sThreadUidTag.get();
+ if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+
+ final int errno = native_untagSocketFd(fd);
+ if (errno < 0) {
+ Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
+ }
+ }
+ }
+
+ private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
+ private static native int native_untagSocketFd(FileDescriptor fd);
+
+ private static class UidTag {
+ public int tag = -1;
+ public int uid = -1;
+ }
+
+ private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() {
+ @Override
+ protected UidTag initialValue() {
+ return new UidTag();
+ }
+ };
+
+ /**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
* <p>
@@ -223,7 +309,7 @@
* @see #clearThreadStatsTag()
*/
public static void setThreadStatsTag(int tag) {
- NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ getAndSetThreadStatsTag(tag);
}
/**
@@ -241,7 +327,9 @@
* restore any existing values after a nested operation is finished
*/
public static int getAndSetThreadStatsTag(int tag) {
- return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ final int old = sThreadUidTag.get().tag;
+ sThreadUidTag.get().tag = tag;
+ return old;
}
/**
@@ -301,7 +389,7 @@
* @see #setThreadStatsTag(int)
*/
public static int getThreadStatsTag() {
- return NetworkManagementSocketTagger.getThreadSocketStatsTag();
+ return sThreadUidTag.get().tag;
}
/**
@@ -311,7 +399,7 @@
* @see #setThreadStatsTag(int)
*/
public static void clearThreadStatsTag() {
- NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
+ sThreadUidTag.get().tag = -1;
}
/**
@@ -331,7 +419,7 @@
*/
@SuppressLint("RequiresPermission")
public static void setThreadStatsUid(int uid) {
- NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
+ sThreadUidTag.get().uid = uid;
}
/**
@@ -342,7 +430,7 @@
* @see #setThreadStatsUid(int)
*/
public static int getThreadStatsUid() {
- return NetworkManagementSocketTagger.getThreadSocketStatsUid();
+ return sThreadUidTag.get().uid;
}
/**
@@ -369,7 +457,7 @@
*/
@SuppressLint("RequiresPermission")
public static void clearThreadStatsUid() {
- NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
+ setThreadStatsUid(-1);
}
/**
diff --git a/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
new file mode 100644
index 0000000..4e8a5b2
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/src/android/net/netstats/IUsageCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 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 android.net.netstats;
+
+import android.net.DataUsageRequest;
+
+/**
+ * Interface for NetworkStatsService to notify events to the callers of registerUsageCallback.
+ *
+ * @hide
+ */
+oneway interface IUsageCallback {
+ void onThresholdReached(in DataUsageRequest request);
+ void onCallbackReleased(in DataUsageRequest request);
+}
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
index 0f21e55..512fbce 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdManager.java
@@ -16,6 +16,9 @@
package android.net.nsd;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
@@ -23,15 +26,22 @@
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkRequest;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Objects;
@@ -278,9 +288,180 @@
private final SparseArray mListenerMap = new SparseArray();
private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
private final Object mMapLock = new Object();
+ // Map of listener key sent by client -> per-network discovery tracker
+ @GuardedBy("mPerNetworkDiscoveryMap")
+ private final ArrayMap<Integer, PerNetworkDiscoveryTracker>
+ mPerNetworkDiscoveryMap = new ArrayMap<>();
private final ServiceHandler mHandler;
+ private class PerNetworkDiscoveryTracker {
+ final String mServiceType;
+ final int mProtocolType;
+ final DiscoveryListener mBaseListener;
+ final ArrayMap<Network, DelegatingDiscoveryListener> mPerNetworkListeners =
+ new ArrayMap<>();
+
+ final NetworkCallback mNetworkCb = new NetworkCallback() {
+ @Override
+ public void onAvailable(@NonNull Network network) {
+ final DelegatingDiscoveryListener wrappedListener = new DelegatingDiscoveryListener(
+ network, mBaseListener);
+ mPerNetworkListeners.put(network, wrappedListener);
+ discoverServices(mServiceType, mProtocolType, network, wrappedListener);
+ }
+
+ @Override
+ public void onLost(@NonNull Network network) {
+ final DelegatingDiscoveryListener listener = mPerNetworkListeners.get(network);
+ if (listener == null) return;
+ listener.notifyAllServicesLost();
+ // Listener will be removed from map in discovery stopped callback
+ stopServiceDiscovery(listener);
+ }
+ };
+
+ // Accessed from mHandler
+ private boolean mStopRequested;
+
+ public void start(@NonNull NetworkRequest request) {
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ cm.registerNetworkCallback(request, mNetworkCb, mHandler);
+ mHandler.post(() -> mBaseListener.onDiscoveryStarted(mServiceType));
+ }
+
+ /**
+ * Stop discovery on all networks tracked by this class.
+ *
+ * This will request all underlying listeners to stop, and the last one to stop will call
+ * onDiscoveryStopped or onStopDiscoveryFailed.
+ *
+ * Must be called on the handler thread.
+ */
+ public void requestStop() {
+ mHandler.post(() -> {
+ mStopRequested = true;
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ cm.unregisterNetworkCallback(mNetworkCb);
+ if (mPerNetworkListeners.size() == 0) {
+ mBaseListener.onDiscoveryStopped(mServiceType);
+ return;
+ }
+ for (int i = 0; i < mPerNetworkListeners.size(); i++) {
+ final DelegatingDiscoveryListener listener = mPerNetworkListeners.valueAt(i);
+ stopServiceDiscovery(listener);
+ }
+ });
+ }
+
+ private PerNetworkDiscoveryTracker(String serviceType, int protocolType,
+ DiscoveryListener baseListener) {
+ mServiceType = serviceType;
+ mProtocolType = protocolType;
+ mBaseListener = baseListener;
+ }
+
+ /**
+ * Subset of NsdServiceInfo that is tracked to generate service lost notifications when a
+ * network is lost.
+ *
+ * Service lost notifications only contain service name, type and network, so only track
+ * that information (Network is known from the listener). This also implements
+ * equals/hashCode for usage in maps.
+ */
+ private class TrackedNsdInfo {
+ private final String mServiceName;
+ private final String mServiceType;
+ TrackedNsdInfo(NsdServiceInfo info) {
+ mServiceName = info.getServiceName();
+ mServiceType = info.getServiceType();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mServiceName, mServiceType);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TrackedNsdInfo)) return false;
+ final TrackedNsdInfo other = (TrackedNsdInfo) obj;
+ return Objects.equals(mServiceName, other.mServiceName)
+ && Objects.equals(mServiceType, other.mServiceType);
+ }
+ }
+
+ private class DelegatingDiscoveryListener implements DiscoveryListener {
+ private final Network mNetwork;
+ private final DiscoveryListener mWrapped;
+ private final ArraySet<TrackedNsdInfo> mFoundInfo = new ArraySet<>();
+
+ private DelegatingDiscoveryListener(Network network, DiscoveryListener listener) {
+ mNetwork = network;
+ mWrapped = listener;
+ }
+
+ void notifyAllServicesLost() {
+ for (int i = 0; i < mFoundInfo.size(); i++) {
+ final TrackedNsdInfo trackedInfo = mFoundInfo.valueAt(i);
+ final NsdServiceInfo serviceInfo = new NsdServiceInfo(
+ trackedInfo.mServiceName, trackedInfo.mServiceType);
+ serviceInfo.setNetwork(mNetwork);
+ mWrapped.onServiceLost(serviceInfo);
+ }
+ }
+
+ @Override
+ public void onStartDiscoveryFailed(String serviceType, int errorCode) {
+ // The delegated listener is used when NsdManager takes care of starting/stopping
+ // discovery on multiple networks. Failure to start on one network is not a global
+ // failure to be reported up, as other networks may succeed: just log.
+ Log.e(TAG, "Failed to start discovery for " + serviceType + " on " + mNetwork
+ + " with code " + errorCode);
+ mPerNetworkListeners.remove(mNetwork);
+ }
+
+ @Override
+ public void onDiscoveryStarted(String serviceType) {
+ // Wrapped listener was called upon registration, it is not called for discovery
+ // on each network
+ }
+
+ @Override
+ public void onStopDiscoveryFailed(String serviceType, int errorCode) {
+ Log.e(TAG, "Failed to stop discovery for " + serviceType + " on " + mNetwork
+ + " with code " + errorCode);
+ mPerNetworkListeners.remove(mNetwork);
+ if (mStopRequested && mPerNetworkListeners.size() == 0) {
+ // Do not report onStopDiscoveryFailed when some underlying listeners failed:
+ // this does not mean that all listeners did, and onStopDiscoveryFailed is not
+ // actionable anyway. Just report that discovery stopped.
+ mWrapped.onDiscoveryStopped(serviceType);
+ }
+ }
+
+ @Override
+ public void onDiscoveryStopped(String serviceType) {
+ mPerNetworkListeners.remove(mNetwork);
+ if (mStopRequested && mPerNetworkListeners.size() == 0) {
+ mWrapped.onDiscoveryStopped(serviceType);
+ }
+ }
+
+ @Override
+ public void onServiceFound(NsdServiceInfo serviceInfo) {
+ mFoundInfo.add(new TrackedNsdInfo(serviceInfo));
+ mWrapped.onServiceFound(serviceInfo);
+ }
+
+ @Override
+ public void onServiceLost(NsdServiceInfo serviceInfo) {
+ mFoundInfo.remove(new TrackedNsdInfo(serviceInfo));
+ mWrapped.onServiceLost(serviceInfo);
+ }
+ }
+ }
+
/**
* Create a new Nsd instance. Applications use
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
@@ -634,6 +815,14 @@
}
/**
+ * Same as {@link #discoverServices(String, int, Network, DiscoveryListener)} with a null
+ * {@link Network}.
+ */
+ public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
+ discoverServices(serviceType, protocolType, (Network) null, listener);
+ }
+
+ /**
* Initiate service discovery to browse for instances of a service type. Service discovery
* consumes network bandwidth and will continue until the application calls
* {@link #stopServiceDiscovery}.
@@ -657,11 +846,13 @@
* @param serviceType The service type being discovered. Examples include "_http._tcp" for
* http services or "_ipp._tcp" for printers
* @param protocolType The service discovery protocol
+ * @param network Network to discover services on, or null to discover on all available networks
* @param listener The listener notifies of a successful discovery and is used
* to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
* Cannot be null. Cannot be in use for an active service discovery.
*/
- public void discoverServices(String serviceType, int protocolType, DiscoveryListener listener) {
+ public void discoverServices(@NonNull String serviceType, int protocolType,
+ @Nullable Network network, @NonNull DiscoveryListener listener) {
if (TextUtils.isEmpty(serviceType)) {
throw new IllegalArgumentException("Service type cannot be empty");
}
@@ -669,6 +860,7 @@
NsdServiceInfo s = new NsdServiceInfo();
s.setServiceType(serviceType);
+ s.setNetwork(network);
int key = putListener(listener, s);
try {
@@ -679,6 +871,67 @@
}
/**
+ * Initiate service discovery to browse for instances of a service type. Service discovery
+ * consumes network bandwidth and will continue until the application calls
+ * {@link #stopServiceDiscovery}.
+ *
+ * <p> The function call immediately returns after sending a request to start service
+ * discovery to the framework. The application is notified of a success to initiate
+ * discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
+ * through {@link DiscoveryListener#onStartDiscoveryFailed}.
+ *
+ * <p> Upon successful start, application is notified when a service is found with
+ * {@link DiscoveryListener#onServiceFound} or when a service is lost with
+ * {@link DiscoveryListener#onServiceLost}.
+ *
+ * <p> Upon failure to start, service discovery is not active and application does
+ * not need to invoke {@link #stopServiceDiscovery}
+ *
+ * <p> The application should call {@link #stopServiceDiscovery} when discovery of this
+ * service type is no longer required, and/or whenever the application is paused or
+ * stopped.
+ *
+ * <p> During discovery, new networks may connect or existing networks may disconnect - for
+ * example if wifi is reconnected. When a service was found on a network that disconnects,
+ * {@link DiscoveryListener#onServiceLost} will be called. If a new network connects that
+ * matches the {@link NetworkRequest}, {@link DiscoveryListener#onServiceFound} will be called
+ * for services found on that network. Applications that do not want to track networks
+ * themselves are encouraged to use this method instead of other overloads of
+ * {@code discoverServices}, as they will receive proper notifications when a service becomes
+ * available or unavailable due to network changes.
+ *
+ * @param serviceType The service type being discovered. Examples include "_http._tcp" for
+ * http services or "_ipp._tcp" for printers
+ * @param protocolType The service discovery protocol
+ * @param networkRequest Request specifying networks that should be considered when discovering
+ * @param listener The listener notifies of a successful discovery and is used
+ * to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
+ * Cannot be null. Cannot be in use for an active service discovery.
+ */
+ @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
+ public void discoverServices(@NonNull String serviceType, int protocolType,
+ @NonNull NetworkRequest networkRequest, @NonNull DiscoveryListener listener) {
+ if (TextUtils.isEmpty(serviceType)) {
+ throw new IllegalArgumentException("Service type cannot be empty");
+ }
+ Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null");
+ checkProtocol(protocolType);
+
+ NsdServiceInfo s = new NsdServiceInfo();
+ s.setServiceType(serviceType);
+
+ final int baseListenerKey = putListener(listener, s);
+
+ final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker(
+ serviceType, protocolType, listener);
+
+ synchronized (mPerNetworkDiscoveryMap) {
+ mPerNetworkDiscoveryMap.put(baseListenerKey, discoveryInfo);
+ discoveryInfo.start(networkRequest);
+ }
+ }
+
+ /**
* Stop service discovery initiated with {@link #discoverServices}. An active service
* discovery is notified to the application with {@link DiscoveryListener#onDiscoveryStarted}
* and it stays active until the application invokes a stop service discovery. A successful
@@ -696,6 +949,14 @@
*/
public void stopServiceDiscovery(DiscoveryListener listener) {
int id = getListenerKey(listener);
+ // If this is a PerNetworkDiscovery request, handle it as such
+ synchronized (mPerNetworkDiscoveryMap) {
+ final PerNetworkDiscoveryTracker info = mPerNetworkDiscoveryMap.get(id);
+ if (info != null) {
+ info.requestStop();
+ return;
+ }
+ }
try {
mService.stopDiscovery(id);
} catch (RemoteException e) {
diff --git a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
index 0946499..8506db1 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/nsd/NsdServiceInfo.java
@@ -17,7 +17,9 @@
package android.net.nsd;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
+import android.net.Network;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -49,6 +51,9 @@
private int mPort;
+ @Nullable
+ private Network mNetwork;
+
public NsdServiceInfo() {
}
@@ -307,18 +312,37 @@
return txtRecord;
}
- public String toString() {
- StringBuffer sb = new StringBuffer();
+ /**
+ * Get the network where the service can be found.
+ *
+ * This is never null if this {@link NsdServiceInfo} was obtained from
+ * {@link NsdManager#discoverServices} or {@link NsdManager#resolveService}.
+ */
+ @Nullable
+ public Network getNetwork() {
+ return mNetwork;
+ }
+ /**
+ * Set the network where the service can be found.
+ * @param network The network, or null to search for, or to announce, the service on all
+ * connected networks.
+ */
+ public void setNetwork(@Nullable Network network) {
+ mNetwork = network;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
sb.append("name: ").append(mServiceName)
.append(", type: ").append(mServiceType)
.append(", host: ").append(mHost)
- .append(", port: ").append(mPort);
+ .append(", port: ").append(mPort)
+ .append(", network: ").append(mNetwork);
byte[] txtRecord = getTxtRecord();
- if (txtRecord != null) {
- sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
- }
+ sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
return sb.toString();
}
@@ -352,6 +376,8 @@
}
dest.writeString(key);
}
+
+ dest.writeParcelable(mNetwork, 0);
}
/** Implement the Parcelable interface */
@@ -381,6 +407,7 @@
}
info.mTxtRecord.put(in.readString(), valueArray);
}
+ info.mNetwork = in.readParcelable(null, Network.class);
return info;
}
diff --git a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java b/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
deleted file mode 100644
index 1eb52fb..0000000
--- a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2011 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;
-
-import android.os.StrictMode;
-import android.util.Log;
-
-import dalvik.system.SocketTagger;
-
-import java.io.FileDescriptor;
-import java.net.SocketException;
-
-/**
- * Assigns tags to sockets for traffic stats.
- * @hide
- */
-public final class NetworkManagementSocketTagger extends SocketTagger {
- private static final String TAG = "NetworkManagementSocketTagger";
- private static final boolean LOGD = false;
-
- private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
- @Override
- protected SocketTags initialValue() {
- return new SocketTags();
- }
- };
-
- public static void install() {
- SocketTagger.set(new NetworkManagementSocketTagger());
- }
-
- public static int setThreadSocketStatsTag(int tag) {
- final int old = threadSocketTags.get().statsTag;
- threadSocketTags.get().statsTag = tag;
- return old;
- }
-
- public static int getThreadSocketStatsTag() {
- return threadSocketTags.get().statsTag;
- }
-
- public static int setThreadSocketStatsUid(int uid) {
- final int old = threadSocketTags.get().statsUid;
- threadSocketTags.get().statsUid = uid;
- return old;
- }
-
- public static int getThreadSocketStatsUid() {
- return threadSocketTags.get().statsUid;
- }
-
- @Override
- public void tag(FileDescriptor fd) throws SocketException {
- final SocketTags options = threadSocketTags.get();
- if (LOGD) {
- Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
- + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
- }
- if (options.statsTag == -1) {
- StrictMode.noteUntaggedSocket();
- }
- // TODO: skip tagging when options would be no-op
- tagSocketFd(fd, options.statsTag, options.statsUid);
- }
-
- private void tagSocketFd(FileDescriptor fd, int tag, int uid) {
- if (tag == -1 && uid == -1) return;
-
- final int errno = native_tagSocketFd(fd, tag, uid);
- if (errno < 0) {
- Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
- + tag + ", "
- + uid + ") failed with errno" + errno);
- }
- }
-
- @Override
- public void untag(FileDescriptor fd) throws SocketException {
- if (LOGD) {
- Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
- }
- unTagSocketFd(fd);
- }
-
- private void unTagSocketFd(FileDescriptor fd) {
- final SocketTags options = threadSocketTags.get();
- if (options.statsTag == -1 && options.statsUid == -1) return;
-
- final int errno = native_untagSocketFd(fd);
- if (errno < 0) {
- Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
- }
- }
-
- public static class SocketTags {
- public int statsTag = -1;
- public int statsUid = -1;
- }
-
- public static void setKernelCounterSet(int uid, int counterSet) {
- final int errno = native_setCounterSet(counterSet, uid);
- if (errno < 0) {
- Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno "
- + errno);
- }
- }
-
- public static void resetKernelUidStats(int uid) {
- int errno = native_deleteTagData(0, uid);
- if (errno < 0) {
- Log.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
- }
- }
-
- /**
- * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
- * format like {@code 0x7fffffff00000000}.
- */
- public static int kernelToTag(String string) {
- int length = string.length();
- if (length > 10) {
- return Long.decode(string.substring(0, length - 8)).intValue();
- } else {
- return 0;
- }
- }
-
- private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
- private static native int native_untagSocketFd(FileDescriptor fd);
- private static native int native_setCounterSet(int uid, int counterSetNum);
- private static native int native_deleteTagData(int tag, int uid);
-}
diff --git a/packages/ConnectivityT/service/Android.bp b/packages/ConnectivityT/service/Android.bp
index 97dfb64..d05370f 100644
--- a/packages/ConnectivityT/service/Android.bp
+++ b/packages/ConnectivityT/service/Android.bp
@@ -26,6 +26,13 @@
srcs: [
"src/com/android/server/net/NetworkIdentity*.java",
"src/com/android/server/net/NetworkStats*.java",
+ "src/com/android/server/net/BpfInterfaceMapUpdater.java",
+ "src/com/android/server/net/InterfaceMapValue.java",
+ "src/com/android/server/net/CookieTagMapKey.java",
+ "src/com/android/server/net/CookieTagMapValue.java",
+ "src/com/android/server/net/StatsMapKey.java",
+ "src/com/android/server/net/StatsMapValue.java",
+ "src/com/android/server/net/UidStatsMapKey.java",
],
path: "src",
visibility: [
@@ -66,6 +73,7 @@
filegroup {
name: "services.connectivity-ethernet-sources",
srcs: [
+ "src/com/android/server/net/DelayedDiskWrite.java",
"src/com/android/server/net/IpConfigStore.java",
],
path: "src",
@@ -82,8 +90,43 @@
":services.connectivity-ethernet-sources",
":services.connectivity-ipsec-sources",
":services.connectivity-netstats-sources",
- ":services.connectivity-nsd-sources",
],
path: "src",
visibility: ["//frameworks/base/services/core"],
}
+
+filegroup {
+ name: "services.connectivity-tiramisu-updatable-sources",
+ srcs: [
+ ":services.connectivity-nsd-sources",
+ ],
+ path: "src",
+ visibility: [
+ "//packages/modules/Connectivity:__subpackages__",
+ ],
+}
+
+cc_library_shared {
+ name: "libcom_android_net_module_util_jni",
+ min_sdk_version: "30",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+ srcs: [
+ "jni/onload.cpp",
+ ],
+ stl: "libc++_static",
+ static_libs: [
+ "libnet_utils_device_common_bpfjni",
+ ],
+ shared_libs: [
+ "liblog",
+ "libnativehelper",
+ ],
+ apex_available: [
+ "//apex_available:platform",
+ ],
+}
diff --git a/packages/ConnectivityT/service/jni/onload.cpp b/packages/ConnectivityT/service/jni/onload.cpp
new file mode 100644
index 0000000..bca4697
--- /dev/null
+++ b/packages/ConnectivityT/service/jni/onload.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 <nativehelper/JNIHelp.h>
+#include <log/log.h>
+
+namespace android {
+
+int register_com_android_net_module_util_BpfMap(JNIEnv* env, char const* class_name);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_com_android_net_module_util_BpfMap(env,
+ "com/android/net/module/util/BpfMap") < 0) return JNI_ERR;
+
+ return JNI_VERSION_1_6;
+}
+
+};
+
diff --git a/packages/ConnectivityT/service/src/com/android/server/NsdService.java b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
index 497107d..ddf6d2c 100644
--- a/packages/ConnectivityT/service/src/com/android/server/NsdService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/NsdService.java
@@ -19,6 +19,9 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.Network;
import android.net.nsd.INsdManager;
import android.net.nsd.INsdManagerCallback;
import android.net.nsd.INsdServiceConnector;
@@ -44,6 +47,9 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
@@ -60,6 +66,7 @@
private static final boolean DBG = true;
private static final long CLEANUP_DELAY_MS = 10000;
+ private static final int IFACE_IDX_ANY = 0;
private final Context mContext;
private final NsdStateMachine mNsdStateMachine;
@@ -297,7 +304,7 @@
maybeStartDaemon();
id = getUniqueId();
- if (discoverServices(id, args.serviceInfo.getServiceType())) {
+ if (discoverServices(id, args.serviceInfo)) {
if (DBG) {
Log.d(TAG, "Discover " + msg.arg2 + " " + id
+ args.serviceInfo.getServiceType());
@@ -430,13 +437,38 @@
}
switch (code) {
case NativeResponseCode.SERVICE_FOUND:
- /* NNN uniqueId serviceName regType domain */
+ /* NNN uniqueId serviceName regType domain interfaceIdx netId */
servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
+ final int foundNetId;
+ try {
+ foundNetId = Integer.parseInt(cooked[6]);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
+ break;
+ }
+ if (foundNetId == 0L) {
+ // Ignore services that do not have a Network: they are not usable
+ // by apps, as they would need privileged permissions to use
+ // interfaces that do not have an associated Network.
+ break;
+ }
+ servInfo.setNetwork(new Network(foundNetId));
clientInfo.onServiceFound(clientId, servInfo);
break;
case NativeResponseCode.SERVICE_LOST:
- /* NNN uniqueId serviceName regType domain */
+ /* NNN uniqueId serviceName regType domain interfaceIdx netId */
+ final int lostNetId;
+ try {
+ lostNetId = Integer.parseInt(cooked[6]);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Invalid network received from mdnsd: " + cooked[6]);
+ break;
+ }
servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
+ // The network could be null if it was torn down when the service is lost
+ // TODO: avoid returning null in that case, possibly by remembering found
+ // services on the same interface index and their network at the time
+ servInfo.setNetwork(lostNetId == 0 ? null : new Network(lostNetId));
clientInfo.onServiceLost(clientId, servInfo);
break;
case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
@@ -461,7 +493,7 @@
/* NNN regId errorCode */
break;
case NativeResponseCode.SERVICE_RESOLVED:
- /* NNN resolveId fullName hostName port txtlen txtdata */
+ /* NNN resolveId fullName hostName port txtlen txtdata interfaceIdx */
int index = 0;
while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
if (cooked[2].charAt(index) == '\\') {
@@ -473,6 +505,7 @@
Log.e(TAG, "Invalid service found " + raw);
break;
}
+
String name = cooked[2].substring(0, index);
String rest = cooked[2].substring(index);
String type = rest.replace(".local.", "");
@@ -483,12 +516,13 @@
clientInfo.mResolvedService.setServiceType(type);
clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
clientInfo.mResolvedService.setTxtRecords(cooked[6]);
+ // Network will be added after SERVICE_GET_ADDR_SUCCESS
stopResolveService(id);
removeRequestMap(clientId, id, clientInfo);
int id2 = getUniqueId();
- if (getAddrInfo(id2, cooked[3])) {
+ if (getAddrInfo(id2, cooked[3], cooked[7] /* interfaceIdx */)) {
storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
} else {
clientInfo.onResolveServiceFailed(
@@ -513,12 +547,31 @@
clientId, NsdManager.FAILURE_INTERNAL_ERROR);
break;
case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
- /* NNN resolveId hostname ttl addr */
+ /* NNN resolveId hostname ttl addr interfaceIdx netId */
+ Network network = null;
try {
- clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
+ final int netId = Integer.parseInt(cooked[6]);
+ network = netId == 0L ? null : new Network(netId);
+ } catch (NumberFormatException e) {
+ Log.wtf(TAG, "Invalid network in GET_ADDR_SUCCESS: " + cooked[6], e);
+ }
+
+ InetAddress serviceHost = null;
+ try {
+ serviceHost = InetAddress.getByName(cooked[4]);
+ } catch (UnknownHostException e) {
+ Log.wtf(TAG, "Invalid host in GET_ADDR_SUCCESS", e);
+ }
+
+ // If the resolved service is on an interface without a network, consider it
+ // as a failure: it would not be usable by apps as they would need
+ // privileged permissions.
+ if (network != null && serviceHost != null) {
+ clientInfo.mResolvedService.setHost(serviceHost);
+ clientInfo.mResolvedService.setNetwork(network);
clientInfo.onResolveServiceSucceeded(
clientId, clientInfo.mResolvedService);
- } catch (java.net.UnknownHostException e) {
+ } else {
clientInfo.onResolveServiceFailed(
clientId, NsdManager.FAILURE_INTERNAL_ERROR);
}
@@ -815,8 +868,15 @@
return mDaemon.execute("update", regId, t.size(), t.getRawData());
}
- private boolean discoverServices(int discoveryId, String serviceType) {
- return mDaemon.execute("discover", discoveryId, serviceType);
+ private boolean discoverServices(int discoveryId, NsdServiceInfo serviceInfo) {
+ final Network network = serviceInfo.getNetwork();
+ final int discoverInterface = getNetworkInterfaceIndex(network);
+ if (network != null && discoverInterface == IFACE_IDX_ANY) {
+ Log.e(TAG, "Interface to discover service on not found");
+ return false;
+ }
+ return mDaemon.execute("discover", discoveryId, serviceInfo.getServiceType(),
+ discoverInterface);
}
private boolean stopServiceDiscovery(int discoveryId) {
@@ -824,17 +884,61 @@
}
private boolean resolveService(int resolveId, NsdServiceInfo service) {
- String name = service.getServiceName();
- String type = service.getServiceType();
- return mDaemon.execute("resolve", resolveId, name, type, "local.");
+ final String name = service.getServiceName();
+ final String type = service.getServiceType();
+ final Network network = service.getNetwork();
+ final int resolveInterface = getNetworkInterfaceIndex(network);
+ if (network != null && resolveInterface == IFACE_IDX_ANY) {
+ Log.e(TAG, "Interface to resolve service on not found");
+ return false;
+ }
+ return mDaemon.execute("resolve", resolveId, name, type, "local.", resolveInterface);
+ }
+
+ /**
+ * Guess the interface to use to resolve or discover a service on a specific network.
+ *
+ * This is an imperfect guess, as for example the network may be gone or not yet fully
+ * registered. This is fine as failing is correct if the network is gone, and a client
+ * attempting to resolve/discover on a network not yet setup would have a bad time anyway; also
+ * this is to support the legacy mdnsresponder implementation, which historically resolved
+ * services on an unspecified network.
+ */
+ private int getNetworkInterfaceIndex(Network network) {
+ if (network == null) return IFACE_IDX_ANY;
+
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ if (cm == null) {
+ Log.wtf(TAG, "No ConnectivityManager for resolveService");
+ return IFACE_IDX_ANY;
+ }
+ final LinkProperties lp = cm.getLinkProperties(network);
+ if (lp == null) return IFACE_IDX_ANY;
+
+ // Only resolve on non-stacked interfaces
+ final NetworkInterface iface;
+ try {
+ iface = NetworkInterface.getByName(lp.getInterfaceName());
+ } catch (SocketException e) {
+ Log.e(TAG, "Error querying interface", e);
+ return IFACE_IDX_ANY;
+ }
+
+ if (iface == null) {
+ Log.e(TAG, "Interface not found: " + lp.getInterfaceName());
+ return IFACE_IDX_ANY;
+ }
+
+ return iface.getIndex();
}
private boolean stopResolveService(int resolveId) {
return mDaemon.execute("stop-resolve", resolveId);
}
- private boolean getAddrInfo(int resolveId, String hostname) {
- return mDaemon.execute("getaddrinfo", resolveId, hostname);
+ private boolean getAddrInfo(int resolveId, String hostname, String interfaceIdx) {
+ // interfaceIdx is always obtained (as string) from the service resolved callback
+ return mDaemon.execute("getaddrinfo", resolveId, hostname, interfaceIdx);
}
private boolean stopGetAddrInfo(int resolveId) {
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
new file mode 100644
index 0000000..25c88eb
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/BpfInterfaceMapUpdater.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import android.content.Context;
+import android.net.INetd;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+import android.system.ErrnoException;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
+import com.android.net.module.util.BpfMap;
+import com.android.net.module.util.IBpfMap;
+import com.android.net.module.util.InterfaceParams;
+import com.android.net.module.util.Struct.U32;
+
+/**
+ * Monitor interface added (without removed) and right interface name and its index to bpf map.
+ */
+public class BpfInterfaceMapUpdater {
+ private static final String TAG = BpfInterfaceMapUpdater.class.getSimpleName();
+ // This is current path but may be changed soon.
+ private static final String IFACE_INDEX_NAME_MAP_PATH =
+ "/sys/fs/bpf/map_netd_iface_index_name_map";
+ private final IBpfMap<U32, InterfaceMapValue> mBpfMap;
+ private final INetd mNetd;
+ private final Handler mHandler;
+ private final Dependencies mDeps;
+
+ public BpfInterfaceMapUpdater(Context ctx, Handler handler) {
+ this(ctx, handler, new Dependencies());
+ }
+
+ @VisibleForTesting
+ public BpfInterfaceMapUpdater(Context ctx, Handler handler, Dependencies deps) {
+ mDeps = deps;
+ mBpfMap = deps.getInterfaceMap();
+ mNetd = deps.getINetd(ctx);
+ mHandler = handler;
+ }
+
+ /**
+ * Dependencies of BpfInerfaceMapUpdater, for injection in tests.
+ */
+ @VisibleForTesting
+ public static class Dependencies {
+ /** Create BpfMap for updating interface and index mapping. */
+ public IBpfMap<U32, InterfaceMapValue> getInterfaceMap() {
+ try {
+ return new BpfMap<>(IFACE_INDEX_NAME_MAP_PATH, BpfMap.BPF_F_RDWR,
+ U32.class, InterfaceMapValue.class);
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Cannot create interface map: " + e);
+ return null;
+ }
+ }
+
+ /** Get InterfaceParams for giving interface name. */
+ public InterfaceParams getInterfaceParams(String ifaceName) {
+ return InterfaceParams.getByName(ifaceName);
+ }
+
+ /** Get INetd binder object. */
+ public INetd getINetd(Context ctx) {
+ return INetd.Stub.asInterface((IBinder) ctx.getSystemService(Context.NETD_SERVICE));
+ }
+ }
+
+ /**
+ * Start listening interface update event.
+ * Query current interface names before listening.
+ */
+ public void start() {
+ mHandler.post(() -> {
+ if (mBpfMap == null) {
+ Log.wtf(TAG, "Fail to start: Null bpf map");
+ return;
+ }
+
+ try {
+ // TODO: use a NetlinkMonitor and listen for RTM_NEWLINK messages instead.
+ mNetd.registerUnsolicitedEventListener(new InterfaceChangeObserver());
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Unable to register netd UnsolicitedEventListener, " + e);
+ }
+
+ final String[] ifaces;
+ try {
+ // TODO: use a netlink dump to get the current interface list.
+ ifaces = mNetd.interfaceGetList();
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.wtf(TAG, "Unable to query interface names by netd, " + e);
+ return;
+ }
+
+ for (String ifaceName : ifaces) {
+ addInterface(ifaceName);
+ }
+ });
+ }
+
+ private void addInterface(String ifaceName) {
+ final InterfaceParams iface = mDeps.getInterfaceParams(ifaceName);
+ if (iface == null) {
+ Log.e(TAG, "Unable to get InterfaceParams for " + ifaceName);
+ return;
+ }
+
+ try {
+ mBpfMap.updateEntry(new U32(iface.index), new InterfaceMapValue(ifaceName));
+ } catch (ErrnoException e) {
+ Log.e(TAG, "Unable to update entry for " + ifaceName + ", " + e);
+ }
+ }
+
+ private class InterfaceChangeObserver extends BaseNetdUnsolicitedEventListener {
+ @Override
+ public void onInterfaceAdded(String ifName) {
+ mHandler.post(() -> addInterface(ifName));
+ }
+ }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
new file mode 100644
index 0000000..443e5b3
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapKey.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Key for cookie tag map.
+ */
+public class CookieTagMapKey extends Struct {
+ @Field(order = 0, type = Type.S64)
+ public final long socketCookie;
+
+ public CookieTagMapKey(final long socketCookie) {
+ this.socketCookie = socketCookie;
+ }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
new file mode 100644
index 0000000..93b9195
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/CookieTagMapValue.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Value for cookie tag map.
+ */
+public class CookieTagMapValue extends Struct {
+ @Field(order = 0, type = Type.U32)
+ public final long uid;
+
+ @Field(order = 1, type = Type.U32)
+ public final long tag;
+
+ public CookieTagMapValue(final long uid, final long tag) {
+ this.uid = uid;
+ this.tag = tag;
+ }
+}
diff --git a/services/core/java/com/android/server/net/DelayedDiskWrite.java b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
similarity index 82%
rename from services/core/java/com/android/server/net/DelayedDiskWrite.java
rename to packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
index 8f09eb7..35dc455 100644
--- a/services/core/java/com/android/server/net/DelayedDiskWrite.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/DelayedDiskWrite.java
@@ -26,21 +26,37 @@
import java.io.FileOutputStream;
import java.io.IOException;
+/**
+ * This class provides APIs to do a delayed data write to a given {@link OutputStream}.
+ */
public class DelayedDiskWrite {
+ private static final String TAG = "DelayedDiskWrite";
+
private HandlerThread mDiskWriteHandlerThread;
private Handler mDiskWriteHandler;
/* Tracks multiple writes on the same thread */
private int mWriteSequence = 0;
- private final String TAG = "DelayedDiskWrite";
+ /**
+ * Used to do a delayed data write to a given {@link OutputStream}.
+ */
public interface Writer {
- public void onWriteCalled(DataOutputStream out) throws IOException;
+ /**
+ * write data to a given {@link OutputStream}.
+ */
+ void onWriteCalled(DataOutputStream out) throws IOException;
}
+ /**
+ * Do a delayed data write to a given output stream opened from filePath.
+ */
public void write(final String filePath, final Writer w) {
write(filePath, w, true);
}
+ /**
+ * Do a delayed data write to a given output stream opened from filePath.
+ */
public void write(final String filePath, final Writer w, final boolean open) {
if (TextUtils.isEmpty(filePath)) {
throw new IllegalArgumentException("empty file path");
@@ -77,7 +93,7 @@
if (out != null) {
try {
out.close();
- } catch (Exception e) {}
+ } catch (Exception e) { }
}
// Quit if no more writes sent
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
new file mode 100644
index 0000000..061f323
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/InterfaceMapValue.java
@@ -0,0 +1,35 @@
+/*
+ * 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * The value of bpf interface index map which is used for NetworkStatsService.
+ */
+public class InterfaceMapValue extends Struct {
+ @Field(order = 0, type = Type.ByteArray, arraysize = 16)
+ public final byte[] interfaceName;
+
+ public InterfaceMapValue(String iface) {
+ final byte[] ifaceArray = iface.getBytes();
+ interfaceName = new byte[16];
+ // All array bytes after the interface name, if any, must be 0.
+ System.arraycopy(ifaceArray, 0, interfaceName, 0, ifaceArray.length);
+ }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
index bb123a3..668d1cb 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
@@ -22,14 +22,12 @@
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
-import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.INetd;
+import android.content.Context;
+import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.net.UnderlyingNetworkInfo;
-import android.os.RemoteException;
import android.os.StrictMode;
import android.os.SystemClock;
@@ -70,7 +68,7 @@
private final boolean mUseBpfStats;
- private final INetd mNetd;
+ private final Context mContext;
/**
* Guards persistent data access in this class
@@ -158,12 +156,12 @@
NetworkStats.apply464xlatAdjustments(baseTraffic, stackedTraffic, mStackedIfaces);
}
- public NetworkStatsFactory(@NonNull INetd netd) {
- this(new File("/proc/"), true, netd);
+ public NetworkStatsFactory(@NonNull Context ctx) {
+ this(ctx, new File("/proc/"), true);
}
@VisibleForTesting
- public NetworkStatsFactory(File procRoot, boolean useBpfStats, @NonNull INetd netd) {
+ public NetworkStatsFactory(@NonNull Context ctx, File procRoot, boolean useBpfStats) {
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
@@ -172,7 +170,7 @@
mPersistSnapshot = new NetworkStats(SystemClock.elapsedRealtime(), -1);
mTunAnd464xlatAdjustedStats = new NetworkStats(SystemClock.elapsedRealtime(), -1);
}
- mNetd = netd;
+ mContext = ctx;
}
public NetworkStats readBpfNetworkStatsDev() throws IOException {
@@ -295,11 +293,12 @@
}
@GuardedBy("mPersistentDataLock")
- private void requestSwapActiveStatsMapLocked() throws RemoteException {
- // Ask netd to do a active map stats swap. When the binder call successfully returns,
+ private void requestSwapActiveStatsMapLocked() {
+ // Do a active map stats swap. When the binder call successfully returns,
// the system server should be able to safely read and clean the inactive map
// without race problem.
- mNetd.trafficSwapActiveStatsMap();
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ cm.swapActiveStatsMap();
}
/**
@@ -327,7 +326,7 @@
if (mUseBpfStats) {
try {
requestSwapActiveStatsMapLocked();
- } catch (RemoteException e) {
+ } catch (RuntimeException e) {
throw new IOException(e);
}
// Stats are always read from the inactive map, so they must be read after the
@@ -469,6 +468,19 @@
}
/**
+ * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
+ * format like {@code 0x7fffffff00000000}.
+ */
+ public static int kernelToTag(String string) {
+ int length = string.length();
+ if (length > 10) {
+ return Long.decode(string.substring(0, length - 8)).intValue();
+ } else {
+ return 0;
+ }
+ }
+
+ /**
* Parse statistics from file into given {@link NetworkStats} object. Values
* are expected to monotonically increase since device boot.
*/
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
index b57a4f9..1953624 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsObservers.java
@@ -26,13 +26,12 @@
import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.os.Bundle;
+import android.net.netstats.IUsageCallback;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.Messenger;
import android.os.Process;
import android.os.RemoteException;
import android.util.ArrayMap;
@@ -75,10 +74,10 @@
*
* @return the normalized request wrapped within {@link RequestInfo}.
*/
- public DataUsageRequest register(DataUsageRequest inputRequest, Messenger messenger,
- IBinder binder, int callingUid, @NetworkStatsAccess.Level int accessLevel) {
- DataUsageRequest request = buildRequest(inputRequest);
- RequestInfo requestInfo = buildRequestInfo(request, messenger, binder, callingUid,
+ public DataUsageRequest register(DataUsageRequest inputRequest, IUsageCallback callback,
+ int callingUid, @NetworkStatsAccess.Level int accessLevel) {
+ DataUsageRequest request = buildRequest(inputRequest, callingUid);
+ RequestInfo requestInfo = buildRequestInfo(request, callback, callingUid,
accessLevel);
if (LOGV) Log.v(TAG, "Registering observer for " + request);
@@ -195,10 +194,12 @@
}
}
- private DataUsageRequest buildRequest(DataUsageRequest request) {
- // Cap the minimum threshold to a safe default to avoid too many callbacks
- long thresholdInBytes = Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes);
- if (thresholdInBytes < request.thresholdInBytes) {
+ private DataUsageRequest buildRequest(DataUsageRequest request, int callingUid) {
+ // For non-system uid, cap the minimum threshold to a safe default to avoid too
+ // many callbacks.
+ long thresholdInBytes = (callingUid == Process.SYSTEM_UID ? request.thresholdInBytes
+ : Math.max(MIN_THRESHOLD_BYTES, request.thresholdInBytes));
+ if (thresholdInBytes > request.thresholdInBytes) {
Log.w(TAG, "Threshold was too low for " + request
+ ". Overriding to a safer default of " + thresholdInBytes + " bytes");
}
@@ -206,11 +207,10 @@
request.template, thresholdInBytes);
}
- private RequestInfo buildRequestInfo(DataUsageRequest request,
- Messenger messenger, IBinder binder, int callingUid,
- @NetworkStatsAccess.Level int accessLevel) {
+ private RequestInfo buildRequestInfo(DataUsageRequest request, IUsageCallback callback,
+ int callingUid, @NetworkStatsAccess.Level int accessLevel) {
if (accessLevel <= NetworkStatsAccess.Level.USER) {
- return new UserUsageRequestInfo(this, request, messenger, binder, callingUid,
+ return new UserUsageRequestInfo(this, request, callback, callingUid,
accessLevel);
} else {
// Safety check in case a new access level is added and we forgot to update this
@@ -218,7 +218,7 @@
throw new IllegalArgumentException(
"accessLevel " + accessLevel + " is less than DEVICESUMMARY.");
}
- return new NetworkUsageRequestInfo(this, request, messenger, binder, callingUid,
+ return new NetworkUsageRequestInfo(this, request, callback, callingUid,
accessLevel);
}
}
@@ -230,25 +230,23 @@
private abstract static class RequestInfo implements IBinder.DeathRecipient {
private final NetworkStatsObservers mStatsObserver;
protected final DataUsageRequest mRequest;
- private final Messenger mMessenger;
- private final IBinder mBinder;
+ private final IUsageCallback mCallback;
protected final int mCallingUid;
protected final @NetworkStatsAccess.Level int mAccessLevel;
protected NetworkStatsRecorder mRecorder;
protected NetworkStatsCollection mCollection;
RequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
- Messenger messenger, IBinder binder, int callingUid,
+ IUsageCallback callback, int callingUid,
@NetworkStatsAccess.Level int accessLevel) {
mStatsObserver = statsObserver;
mRequest = request;
- mMessenger = messenger;
- mBinder = binder;
+ mCallback = callback;
mCallingUid = callingUid;
mAccessLevel = accessLevel;
try {
- mBinder.linkToDeath(this, 0);
+ mCallback.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
binderDied();
}
@@ -257,7 +255,7 @@
@Override
public void binderDied() {
if (LOGV) {
- Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mBinder + ")");
+ Log.v(TAG, "RequestInfo binderDied(" + mRequest + ", " + mCallback + ")");
}
mStatsObserver.unregister(mRequest, Process.SYSTEM_UID);
callCallback(NetworkStatsManager.CALLBACK_RELEASED);
@@ -270,9 +268,7 @@
}
private void unlinkDeathRecipient() {
- if (mBinder != null) {
- mBinder.unlinkToDeath(this, 0);
- }
+ mCallback.asBinder().unlinkToDeath(this, 0);
}
/**
@@ -294,17 +290,19 @@
}
private void callCallback(int callbackType) {
- Bundle bundle = new Bundle();
- bundle.putParcelable(DataUsageRequest.PARCELABLE_KEY, mRequest);
- Message msg = Message.obtain();
- msg.what = callbackType;
- msg.setData(bundle);
try {
if (LOGV) {
Log.v(TAG, "sending notification " + callbackTypeToName(callbackType)
+ " for " + mRequest);
}
- mMessenger.send(msg);
+ switch (callbackType) {
+ case NetworkStatsManager.CALLBACK_LIMIT_REACHED:
+ mCallback.onThresholdReached(mRequest);
+ break;
+ case NetworkStatsManager.CALLBACK_RELEASED:
+ mCallback.onCallbackReleased(mRequest);
+ break;
+ }
} catch (RemoteException e) {
// May occur naturally in the race of binder death.
Log.w(TAG, "RemoteException caught trying to send a callback msg for " + mRequest);
@@ -334,9 +332,9 @@
private static class NetworkUsageRequestInfo extends RequestInfo {
NetworkUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
- Messenger messenger, IBinder binder, int callingUid,
+ IUsageCallback callback, int callingUid,
@NetworkStatsAccess.Level int accessLevel) {
- super(statsObserver, request, messenger, binder, callingUid, accessLevel);
+ super(statsObserver, request, callback, callingUid, accessLevel);
}
@Override
@@ -376,9 +374,9 @@
private static class UserUsageRequestInfo extends RequestInfo {
UserUsageRequestInfo(NetworkStatsObservers statsObserver, DataUsageRequest request,
- Messenger messenger, IBinder binder, int callingUid,
+ IUsageCallback callback, int callingUid,
@NetworkStatsAccess.Level int accessLevel) {
- super(statsObserver, request, messenger, binder, callingUid, accessLevel);
+ super(statsObserver, request, callback, callingUid, accessLevel);
}
@Override
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index e15acf3..9f3371b 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -19,12 +19,13 @@
import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
+import static android.app.usage.NetworkStatsManager.PREFIX_DEV;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.ACTION_USER_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.IFACE_VT;
@@ -46,24 +47,10 @@
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UNSUPPORTED;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
import static android.os.Trace.TRACE_TAG_NETWORK;
-import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
-import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
-import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
-import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
-import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
-import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
-import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
-import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
-import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
-import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
-import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
-import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
@@ -72,8 +59,6 @@
import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
-import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
-import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -112,6 +97,7 @@
import android.net.TrafficStats;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
+import android.net.netstats.IUsageCallback;
import android.net.netstats.provider.INetworkStatsProvider;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
@@ -119,12 +105,10 @@
import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
-import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.Messenger;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -135,6 +119,8 @@
import android.provider.Settings.Global;
import android.service.NetworkInterfaceProto;
import android.service.NetworkStatsServiceDumpProto;
+import android.system.ErrnoException;
+import android.system.Os;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionPlan;
import android.text.TextUtils;
@@ -153,10 +139,14 @@
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.BestClock;
import com.android.net.module.util.BinderUtils;
+import com.android.net.module.util.BpfMap;
import com.android.net.module.util.CollectionUtils;
+import com.android.net.module.util.IBpfMap;
+import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.NetworkStatsUtils;
import com.android.net.module.util.PermissionUtils;
-import com.android.server.LocalServices;
+import com.android.net.module.util.Struct.U32;
+import com.android.net.module.util.Struct.U8;
import java.io.File;
import java.io.FileDescriptor;
@@ -217,6 +207,14 @@
private static final int LOG_TAG_NETSTATS_MOBILE_SAMPLE = 51100;
private static final int LOG_TAG_NETSTATS_WIFI_SAMPLE = 51101;
+ // TODO: Replace the hardcoded string and move it into ConnectivitySettingsManager.
+ private static final String NETSTATS_COMBINE_SUBTYPE_ENABLED =
+ "netstats_combine_subtype_enabled";
+
+ // This is current path but may be changed soon.
+ private static final String UID_COUNTERSET_MAP_PATH =
+ "/sys/fs/bpf/map_netd_uid_counterset_map";
+
private final Context mContext;
private final NetworkStatsFactory mStatsFactory;
private final AlarmManager mAlarmManager;
@@ -243,11 +241,6 @@
private PendingIntent mPollIntent;
- private static final String PREFIX_DEV = "dev";
- private static final String PREFIX_XT = "xt";
- private static final String PREFIX_UID = "uid";
- private static final String PREFIX_UID_TAG = "uid_tag";
-
/**
* Settings that can be changed externally.
*/
@@ -257,9 +250,9 @@
boolean getSampleEnabled();
boolean getAugmentEnabled();
/**
- * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
- * When disabled, mobile data is broken down by a granular subtype representative of the
- * actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
+ * When enabled, all mobile data is reported under {@link NetworkTemplate#NETWORK_TYPE_ALL}.
+ * When disabled, mobile data is broken down by a granular ratType representative of the
+ * actual ratType. {@see android.app.usage.NetworkStatsManager#getCollapsedRatType}.
* Enabling this decreases the level of detail but saves performance, disk space and
* amount of data logged.
*/
@@ -306,6 +299,9 @@
/** Set of any ifaces associated with mobile networks since boot. */
private volatile String[] mMobileIfaces = new String[0];
+ /** Set of any ifaces associated with wifi networks since boot. */
+ private volatile String[] mWifiIfaces = new String[0];
+
/** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
@GuardedBy("mStatsLock")
private Network[] mDefaultNetworks = new Network[0];
@@ -337,8 +333,14 @@
@GuardedBy("mStatsLock")
private NetworkStatsCollection mXtStatsCached;
- /** Current counter sets for each UID. */
+ /**
+ * Current counter sets for each UID.
+ * TODO: maybe remove mActiveUidCounterSet and read UidCouneterSet value from mUidCounterSetMap
+ * directly ? But if mActiveUidCounterSet would be accessed very frequently, maybe keep
+ * mActiveUidCounterSet to avoid accessing kernel too frequently.
+ */
private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
+ private final IBpfMap<U32, U8> mUidCounterSetMap;
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mUidOperations = new NetworkStats(0L, 10);
@@ -366,6 +368,12 @@
@NonNull
private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
+ @NonNull
+ private final LocationPermissionChecker mLocationPermissionChecker;
+
+ @NonNull
+ private final BpfInterfaceMapUpdater mInterfaceMapUpdater;
+
private static @NonNull File getDefaultSystemDir() {
return new File(Environment.getDataDirectory(), "system");
}
@@ -428,7 +436,7 @@
final NetworkStatsService service = new NetworkStatsService(context,
INetd.Stub.asInterface((IBinder) context.getSystemService(Context.NETD_SERVICE)),
alarmManager, wakeLock, getDefaultClock(),
- new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(netd),
+ new DefaultNetworkStatsSettings(), new NetworkStatsFactory(context),
new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
new Dependencies());
@@ -458,10 +466,14 @@
handlerThread.start();
mHandler = new NetworkStatsHandler(handlerThread.getLooper());
mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
- new HandlerExecutor(mHandler), this);
+ (command) -> mHandler.post(command) , this);
mContentResolver = mContext.getContentResolver();
mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
mNetworkStatsSubscriptionsMonitor);
+ mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
+ mInterfaceMapUpdater = mDeps.makeBpfInterfaceMapUpdater(mContext, mHandler);
+ mInterfaceMapUpdater.start();
+ mUidCounterSetMap = mDeps.getUidCounterSetMap();
}
/**
@@ -509,6 +521,35 @@
}
};
}
+
+ /**
+ * @see LocationPermissionChecker
+ */
+ public LocationPermissionChecker makeLocationPermissionChecker(final Context context) {
+ return new LocationPermissionChecker(context);
+ }
+
+ /** Create BpfInterfaceMapUpdater to update bpf interface map. */
+ @NonNull
+ public BpfInterfaceMapUpdater makeBpfInterfaceMapUpdater(
+ @NonNull Context ctx, @NonNull Handler handler) {
+ return new BpfInterfaceMapUpdater(ctx, handler);
+ }
+
+ /** Get counter sets map for each UID. */
+ public IBpfMap<U32, U8> getUidCounterSetMap() {
+ try {
+ return new BpfMap<U32, U8>(UID_COUNTERSET_MAP_PATH, BpfMap.BPF_F_RDWR,
+ U32.class, U8.class);
+ } catch (ErrnoException e) {
+ Log.wtf(TAG, "Cannot create uid counter set map: " + e);
+ return null;
+ }
+ }
+
+ public TagStatsDeleter getTagStatsDeleter() {
+ return NetworkStatsService::nativeDeleteTagData;
+ }
}
/**
@@ -557,7 +598,7 @@
// watch for tethering changes
final TetheringManager tetheringManager = mContext.getSystemService(TetheringManager.class);
tetheringManager.registerTetheringEventCallback(
- new HandlerExecutor(mHandler), mTetherListener);
+ (command) -> mHandler.post(command), mTetherListener);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
@@ -591,13 +632,13 @@
mSettings.getPollInterval(), pollIntent);
mContentResolver.registerContentObserver(Settings.Global
- .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED),
+ .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED),
false /* notifyForDescendants */, mContentObserver);
// Post a runnable on handler thread to call onChange(). It's for getting current value of
// NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes.
mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
- .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED)));
+ .getUriFor(NETSTATS_COMBINE_SUBTYPE_ENABLED)));
registerGlobalAlert();
}
@@ -708,12 +749,25 @@
return now - lastCallTime < POLL_RATE_LIMIT_MS;
}
- private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
+ private int restrictFlagsForCaller(int flags) {
+ // All non-privileged callers are not allowed to turn off POLL_ON_OPEN.
+ final boolean isPrivileged = PermissionUtils.checkAnyPermissionOf(mContext,
+ NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+ android.Manifest.permission.NETWORK_STACK);
+ if (!isPrivileged) {
+ flags |= NetworkStatsManager.FLAG_POLL_ON_OPEN;
+ }
+ // Non-system uids are rate limited for POLL_ON_OPEN.
final int callingUid = Binder.getCallingUid();
- final int usedFlags = isRateLimitedForPoll(callingUid)
+ flags = isRateLimitedForPoll(callingUid)
? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
: flags;
- if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
+ return flags;
+ }
+
+ private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
+ final int restrictedFlags = restrictFlagsForCaller(flags);
+ if ((restrictedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
| NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -727,7 +781,7 @@
// for its lifetime; when caller closes only weak references remain.
return new INetworkStatsSession.Stub() {
- private final int mCallingUid = callingUid;
+ private final int mCallingUid = Binder.getCallingUid();
private final String mCallingPackage = callingPackage;
private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
callingPackage);
@@ -761,26 +815,41 @@
@Override
public NetworkStats getDeviceSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
- mCallingUid);
+ enforceTemplatePermissions(template, callingPackage);
+ return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
+ mAccessLevel, mCallingUid);
}
@Override
public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) {
- return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
- mCallingUid);
+ enforceTemplatePermissions(template, callingPackage);
+ return internalGetSummaryForNetwork(template, restrictedFlags, start, end,
+ mAccessLevel, mCallingUid);
+ }
+
+ // TODO: Remove this after all callers are removed.
+ @Override
+ public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
+ enforceTemplatePermissions(template, callingPackage);
+ return internalGetHistoryForNetwork(template, restrictedFlags, fields,
+ mAccessLevel, mCallingUid, Long.MIN_VALUE, Long.MAX_VALUE);
}
@Override
- public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
- return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
- mCallingUid);
+ public NetworkStatsHistory getHistoryIntervalForNetwork(NetworkTemplate template,
+ int fields, long start, long end) {
+ enforceTemplatePermissions(template, callingPackage);
+ // TODO(b/200768422): Redact returned history if the template is location
+ // sensitive but the caller is not privileged.
+ return internalGetHistoryForNetwork(template, restrictedFlags, fields,
+ mAccessLevel, mCallingUid, start, end);
}
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
+ enforceTemplatePermissions(template, callingPackage);
try {
final NetworkStats stats = getUidComplete()
.getSummary(template, start, end, mAccessLevel, mCallingUid);
@@ -798,6 +867,7 @@
@Override
public NetworkStats getTaggedSummaryForAllUid(
NetworkTemplate template, long start, long end) {
+ enforceTemplatePermissions(template, callingPackage);
try {
final NetworkStats tagStats = getUidTagComplete()
.getSummary(template, start, end, mAccessLevel, mCallingUid);
@@ -810,6 +880,7 @@
@Override
public NetworkStatsHistory getHistoryForUid(
NetworkTemplate template, int uid, int set, int tag, int fields) {
+ enforceTemplatePermissions(template, callingPackage);
// NOTE: We don't augment UID-level statistics
if (tag == TAG_NONE) {
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
@@ -824,6 +895,9 @@
public NetworkStatsHistory getHistoryIntervalForUid(
NetworkTemplate template, int uid, int set, int tag, int fields,
long start, long end) {
+ enforceTemplatePermissions(template, callingPackage);
+ // TODO(b/200768422): Redact returned history if the template is location
+ // sensitive but the caller is not privileged.
// NOTE: We don't augment UID-level statistics
if (tag == TAG_NONE) {
return getUidComplete().getHistory(template, null, uid, set, tag, fields,
@@ -845,6 +919,26 @@
};
}
+ private void enforceTemplatePermissions(@NonNull NetworkTemplate template,
+ @NonNull String callingPackage) {
+ // For a template with wifi network keys, it is possible for a malicious
+ // client to track the user locations via querying data usage. Thus, enforce
+ // fine location permission check.
+ if (!template.getWifiNetworkKeys().isEmpty()) {
+ final boolean canAccessFineLocation = mLocationPermissionChecker
+ .checkCallersLocationPermission(callingPackage,
+ null /* featureId */,
+ Binder.getCallingUid(),
+ false /* coarseForTargetSdkLessThanQ */,
+ null /* message */);
+ if (!canAccessFineLocation) {
+ throw new SecurityException("Access fine location is required when querying"
+ + " with wifi network keys, make sure the app has the necessary"
+ + "permissions and the location toggle is on.");
+ }
+ }
+ }
+
private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
return NetworkStatsAccess.checkAccessLevel(
mContext, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage);
@@ -881,7 +975,7 @@
// We've been using pure XT stats long enough that we no longer need to
// splice DEV and XT together.
final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
- accessLevel, callingUid);
+ accessLevel, callingUid, start, end);
final long now = System.currentTimeMillis();
final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
@@ -898,14 +992,14 @@
* appropriate.
*/
private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
- int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
+ int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid,
+ long start, long end) {
// We've been using pure XT stats long enough that we no longer need to
// splice DEV and XT together.
final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
synchronized (mStatsLock) {
return mXtStatsCached.getHistory(template, augmentPlan,
- UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
- accessLevel, callingUid);
+ UID_ALL, SET_ALL, TAG_NONE, fields, start, end, accessLevel, callingUid);
}
}
@@ -936,8 +1030,17 @@
}
// TODO: switch to data layer stats once kernel exports
- // for now, read network layer stats and flatten across all ifaces
- final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
+ // for now, read network layer stats and flatten across all ifaces.
+ // This function is used to query NeworkStats for calle's uid. The only caller method
+ // TrafficStats#getDataLayerSnapshotForUid alrady claim no special permission to query
+ // its own NetworkStats.
+ final long ident = Binder.clearCallingIdentity();
+ final NetworkStats networkLayer;
+ try {
+ networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
// splice in operation counts
networkLayer.spliceOperationsFrom(mUidOperations);
@@ -956,11 +1059,15 @@
}
@Override
- public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
+ public NetworkStats getUidStatsForTransport(int transport) {
enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
try {
+ final String[] relevantIfaces =
+ transport == TRANSPORT_WIFI ? mWifiIfaces : mMobileIfaces;
+ // TODO(b/215633405) : mMobileIfaces and mWifiIfaces already contain the stacked
+ // interfaces, so this is not useful, remove it.
final String[] ifacesToQuery =
- mStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
+ mStatsFactory.augmentWithStackedInterfaces(relevantIfaces);
return getNetworkStatsUidDetail(ifacesToQuery);
} catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e);
@@ -1000,6 +1107,29 @@
}
}
+ private void setKernelCounterSet(int uid, int set) {
+ if (mUidCounterSetMap == null) {
+ Log.wtf(TAG, "Fail to set UidCounterSet: Null bpf map");
+ return;
+ }
+
+ if (set == SET_DEFAULT) {
+ try {
+ mUidCounterSetMap.deleteEntry(new U32(uid));
+ } catch (ErrnoException e) {
+ Log.w(TAG, "UidCounterSetMap.deleteEntry(" + uid + ") failed with errno: " + e);
+ }
+ return;
+ }
+
+ try {
+ mUidCounterSetMap.updateEntry(new U32(uid), new U8((short) set));
+ } catch (ErrnoException e) {
+ Log.w(TAG, "UidCounterSetMap.updateEntry(" + uid + ", " + set
+ + ") failed with errno: " + e);
+ }
+ }
+
@VisibleForTesting
public void setUidForeground(int uid, boolean uidForeground) {
PermissionUtils.enforceNetworkStackPermission(mContext);
@@ -1080,21 +1210,20 @@
}
@Override
- public DataUsageRequest registerUsageCallback(String callingPackage,
- DataUsageRequest request, Messenger messenger, IBinder binder) {
+ public DataUsageRequest registerUsageCallback(@NonNull String callingPackage,
+ @NonNull DataUsageRequest request, @NonNull IUsageCallback callback) {
Objects.requireNonNull(callingPackage, "calling package is null");
Objects.requireNonNull(request, "DataUsageRequest is null");
Objects.requireNonNull(request.template, "NetworkTemplate is null");
- Objects.requireNonNull(messenger, "messenger is null");
- Objects.requireNonNull(binder, "binder is null");
+ Objects.requireNonNull(callback, "callback is null");
int callingUid = Binder.getCallingUid();
@NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
DataUsageRequest normalizedRequest;
final long token = Binder.clearCallingIdentity();
try {
- normalizedRequest = mStatsObservers.register(request, messenger, binder,
- callingUid, accessLevel);
+ normalizedRequest = mStatsObservers.register(
+ request, callback, callingUid, accessLevel);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -1319,16 +1448,18 @@
final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
final ArraySet<String> mobileIfaces = new ArraySet<>();
+ final ArraySet<String> wifiIfaces = new ArraySet<>();
for (NetworkStateSnapshot snapshot : snapshots) {
final int displayTransport =
getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
+ final boolean isWifi = (NetworkCapabilities.TRANSPORT_WIFI == displayTransport);
final boolean isDefault = CollectionUtils.contains(
mDefaultNetworks, snapshot.getNetwork());
- final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
- : getSubTypeForStateSnapshot(snapshot);
+ final int ratType = combineSubtypeEnabled ? NetworkTemplate.NETWORK_TYPE_ALL
+ : getRatTypeForStateSnapshot(snapshot);
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
- isDefault, subType);
+ isDefault, ratType);
// Traffic occurring on the base interface is always counted for
// both total usage and UID details.
@@ -1343,12 +1474,12 @@
// VT is considered always metered in framework's layer. If VT is not metered
// per carrier's policy, modem will report 0 usage for VT calls.
if (snapshot.getNetworkCapabilities().hasCapability(
- NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) {
+ NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.isMetered()) {
// Copy the identify from IMS one but mark it as metered.
NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
- ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
- ident.getRoaming(), true /* metered */,
+ ident.getRatType(), ident.getSubscriberId(), ident.getWifiNetworkKey(),
+ ident.isRoaming(), true /* metered */,
true /* onDefaultNetwork */, ident.getOemManaged());
final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
@@ -1358,6 +1489,9 @@
if (isMobile) {
mobileIfaces.add(baseIface);
}
+ if (isWifi) {
+ wifiIfaces.add(baseIface);
+ }
}
// Traffic occurring on stacked interfaces is usually clatd.
@@ -1399,6 +1533,9 @@
if (isMobile) {
mobileIfaces.add(iface);
}
+ if (isWifi) {
+ wifiIfaces.add(iface);
+ }
mStatsFactory.noteStackedIface(iface, baseIface);
}
@@ -1406,11 +1543,16 @@
}
mMobileIfaces = mobileIfaces.toArray(new String[0]);
+ mWifiIfaces = wifiIfaces.toArray(new String[0]);
// TODO (b/192758557): Remove debug log.
if (CollectionUtils.contains(mMobileIfaces, null)) {
throw new NullPointerException(
"null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
}
+ if (CollectionUtils.contains(mWifiIfaces, null)) {
+ throw new NullPointerException(
+ "null element in mWifiIfaces: " + Arrays.toString(mWifiIfaces));
+ }
}
private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
@@ -1428,11 +1570,11 @@
}
/**
- * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
+ * For networks with {@code TRANSPORT_CELLULAR}, get ratType that was obtained through
* {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
* transport types do not actually fill this value.
*/
- private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
+ private int getRatTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
return 0;
}
@@ -1663,7 +1805,10 @@
// Clear kernel stats associated with UID
for (int uid : uids) {
- resetKernelUidStats(uid);
+ final int ret = mDeps.getTagStatsDeleter().deleteTagData(uid);
+ if (ret < 0) {
+ Log.w(TAG, "problem clearing counters for uid " + uid + ": " + Os.strerror(-ret));
+ }
}
}
@@ -2120,7 +2265,7 @@
public void notifyWarningOrLimitReached() {
Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
BinderUtils.withCleanCallingIdentity(() ->
- mNetworkPolicyManager.onStatsProviderWarningOrLimitReached());
+ mNetworkPolicyManager.notifyStatsProviderWarningOrLimitReached());
}
@Override
@@ -2179,24 +2324,11 @@
* {@link android.provider.Settings.Global}.
*/
private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
- private final ContentResolver mResolver;
-
- public DefaultNetworkStatsSettings(Context context) {
- mResolver = Objects.requireNonNull(context.getContentResolver());
- // TODO: adjust these timings for production builds
- }
-
- private long getGlobalLong(String name, long def) {
- return Settings.Global.getLong(mResolver, name, def);
- }
- private boolean getGlobalBoolean(String name, boolean def) {
- final int defInt = def ? 1 : 0;
- return Settings.Global.getInt(mResolver, name, defInt) != 0;
- }
+ DefaultNetworkStatsSettings() {}
@Override
public long getPollInterval() {
- return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
+ return 30 * MINUTE_IN_MILLIS;
}
@Override
public long getPollDelay() {
@@ -2204,25 +2336,23 @@
}
@Override
public long getGlobalAlertBytes(long def) {
- return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
+ return def;
}
@Override
public boolean getSampleEnabled() {
- return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
+ return true;
}
@Override
public boolean getAugmentEnabled() {
- return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
+ return true;
}
@Override
public boolean getCombineSubtypeEnabled() {
- return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false);
+ return false;
}
@Override
public Config getDevConfig() {
- return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
- getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
- getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
+ return new Config(HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
}
@Override
public Config getXtConfig() {
@@ -2230,35 +2360,39 @@
}
@Override
public Config getUidConfig() {
- return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
- getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
- getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
+ return new Config(2 * HOUR_IN_MILLIS, 15 * DAY_IN_MILLIS, 90 * DAY_IN_MILLIS);
}
@Override
public Config getUidTagConfig() {
- return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
- getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
- getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
+ return new Config(2 * HOUR_IN_MILLIS, 5 * DAY_IN_MILLIS, 15 * DAY_IN_MILLIS);
}
@Override
public long getDevPersistBytes(long def) {
- return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
+ return def;
}
@Override
public long getXtPersistBytes(long def) {
- return getDevPersistBytes(def);
+ return def;
}
@Override
public long getUidPersistBytes(long def) {
- return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
+ return def;
}
@Override
public long getUidTagPersistBytes(long def) {
- return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
+ return def;
}
}
private static native long nativeGetTotalStat(int type);
private static native long nativeGetIfaceStat(String iface, int type);
private static native long nativeGetUidStat(int uid, int type);
+
+ // TODO: use BpfNetMaps to delete tag data and remove this.
+ @VisibleForTesting
+ interface TagStatsDeleter {
+ int deleteTagData(int uid);
+ }
+
+ private static native int nativeDeleteTagData(int uid);
}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index 4875f1c..5bba0b1 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -16,15 +16,14 @@
package com.android.server.net;
-import static android.net.NetworkTemplate.NETWORK_TYPE_5G_NSA;
-import static android.net.NetworkTemplate.getCollapsedRatType;
+import static android.app.usage.NetworkStatsManager.NETWORK_TYPE_5G_NSA;
+import static android.app.usage.NetworkStatsManager.getCollapsedRatType;
import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED;
import static android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
import android.annotation.NonNull;
import android.content.Context;
-import android.telephony.Annotation;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyDisplayInfo;
@@ -57,10 +56,9 @@
*
* @param subscriberId IMSI of the subscription.
* @param collapsedRatType collapsed RAT type.
- * @see android.net.NetworkTemplate#getCollapsedRatType(int).
+ * @see android.app.usage.NetworkStatsManager#getCollapsedRatType(int).
*/
- void onCollapsedRatTypeChanged(@NonNull String subscriberId,
- @Annotation.NetworkType int collapsedRatType);
+ void onCollapsedRatTypeChanged(@NonNull String subscriberId, int collapsedRatType);
}
private final Delegate mDelegate;
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
new file mode 100644
index 0000000..ea8d8363
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapKey.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Key for both stats maps.
+ */
+public class StatsMapKey extends Struct {
+ @Field(order = 0, type = Type.U32)
+ public final long uid;
+
+ @Field(order = 1, type = Type.U32)
+ public final long tag;
+
+ @Field(order = 2, type = Type.U32)
+ public final long counterSet;
+
+ @Field(order = 3, type = Type.U32)
+ public final long ifaceIndex;
+
+ public StatsMapKey(final long uid, final long tag, final long counterSet,
+ final long ifaceIndex) {
+ this.uid = uid;
+ this.tag = tag;
+ this.counterSet = counterSet;
+ this.ifaceIndex = ifaceIndex;
+ }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
new file mode 100644
index 0000000..48f26ce
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/StatsMapValue.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Value used for both stats maps and uid stats map.
+ */
+public class StatsMapValue extends Struct {
+ @Field(order = 0, type = Type.U63)
+ public final long rxPackets;
+
+ @Field(order = 1, type = Type.U63)
+ public final long rxBytes;
+
+ @Field(order = 2, type = Type.U63)
+ public final long txPackets;
+
+ @Field(order = 3, type = Type.U63)
+ public final long txBytes;
+
+ public StatsMapValue(final long rxPackets, final long rxBytes, final long txPackets,
+ final long txBytes) {
+ this.rxPackets = rxPackets;
+ this.rxBytes = rxBytes;
+ this.txPackets = txPackets;
+ this.txBytes = txBytes;
+ }
+}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
new file mode 100644
index 0000000..2849f94
--- /dev/null
+++ b/packages/ConnectivityT/service/src/com/android/server/net/UidStatsMapKey.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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.net;
+
+import com.android.net.module.util.Struct;
+import com.android.net.module.util.Struct.Field;
+import com.android.net.module.util.Struct.Type;
+
+/**
+ * Key for uid stats map.
+ */
+public class UidStatsMapKey extends Struct {
+ @Field(order = 0, type = Type.U32)
+ public final long uid;
+
+ public UidStatsMapKey(final long uid) {
+ this.uid = uid;
+ }
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index a3eb0ecc..ce58ff6 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -236,7 +236,8 @@
root.flags |= Root.FLAG_REMOVABLE_USB;
}
- if (volume.getType() != VolumeInfo.TYPE_EMULATED) {
+ if (volume.getType() != VolumeInfo.TYPE_EMULATED
+ && volume.getType() != VolumeInfo.TYPE_STUB) {
root.flags |= Root.FLAG_SUPPORTS_EJECT;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
index f5aa652..b4e84dd 100644
--- a/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
+++ b/packages/SettingsLib/src/com/android/settingslib/NetworkPolicyEditor.java
@@ -27,9 +27,7 @@
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
-import android.net.wifi.WifiInfo;
import android.os.AsyncTask;
-import android.text.TextUtils;
import android.util.RecurrenceRule;
import com.google.android.collect.Lists;
@@ -124,7 +122,7 @@
if (policy != null) {
return policy;
} else {
- return getPolicy(buildUnquotedNetworkTemplate(template));
+ return getPolicy(template);
}
}
@@ -207,21 +205,4 @@
policy.clearSnooze();
writeAsync();
}
-
- /**
- * Build a revised {@link NetworkTemplate} that matches the same rule, but
- * with an unquoted {@link NetworkTemplate#getNetworkId()}. Used to work
- * around legacy bugs.
- */
- private static NetworkTemplate buildUnquotedNetworkTemplate(NetworkTemplate template) {
- if (template == null) return null;
- final String networkId = template.getNetworkId();
- final String strippedNetworkId = WifiInfo.sanitizeSsid(networkId);
- if (!TextUtils.equals(strippedNetworkId, networkId)) {
- return new NetworkTemplate(
- template.getMatchRule(), template.getSubscriberId(), strippedNetworkId);
- } else {
- return null;
- }
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 99e3160..df19c67 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -173,8 +173,10 @@
}
public BluetoothDevice getActiveDevice() {
- if (mService == null) return null;
- return mService.getActiveDevice();
+ if (mBluetoothAdapter == null) return null;
+ final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+ .getActiveDevices(BluetoothProfile.A2DP);
+ return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
}
@Override
@@ -221,7 +223,7 @@
}
public boolean supportsHighQualityAudio(BluetoothDevice device) {
- BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
if (bluetoothDevice == null) {
return false;
}
@@ -234,7 +236,7 @@
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public boolean isHighQualityAudioEnabled(BluetoothDevice device) {
- BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
if (bluetoothDevice == null) {
return false;
}
@@ -260,7 +262,7 @@
}
public void setHighQualityAudioEnabled(BluetoothDevice device, boolean enabled) {
- BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
if (bluetoothDevice == null) {
return;
}
@@ -286,7 +288,7 @@
*/
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
public String getHighQualityAudioOptionLabel(BluetoothDevice device) {
- BluetoothDevice bluetoothDevice = (device != null) ? device : mService.getActiveDevice();
+ BluetoothDevice bluetoothDevice = (device != null) ? device : getActiveDevice();
int unknownCodecId = R.string.bluetooth_profile_a2dp_high_quality_unknown_codec;
if (bluetoothDevice == null || !supportsHighQualityAudio(device)
|| getConnectionStatus(device) != BluetoothProfile.STATE_CONNECTED) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index ddee433..233e798 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -500,6 +500,17 @@
}
/**
+ * Get identity address from remote device
+ * @return {@link BluetoothDevice#getIdentityAddress()} if
+ * {@link BluetoothDevice#getIdentityAddress()} is not null otherwise return
+ * {@link BluetoothDevice#getAddress()}
+ */
+ public String getIdentityAddress() {
+ final String identityAddress = mDevice.getIdentityAddress();
+ return TextUtils.isEmpty(identityAddress) ? getAddress() : identityAddress;
+ }
+
+ /**
* Get name from remote device
* @return {@link BluetoothDevice#getAlias()} if
* {@link BluetoothDevice#getAlias()} is not null otherwise return
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
index 9dd329e..b44d914 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HeadsetProfile.java
@@ -132,10 +132,12 @@
}
public BluetoothDevice getActiveDevice() {
- if (mService == null) {
+ if (mBluetoothAdapter == null) {
return null;
}
- return mService.getActiveDevice();
+ final List<BluetoothDevice> activeDevices = mBluetoothAdapter
+ .getActiveDevices(BluetoothProfile.HEADSET);
+ return (activeDevices.size() > 0) ? activeDevices.get(0) : null;
}
public boolean isAudioOn() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
index a1fba4a..ff1368a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidProfile.java
@@ -168,8 +168,10 @@
}
public List<BluetoothDevice> getActiveDevices() {
- if (mService == null) return new ArrayList<>();
- return mService.getActiveDevices();
+ if (mBluetoothAdapter == null) {
+ return new ArrayList<>();
+ }
+ return mBluetoothAdapter.getActiveDevices(BluetoothProfile.HEARING_AID);
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
index 209507a..db6d41e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LeAudioProfile.java
@@ -21,12 +21,12 @@
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED;
import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
-import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudio;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -177,10 +177,10 @@
}
public List<BluetoothDevice> getActiveDevices() {
- if (mService == null) {
+ if (mBluetoothAdapter == null) {
return new ArrayList<>();
}
- return mService.getActiveDevices();
+ return mBluetoothAdapter.getActiveDevices(BluetoothProfile.LE_AUDIO);
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
new file mode 100644
index 0000000..ab9b5dc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/OWNERS
@@ -0,0 +1,4 @@
+# Default reviewers for this and subdirectories.
+bonianchen@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java
index e30aac5..a69c59c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartData.java
@@ -16,12 +16,18 @@
package com.android.settingslib.net;
-import android.net.NetworkStatsHistory;
+import android.app.usage.NetworkStats;
+
+import java.util.List;
public class ChartData {
- public NetworkStatsHistory network;
+ // Collect the data usage history of the network from the given {@link NetworkTemplate}.
+ public List<NetworkStats.Bucket> network;
- public NetworkStatsHistory detail;
- public NetworkStatsHistory detailDefault;
- public NetworkStatsHistory detailForeground;
+ // Collect the detail datausage history (foreground + Background).
+ public List<NetworkStats.Bucket> detail;
+ // Collect background datausage history.
+ public List<NetworkStats.Bucket> detailDefault;
+ // Collect foreground datausage history.
+ public List<NetworkStats.Bucket> detailForeground;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
index 60d22a0..573922f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/ChartDataLoader.java
@@ -19,20 +19,21 @@
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
-import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
-import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
-import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import android.annotation.NonNull;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
import android.content.AsyncTaskLoader;
import android.content.Context;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.os.RemoteException;
import com.android.settingslib.AppItem;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Framework loader is deprecated, use the compat version instead.
*
@@ -42,26 +43,20 @@
public class ChartDataLoader extends AsyncTaskLoader<ChartData> {
private static final String KEY_TEMPLATE = "template";
private static final String KEY_APP = "app";
- private static final String KEY_FIELDS = "fields";
- private final INetworkStatsSession mSession;
+ private final NetworkStatsManager mNetworkStatsManager;
private final Bundle mArgs;
public static Bundle buildArgs(NetworkTemplate template, AppItem app) {
- return buildArgs(template, app, FIELD_RX_BYTES | FIELD_TX_BYTES);
- }
-
- public static Bundle buildArgs(NetworkTemplate template, AppItem app, int fields) {
final Bundle args = new Bundle();
args.putParcelable(KEY_TEMPLATE, template);
args.putParcelable(KEY_APP, app);
- args.putInt(KEY_FIELDS, fields);
return args;
}
- public ChartDataLoader(Context context, INetworkStatsSession session, Bundle args) {
+ public ChartDataLoader(Context context, NetworkStatsManager statsManager, Bundle args) {
super(context);
- mSession = session;
+ mNetworkStatsManager = statsManager;
mArgs = args;
}
@@ -75,10 +70,9 @@
public ChartData loadInBackground() {
final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
final AppItem app = mArgs.getParcelable(KEY_APP);
- final int fields = mArgs.getInt(KEY_FIELDS);
try {
- return loadInBackground(template, app, fields);
+ return loadInBackground(template, app);
} catch (RemoteException e) {
// since we can't do much without history, and we don't want to
// leave with half-baked UI, we bail hard.
@@ -86,10 +80,22 @@
}
}
- private ChartData loadInBackground(NetworkTemplate template, AppItem app, int fields)
+ @NonNull
+ private List<NetworkStats.Bucket> convertToBuckets(@NonNull NetworkStats stats) {
+ final List<NetworkStats.Bucket> ret = new ArrayList<>();
+ while (stats.hasNextBucket()) {
+ final NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+ stats.getNextBucket(bucket);
+ ret.add(bucket);
+ }
+ return ret;
+ }
+
+ private ChartData loadInBackground(NetworkTemplate template, AppItem app)
throws RemoteException {
final ChartData data = new ChartData();
- data.network = mSession.getHistoryForNetwork(template, fields);
+ data.network = convertToBuckets(mNetworkStatsManager.queryDetailsForDevice(
+ template, Long.MIN_VALUE, Long.MAX_VALUE));
if (app != null) {
// load stats for current uid and template
@@ -103,13 +109,13 @@
}
if (size > 0) {
- data.detail = new NetworkStatsHistory(data.detailForeground.getBucketDuration());
- data.detail.recordEntireHistory(data.detailDefault);
- data.detail.recordEntireHistory(data.detailForeground);
+ data.detail = new ArrayList<>();
+ data.detail.addAll(data.detailDefault);
+ data.detail.addAll(data.detailForeground);
} else {
- data.detailDefault = new NetworkStatsHistory(HOUR_IN_MILLIS);
- data.detailForeground = new NetworkStatsHistory(HOUR_IN_MILLIS);
- data.detail = new NetworkStatsHistory(HOUR_IN_MILLIS);
+ data.detailDefault = new ArrayList<>();
+ data.detailForeground = new ArrayList<>();
+ data.detail = new ArrayList<>();
}
}
@@ -129,17 +135,17 @@
}
/**
- * Collect {@link NetworkStatsHistory} for the requested UID, combining with
- * an existing {@link NetworkStatsHistory} if provided.
+ * Collect {@link List<NetworkStats.Bucket>} for the requested UID, combining with
+ * an existing {@link List<NetworkStats.Bucket>} if provided.
*/
- private NetworkStatsHistory collectHistoryForUid(
- NetworkTemplate template, int uid, int set, NetworkStatsHistory existing)
- throws RemoteException {
- final NetworkStatsHistory history = mSession.getHistoryForUid(
- template, uid, set, TAG_NONE, FIELD_RX_BYTES | FIELD_TX_BYTES);
+ private List<NetworkStats.Bucket> collectHistoryForUid(
+ NetworkTemplate template, int uid, int set, List<NetworkStats.Bucket> existing) {
+ final List<NetworkStats.Bucket> history = convertToBuckets(
+ mNetworkStatsManager.queryDetailsForUidTagState(template,
+ Long.MIN_VALUE, Long.MAX_VALUE, uid, TAG_NONE, set));
if (existing != null) {
- existing.recordEntireHistory(history);
+ existing.addAll(history);
return existing;
} else {
return history;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
index cff45c6..30c6645 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java
@@ -16,7 +16,6 @@
package com.android.settingslib.net;
-import static android.net.TrafficStats.MB_IN_BYTES;
import static android.telephony.TelephonyManager.SIM_STATE_READY;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
@@ -49,6 +48,7 @@
private static final StringBuilder PERIOD_BUILDER = new StringBuilder(50);
private static final java.util.Formatter PERIOD_FORMATTER = new java.util.Formatter(
PERIOD_BUILDER, Locale.getDefault());
+ private static final long MB_IN_BYTES = 1024 * 1024;
private final Context mContext;
private final NetworkPolicyManager mPolicyManager;
@@ -237,10 +237,8 @@
final int matchRule = networkTemplate.getMatchRule();
switch (matchRule) {
case NetworkTemplate.MATCH_MOBILE:
- case NetworkTemplate.MATCH_MOBILE_WILDCARD:
return ConnectivityManager.TYPE_MOBILE;
case NetworkTemplate.MATCH_WIFI:
- case NetworkTemplate.MATCH_WIFI_WILDCARD:
return ConnectivityManager.TYPE_WIFI;
case NetworkTemplate.MATCH_ETHERNET:
return ConnectivityManager.TYPE_ETHERNET;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index afd44d5..386a47a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -63,14 +63,32 @@
private static NetworkTemplate getNormalizedMobileTemplate(
TelephonyManager telephonyManager, int subId) {
final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId);
- final String[] mergedSubscriberIds = telephonyManager
- .createForSubscriptionId(subId).getMergedImsisFromGroup();
+ final Set<String> mergedSubscriberIds = Set.of(telephonyManager
+ .createForSubscriptionId(subId).getMergedImsisFromGroup());
if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
Log.i(TAG, "mergedSubscriberIds is null.");
return mobileTemplate;
}
- return NetworkTemplate.normalize(mobileTemplate, mergedSubscriberIds);
+ return normalizeMobileTemplate(mobileTemplate, mergedSubscriberIds);
+ }
+
+ private static NetworkTemplate normalizeMobileTemplate(
+ NetworkTemplate template, Set<String> mergedSet) {
+ if (template.getSubscriberIds().isEmpty()) return template;
+ // The input template should have at most 1 subscriberId.
+ final String subscriberId = template.getSubscriberIds().iterator().next();
+
+ if (mergedSet.contains(subscriberId)) {
+ // Requested template subscriber is part of the merge group; return
+ // a template that matches all merged subscribers.
+ return new NetworkTemplate.Builder(template.getMatchRule())
+ .setSubscriberIds(mergedSet)
+ .setWifiNetworkKeys(template.getWifiNetworkKeys())
+ .setMeteredness(NetworkStats.METERED_YES).build();
+ }
+
+ return template;
}
private static NetworkTemplate getMobileTemplateForSubId(
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
index 43c05b8..504390c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataForUidLoader.java
@@ -53,8 +53,9 @@
long totalUsage = 0L;
long totalForeground = 0L;
for (int uid : mUids) {
- final NetworkStats stats = mNetworkStatsManager.queryDetailsForUid(
- mNetworkTemplate, start, end, uid);
+ final NetworkStats stats = mNetworkStatsManager.queryDetailsForUidTagState(
+ mNetworkTemplate, start, end, uid, NetworkStats.Bucket.TAG_NONE,
+ NetworkStats.Bucket.STATE_ALL);
final long usage = getTotalUsage(stats);
if (usage > 0L) {
totalUsage += usage;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
index 3e95b01..5e9ac5a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/NetworkCycleDataLoader.java
@@ -16,23 +16,16 @@
package com.android.settingslib.net;
-import static android.net.NetworkStatsHistory.FIELD_RX_BYTES;
-import static android.net.NetworkStatsHistory.FIELD_TX_BYTES;
-
+import android.annotation.NonNull;
import android.app.usage.NetworkStats;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.text.format.DateUtils;
import android.util.Pair;
+import android.util.Range;
import androidx.annotation.VisibleForTesting;
import androidx.loader.content.AsyncTaskLoader;
@@ -52,8 +45,6 @@
protected final NetworkTemplate mNetworkTemplate;
private final NetworkPolicy mPolicy;
private final ArrayList<Long> mCycles;
- @VisibleForTesting
- final INetworkStatsService mNetworkStatsService;
protected NetworkCycleDataLoader(Builder<?> builder) {
super(builder.mContext);
@@ -61,8 +52,6 @@
mCycles = builder.mCycles;
mNetworkStatsManager = (NetworkStatsManager)
builder.mContext.getSystemService(Context.NETWORK_STATS_SERVICE);
- mNetworkStatsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
final NetworkPolicyEditor policyEditor =
new NetworkPolicyEditor(NetworkPolicyManager.from(builder.mContext));
policyEditor.read();
@@ -112,23 +101,20 @@
@VisibleForTesting
void loadFourWeeksData() {
+ if (mNetworkTemplate == null) return;
+ final NetworkStats stats = mNetworkStatsManager.queryDetailsForDevice(
+ mNetworkTemplate, Long.MIN_VALUE, Long.MAX_VALUE);
try {
- final INetworkStatsSession networkSession = mNetworkStatsService.openSession();
- final NetworkStatsHistory networkHistory = networkSession.getHistoryForNetwork(
- mNetworkTemplate, FIELD_RX_BYTES | FIELD_TX_BYTES);
- final long historyStart = networkHistory.getStart();
- final long historyEnd = networkHistory.getEnd();
+ final Range<Long> historyTimeRange = getTimeRangeOf(stats);
- long cycleEnd = historyEnd;
- while (cycleEnd > historyStart) {
+ long cycleEnd = historyTimeRange.getUpper();
+ while (cycleEnd > historyTimeRange.getLower()) {
final long cycleStart = cycleEnd - (DateUtils.WEEK_IN_MILLIS * 4);
recordUsage(cycleStart, cycleEnd);
cycleEnd = cycleStart;
}
-
- TrafficStats.closeQuietly(networkSession);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
+ } catch (IllegalArgumentException e) {
+ // Empty history, ignore.
}
}
@@ -169,6 +155,32 @@
return bytes;
}
+ @NonNull
+ @VisibleForTesting
+ Range getTimeRangeOf(@NonNull NetworkStats stats) {
+ long start = Long.MAX_VALUE;
+ long end = Long.MIN_VALUE;
+ while (hasNextBucket(stats)) {
+ final NetworkStats.Bucket bucket = getNextBucket(stats);
+ start = Math.min(start, bucket.getStartTimeStamp());
+ end = Math.max(end, bucket.getEndTimeStamp());
+ }
+ return new Range(start, end);
+ }
+
+ @VisibleForTesting
+ boolean hasNextBucket(@NonNull NetworkStats stats) {
+ return stats.hasNextBucket();
+ }
+
+ @NonNull
+ @VisibleForTesting
+ NetworkStats.Bucket getNextBucket(@NonNull NetworkStats stats) {
+ NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+ stats.getNextBucket(bucket);
+ return bucket;
+ }
+
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
public ArrayList<Long> getCycles() {
return mCycles;
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/OWNERS b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
new file mode 100644
index 0000000..ab9b5dc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/OWNERS
@@ -0,0 +1,4 @@
+# Default reviewers for this and subdirectories.
+bonianchen@google.com
+
+# Emergency approvers in case the above are not available
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
index 649aeff..8da6032 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SummaryForAllUidLoader.java
@@ -16,13 +16,12 @@
package com.android.settingslib.net;
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
import android.content.AsyncTaskLoader;
import android.content.Context;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStats;
import android.net.NetworkTemplate;
import android.os.Bundle;
-import android.os.RemoteException;
/**
* Framework loader is deprecated, use the compat version instead.
@@ -35,7 +34,7 @@
private static final String KEY_START = "start";
private static final String KEY_END = "end";
- private final INetworkStatsSession mSession;
+ private final NetworkStatsManager mNetworkStatsManager;
private final Bundle mArgs;
public static Bundle buildArgs(NetworkTemplate template, long start, long end) {
@@ -46,9 +45,9 @@
return args;
}
- public SummaryForAllUidLoader(Context context, INetworkStatsSession session, Bundle args) {
+ public SummaryForAllUidLoader(Context context, Bundle args) {
super(context);
- mSession = session;
+ mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
mArgs = args;
}
@@ -63,12 +62,7 @@
final NetworkTemplate template = mArgs.getParcelable(KEY_TEMPLATE);
final long start = mArgs.getLong(KEY_START);
final long end = mArgs.getLong(KEY_END);
-
- try {
- return mSession.getSummaryForAllUid(template, start, end, false);
- } catch (RemoteException e) {
- return null;
- }
+ return mNetworkStatsManager.querySummary(template, start, end);
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
index 02326ea..623eb33 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/UidDetailProvider.java
@@ -17,6 +17,7 @@
package com.android.settingslib.net;
import android.app.AppGlobals;
+import android.app.usage.NetworkStats;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -116,13 +117,13 @@
detail.label = res.getString(R.string.process_kernel_label);
detail.icon = pm.getDefaultActivityIcon();
return detail;
- case TrafficStats.UID_REMOVED:
+ case NetworkStats.Bucket.UID_REMOVED:
detail.label = res.getString(UserManager.supportsMultipleUsers()
? R.string.data_usage_uninstalled_apps_users
: R.string.data_usage_uninstalled_apps);
detail.icon = pm.getDefaultActivityIcon();
return detail;
- case TrafficStats.UID_TETHERING:
+ case NetworkStats.Bucket.UID_TETHERING:
final TetheringManager tm = mContext.getSystemService(TetheringManager.class);
detail.label = res.getString(Utils.getTetheringLabel(tm));
detail.icon = pm.getDefaultActivityIcon();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
index f167721..d7b366e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/A2dpProfileTest.java
@@ -60,6 +60,8 @@
private BluetoothDevice mDevice;
@Mock
private BluetoothA2dp mBluetoothA2dp;
+ @Mock
+ private BluetoothAdapter mBluetoothAdapter;
private BluetoothProfile.ServiceListener mServiceListener;
private A2dpProfile mProfile;
@@ -72,7 +74,8 @@
mProfile = new A2dpProfile(mContext, mDeviceManager, mProfileManager);
mServiceListener = mShadowBluetoothAdapter.getServiceListener();
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, mBluetoothA2dp);
- when(mBluetoothA2dp.getActiveDevice()).thenReturn(mDevice);
+ when(mBluetoothAdapter.getActiveDevices(eq(BluetoothProfile.A2DP)))
+ .thenReturn(Arrays.asList(mDevice));
}
@Test
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
index 5b0f659..2f3da83 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataForUidLoaderTest.java
@@ -16,6 +16,7 @@
package com.android.settingslib.net;
+import static android.app.usage.NetworkStats.Bucket.STATE_ALL;
import static android.app.usage.NetworkStats.Bucket.STATE_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
@@ -83,7 +84,6 @@
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, uid);
verify(mNetworkStatsManager).queryDetailsForUidTagState(
mNetworkTemplate, start, end, uid, TAG_NONE, STATE_FOREGROUND);
}
@@ -116,9 +116,12 @@
mLoader.recordUsage(start, end);
- verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 1);
- verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 2);
- verify(mNetworkStatsManager).queryDetailsForUid(mNetworkTemplate, start, end, 3);
+ verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 1,
+ TAG_NONE, STATE_ALL);
+ verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 2,
+ TAG_NONE, STATE_ALL);
+ verify(mNetworkStatsManager).queryDetailsForUidTagState(mNetworkTemplate, start, end, 3,
+ TAG_NONE, STATE_ALL);
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
index 74b9151..c79440e 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/NetworkCycleDataLoaderTest.java
@@ -16,24 +16,24 @@
package com.android.settingslib.net;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.nullable;
+import static android.app.usage.NetworkStats.Bucket.UID_ALL;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.NonNull;
+import android.app.usage.NetworkStats;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
-import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
-import android.os.RemoteException;
import android.text.format.DateUtils;
import android.util.Range;
@@ -49,6 +49,8 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
@RunWith(RobolectricTestRunner.class)
public class NetworkCycleDataLoaderTest {
@@ -63,8 +65,6 @@
private NetworkPolicy mPolicy;
@Mock
private Iterator<Range<ZonedDateTime>> mIterator;
- @Mock
- private INetworkStatsService mNetworkStatsService;
private NetworkCycleDataTestLoader mLoader;
@@ -132,20 +132,24 @@
verify(mLoader).recordUsage(nowInMs, nowInMs);
}
+ private NetworkStats.Bucket makeMockBucket(int uid, long rxBytes, long txBytes,
+ long start, long end) {
+ NetworkStats.Bucket ret = mock(NetworkStats.Bucket.class);
+ when(ret.getUid()).thenReturn(uid);
+ when(ret.getRxBytes()).thenReturn(rxBytes);
+ when(ret.getTxBytes()).thenReturn(txBytes);
+ when(ret.getStartTimeStamp()).thenReturn(start);
+ when(ret.getEndTimeStamp()).thenReturn(end);
+ return ret;
+ }
+
@Test
- public void loadFourWeeksData_shouldRecordUsageForLast4Weeks() throws RemoteException {
+ public void loadFourWeeksData_shouldRecordUsageForLast4Weeks() {
mLoader = spy(new NetworkCycleDataTestLoader(mContext));
- ReflectionHelpers.setField(mLoader, "mNetworkStatsService", mNetworkStatsService);
- final INetworkStatsSession networkSession = mock(INetworkStatsSession.class);
- when(mNetworkStatsService.openSession()).thenReturn(networkSession);
- final NetworkStatsHistory networkHistory = mock(NetworkStatsHistory.class);
- when(networkSession.getHistoryForNetwork(nullable(NetworkTemplate.class), anyInt()))
- .thenReturn(networkHistory);
final long now = System.currentTimeMillis();
final long fourWeeksAgo = now - (DateUtils.WEEK_IN_MILLIS * 4);
final long twoDaysAgo = now - (DateUtils.DAY_IN_MILLIS * 2);
- when(networkHistory.getStart()).thenReturn(twoDaysAgo);
- when(networkHistory.getEnd()).thenReturn(now);
+ mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, twoDaysAgo, now));
mLoader.loadFourWeeksData();
@@ -173,10 +177,31 @@
verify(mLoader).recordUsage(thirtyDaysAgo, twentyDaysAgo);
}
+ @Test
+ public void getTimeRangeOf() {
+ mLoader = spy(new NetworkCycleDataTestLoader(mContext));
+ // If empty, new Range(MAX_VALUE, MIN_VALUE) will be constructed. Hence, the function
+ // should throw.
+ assertThrows(IllegalArgumentException.class,
+ () -> mLoader.getTimeRangeOf(mock(NetworkStats.class)));
+
+ mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 0, 10));
+ // Feed the function with unused NetworkStats. The actual data injection is
+ // done by addBucket.
+ assertEquals(new Range(0L, 10L), mLoader.getTimeRangeOf(mock(NetworkStats.class)));
+
+ mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 0, 10));
+ mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 30, 40));
+ mLoader.addBucket(makeMockBucket(UID_ALL, 123, 456, 10, 25));
+ assertEquals(new Range(0L, 40L), mLoader.getTimeRangeOf(mock(NetworkStats.class)));
+ }
+
public class NetworkCycleDataTestLoader extends NetworkCycleDataLoader<List<NetworkCycleData>> {
+ private final Queue<NetworkStats.Bucket> mMockedBuckets = new LinkedBlockingQueue<>();
private NetworkCycleDataTestLoader(Context context) {
- super(NetworkCycleDataLoader.builder(mContext));
+ super(NetworkCycleDataLoader.builder(mContext)
+ .setNetworkTemplate(mock(NetworkTemplate.class)));
mContext = context;
}
@@ -188,5 +213,19 @@
List<NetworkCycleData> getCycleUsage() {
return null;
}
+
+ public void addBucket(NetworkStats.Bucket bucket) {
+ mMockedBuckets.add(bucket);
+ }
+
+ @Override
+ public boolean hasNextBucket(@NonNull NetworkStats unused) {
+ return !mMockedBuckets.isEmpty();
+ }
+
+ @Override
+ public NetworkStats.Bucket getNextBucket(@NonNull NetworkStats unused) {
+ return mMockedBuckets.remove();
+ }
}
}
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 5b9b74a..074d85c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -190,6 +190,9 @@
<uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS" />
<uses-permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS" />
+ <!-- Permission required for processes that don't own the focused window to switch
+ touch mode state -->
+ <uses-permission android:name="android.permission.MODIFY_TOUCH_MODE_STATE" />
<!-- Permission required to test onPermissionsChangedListener -->
<uses-permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS" />
<uses-permission android:name="android.permission.SET_KEYBOARD_LAYOUT" />
@@ -245,6 +248,7 @@
<uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
<uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
<uses-permission android:name="android.permission.MANAGE_SMARTSPACE" />
+ <uses-permission android:name="android.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION" />
<uses-permission android:name="android.permission.MANAGE_UI_TRANSLATION" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
@@ -503,6 +507,8 @@
<!-- Permission needed for CTS test - WifiManagerTest -->
<uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
<uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+ <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" />
+ <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
<!-- Permission required for CTS tests to enable/disable rate limiting toasts. -->
<uses-permission android:name="android.permission.MANAGE_TOAST_RATE_LIMITING" />
@@ -527,6 +533,11 @@
<!-- Permission required for CTS test - PeopleManagerTest -->
<uses-permission android:name="android.permission.READ_PEOPLE_DATA" />
+ <!-- Permissions required for CTS test - TrustTestCases -->
+ <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" />
+ <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+ <uses-permission android:name="android.permission.TRUST_LISTENER" />
+
<!-- Permission required for CTS test - CtsGameManagerTestCases -->
<uses-permission android:name="android.permission.MANAGE_GAME_MODE" />
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index e1da744..8323e32 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -11,8 +11,10 @@
awickham@google.com
beverlyt@google.com
brockman@google.com
+brzezinski@google.com
brycelee@google.com
ccassidy@google.com
+chrisgollner@google.com
cinek@google.com
cwren@google.com
dupin@google.com
@@ -43,6 +45,8 @@
mrcasey@google.com
mrenouf@google.com
nesciosquid@google.com
+nickchameyev@google.com
+nicomazz@google.com
ogunwale@google.com
peanutbutter@google.com
pinyaoting@google.com
@@ -67,6 +71,7 @@
yurilin@google.com
xuqiu@google.com
zakcohen@google.com
+jernej@google.com
#Android Auto
hseog@google.com
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index d3d6e03..6f30ac3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,6 +18,7 @@
import android.annotation.MainThread
import android.app.Dialog
+import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@@ -88,7 +89,7 @@
bouncerOrRun(createAction(cvh.cws.ci.controlId, {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
if (cvh.usePanel()) {
- showDetail(cvh, control.getAppIntent().getIntent())
+ showDetail(cvh, control.getAppIntent())
} else {
cvh.action(CommandAction(templateId))
}
@@ -116,7 +117,7 @@
// Long press snould only be called when there is valid control state, otherwise ignore
cvh.cws.control?.let {
cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
- showDetail(cvh, it.getAppIntent().getIntent())
+ showDetail(cvh, it.getAppIntent())
}
}, false /* blockable */))
}
@@ -167,10 +168,10 @@
bgExecutor.execute { vibrator.vibrate(effect) }
}
- private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
+ private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
bgExecutor.execute {
val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
- intent,
+ pendingIntent.getIntent(),
PackageManager.MATCH_DEFAULT_ONLY
)
@@ -178,7 +179,7 @@
// make sure the intent is valid before attempting to open the dialog
if (activities.isNotEmpty() && taskViewFactory.isPresent) {
taskViewFactory.get().create(context, uiExecutor, {
- dialog = DetailDialog(activityContext, it, intent, cvh).also {
+ dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also {
it.setOnDismissListener { _ -> dialog = null }
it.show()
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 8a47a36..4758ab0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -43,7 +43,7 @@
class DetailDialog(
val activityContext: Context?,
val taskView: TaskView,
- val intent: Intent,
+ val pendingIntent: PendingIntent,
val cvh: ControlViewHolder
) : Dialog(
activityContext ?: cvh.context,
@@ -59,6 +59,14 @@
var detailTaskId = INVALID_TASK_ID
+ private val fillInIntent = Intent().apply {
+ putExtra(EXTRA_USE_PANEL, true)
+
+ // Apply flags to make behaviour match documentLaunchMode=always.
+ addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+ addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+ }
+
fun removeDetailTask() {
if (detailTaskId == INVALID_TASK_ID) return
ActivityTaskManager.getInstance().removeTask(detailTaskId)
@@ -67,13 +75,6 @@
val stateCallback = object : TaskView.Listener {
override fun onInitialized() {
- val launchIntent = Intent(intent)
- launchIntent.putExtra(EXTRA_USE_PANEL, true)
-
- // Apply flags to make behaviour match documentLaunchMode=always.
- launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
- launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-
val options = activityContext?.let {
ActivityOptions.makeCustomAnimation(
it,
@@ -82,9 +83,8 @@
)
} ?: ActivityOptions.makeBasic()
taskView.startActivity(
- PendingIntent.getActivity(context, 0, launchIntent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
- null /* fillInIntent */,
+ pendingIntent,
+ fillInIntent,
options,
getTaskViewBounds()
)
@@ -97,6 +97,9 @@
override fun onTaskCreated(taskId: Int, name: ComponentName?) {
detailTaskId = taskId
+ requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
+ setAlpha(1f)
+ }
}
override fun onReleased() {
@@ -121,6 +124,7 @@
requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
addView(taskView)
+ setAlpha(0f)
}
requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -134,7 +138,7 @@
removeDetailTask()
dismiss()
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
- v.context.startActivity(intent)
+ pendingIntent.send()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
index c50365f..71c5fad 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
@@ -15,7 +15,8 @@
class SensorUseDialog(
context: Context,
val sensor: Int,
- val clickListener: DialogInterface.OnClickListener
+ val clickListener: DialogInterface.OnClickListener,
+ val dismissListener: DialogInterface.OnDismissListener
) : SystemUIDialog(context) {
// TODO move to onCreate (b/200815309)
@@ -69,6 +70,8 @@
context.getString(com.android.internal.R.string
.cancel), clickListener)
+ setOnDismissListener(dismissListener)
+
setCancelable(false)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
index b0071d9..dae375a 100644
--- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
@@ -50,7 +50,7 @@
private val keyguardStateController: KeyguardStateController,
private val keyguardDismissUtil: KeyguardDismissUtil,
@Background private val bgHandler: Handler
-) : Activity(), DialogInterface.OnClickListener {
+) : Activity(), DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
companion object {
private val LOG_TAG = SensorUseStartedActivity::class.java.simpleName
@@ -120,7 +120,7 @@
}
}
- mDialog = SensorUseDialog(this, sensor, this)
+ mDialog = SensorUseDialog(this, sensor, this, this)
mDialog!!.show()
}
@@ -212,4 +212,8 @@
.suppressSensorPrivacyReminders(sensor, suppressed)
}
}
+
+ override fun onDismiss(dialog: DialogInterface?) {
+ finish()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
new file mode 100644
index 0000000..87b9172
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.systemui.controls.ui
+
+import android.app.PendingIntent
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.wm.shell.TaskView
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class DetailDialogTest : SysuiTestCase() {
+
+ @Mock
+ private lateinit var taskView: TaskView
+ @Mock
+ private lateinit var controlViewHolder: ControlViewHolder
+ @Mock
+ private lateinit var pendingIntent: PendingIntent
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun testPendingIntentIsUnModified() {
+ // GIVEN the dialog is created with a PendingIntent
+ val dialog = createDialog(pendingIntent)
+
+ // WHEN the TaskView is initialized
+ dialog.stateCallback.onInitialized()
+
+ // THEN the PendingIntent used to call startActivity is unmodified by systemui
+ verify(taskView).startActivity(eq(pendingIntent), any(), any(), any())
+ }
+
+ private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
+ return DetailDialog(
+ mContext,
+ taskView,
+ pendingIntent,
+ controlViewHolder
+ )
+ }
+}
diff --git a/services/Android.bp b/services/Android.bp
index 8fb9ae8..8947393 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -176,6 +176,10 @@
name: "libandroid_servers",
defaults: ["libservices.core-libs"],
whole_static_libs: ["libservices.core"],
+ required: [
+ // TODO: remove after NetworkStatsService is moved to the mainline module.
+ "libcom_android_net_module_util_jni",
+ ],
}
platform_compat_config {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 960f7ca..9d19008 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -166,6 +166,9 @@
"overlayable_policy_aidl-java",
"SurfaceFlingerProperties",
"com.android.sysprop.watchdog",
+ // This is used for services.connectivity-tiramisu-sources.
+ // TODO: delete when NetworkStatsService is moved to the mainline module.
+ "net-utils-device-common-bpf",
],
javac_shard_size: 50,
}
diff --git a/services/core/java/android/app/usage/OWNERS b/services/core/java/android/app/usage/OWNERS
new file mode 100644
index 0000000..3a55514
--- /dev/null
+++ b/services/core/java/android/app/usage/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/base:/core/java/android/app/usage/OWNERS
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index 48f5b51..a0575cf 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -484,7 +484,9 @@
HashMap<String, Long> timestamps = readTimestamps();
try {
if (proto) {
- db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0);
+ if (recordFileTimestamp(tombstone, timestamps)) {
+ db.addFile(TAG_TOMBSTONE_PROTO, tombstone, 0);
+ }
} else {
final String headers = getBootHeadersToLogAndUpdate();
addFileToDropBox(db, timestamps, headers, tombstone.getPath(), LOG_SIZE,
@@ -526,16 +528,10 @@
if (db == null || !db.isTagEnabled(tag)) return; // Logging disabled
File file = new File(filename);
- long fileTime = file.lastModified();
- if (fileTime <= 0) return; // File does not exist
-
- if (timestamps.containsKey(filename) && timestamps.get(filename) == fileTime) {
- return; // Already logged this particular file
+ if (!recordFileTimestamp(file, timestamps)) {
+ return;
}
- timestamps.put(filename, fileTime);
-
-
String fileContents = FileUtils.readTextFile(file, maxSize, TAG_TRUNCATED);
String text = headers + fileContents + footers;
// Create an additional report for system server native crashes, with a special tag.
@@ -548,6 +544,19 @@
addTextToDropBox(db, tag, text, filename, maxSize);
}
+ private static boolean recordFileTimestamp(File file, HashMap<String, Long> timestamps) {
+ final long fileTime = file.lastModified();
+ if (fileTime <= 0) return false; // File does not exist
+
+ final String filename = file.getPath();
+ if (timestamps.containsKey(filename) && timestamps.get(filename) == fileTime) {
+ return false; // Already logged this particular file
+ }
+
+ timestamps.put(filename, fileTime);
+ return true;
+ }
+
private static void addTextToDropBox(DropBoxManager db, String tag, String text,
String filename, int maxSize) {
Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index e29e894..e924012 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -16,8 +16,9 @@
package com.android.server;
+import android.annotation.EnforcePermission;
+import android.annotation.RequiresNoPermission;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.gsi.AvbPublicKey;
import android.gsi.GsiProgress;
import android.gsi.IGsiService;
@@ -53,20 +54,12 @@
}
private IGsiService getGsiService() {
- checkPermission();
if (mGsiService != null) {
return mGsiService;
}
return IGsiService.Stub.asInterface(ServiceManager.waitForService("gsiservice"));
}
- private void checkPermission() {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires MANAGE_DYNAMIC_SYSTEM permission");
- }
- }
-
class GsiServiceCallback extends IGsiServiceCallback.Stub {
// 0 for success
private int mResult = -1;
@@ -82,6 +75,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean startInstallation(String dsuSlot) throws RemoteException {
IGsiService service = getGsiService();
mGsiService = service;
@@ -124,6 +118,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean createPartition(String name, long size, boolean readOnly)
throws RemoteException {
IGsiService service = getGsiService();
@@ -135,6 +130,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean closePartition() throws RemoteException {
IGsiService service = getGsiService();
if (service.closePartition() != 0) {
@@ -145,6 +141,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean finishInstallation() throws RemoteException {
IGsiService service = getGsiService();
if (service.closeInstall() != 0) {
@@ -155,21 +152,25 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public GsiProgress getInstallationProgress() throws RemoteException {
return getGsiService().getInstallProgress();
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean abort() throws RemoteException {
return getGsiService().cancelGsiInstall();
}
@Override
+ @RequiresNoPermission
public boolean isInUse() {
return SystemProperties.getBoolean("ro.gsid.image_running", false);
}
@Override
+ @RequiresNoPermission
public boolean isInstalled() {
boolean installed = SystemProperties.getBoolean("gsid.image_installed", false);
Slog.i(TAG, "isInstalled(): " + installed);
@@ -177,11 +178,13 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean isEnabled() throws RemoteException {
return getGsiService().isGsiEnabled();
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean remove() throws RemoteException {
try {
GsiServiceCallback callback = new GsiServiceCallback();
@@ -197,6 +200,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean setEnable(boolean enable, boolean oneShot) throws RemoteException {
IGsiService gsiService = getGsiService();
if (enable) {
@@ -220,6 +224,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean setAshmem(ParcelFileDescriptor ashmem, long size) {
try {
return getGsiService().setGsiAshmem(ashmem, size);
@@ -229,6 +234,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean submitFromAshmem(long size) {
try {
return getGsiService().commitGsiChunkFromAshmem(size);
@@ -238,6 +244,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public boolean getAvbPublicKey(AvbPublicKey dst) {
try {
return getGsiService().getAvbPublicKey(dst) == 0;
@@ -247,6 +254,7 @@
}
@Override
+ @EnforcePermission(android.Manifest.permission.MANAGE_DYNAMIC_SYSTEM)
public long suggestScratchSize() throws RemoteException {
return getGsiService().suggestScratchSize();
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 3951680..39ac5ef 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -20,12 +20,12 @@
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.SHUTDOWN;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_ALLOWLIST;
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
import static android.net.INetd.FIREWALL_CHAIN_NONE;
-import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
-import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_DENYLIST;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
@@ -34,16 +34,13 @@
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.net.NetworkStats.SET_DEFAULT;
-import static android.net.NetworkStats.STATS_PER_UID;
-import static android.net.NetworkStats.TAG_NONE;
-import static android.net.TrafficStats.UID_TETHERING;
import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
import android.annotation.NonNull;
import android.app.ActivityManager;
import android.content.Context;
+import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.INetdUnsolicitedEventListener;
import android.net.INetworkManagementEventObserver;
@@ -57,7 +54,6 @@
import android.net.NetworkStack;
import android.net.NetworkStats;
import android.net.RouteInfo;
-import android.net.TetherStatsParcel;
import android.net.UidRangeParcel;
import android.net.util.NetdService;
import android.os.BatteryStats;
@@ -1158,19 +1154,12 @@
}
Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "inetd bandwidth");
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
try {
if (allowlist) {
- if (enable) {
- mNetdService.bandwidthAddNiceApp(uid);
- } else {
- mNetdService.bandwidthRemoveNiceApp(uid);
- }
+ cm.updateMeteredNetworkAllowList(uid, enable);
} else {
- if (enable) {
- mNetdService.bandwidthAddNaughtyApp(uid);
- } else {
- mNetdService.bandwidthRemoveNaughtyApp(uid);
- }
+ cm.updateMeteredNetworkDenyList(uid, enable);
}
synchronized (mRulesLock) {
if (enable) {
@@ -1179,7 +1168,7 @@
quotaList.delete(uid);
}
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (RuntimeException e) {
throw new IllegalStateException(e);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_NETWORK);
@@ -1292,40 +1281,9 @@
private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
@Override
public NetworkStats getTetherStats(int how) {
- // We only need to return per-UID stats. Per-device stats are already counted by
- // interface counters.
- if (how != STATS_PER_UID) {
- return new NetworkStats(SystemClock.elapsedRealtime(), 0);
- }
-
- final TetherStatsParcel[] tetherStatsVec;
- try {
- tetherStatsVec = mNetdService.tetherGetStats();
- } catch (RemoteException | ServiceSpecificException e) {
- throw new IllegalStateException("problem parsing tethering stats: ", e);
- }
-
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(),
- tetherStatsVec.length);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
-
- for (TetherStatsParcel tetherStats : tetherStatsVec) {
- try {
- entry.iface = tetherStats.iface;
- entry.uid = UID_TETHERING;
- entry.set = SET_DEFAULT;
- entry.tag = TAG_NONE;
- entry.rxBytes = tetherStats.rxBytes;
- entry.rxPackets = tetherStats.rxPackets;
- entry.txBytes = tetherStats.txBytes;
- entry.txPackets = tetherStats.txPackets;
- stats.combineValues(entry);
- } catch (ArrayIndexOutOfBoundsException e) {
- throw new IllegalStateException("invalid tethering stats " + e);
- }
- }
-
- return stats;
+ // Remove the implementation of NetdTetheringStatsProvider#getTetherStats
+ // since all callers are migrated to use INetd#tetherGetStats directly.
+ throw new UnsupportedOperationException();
}
@Override
@@ -1336,20 +1294,9 @@
@Override
public NetworkStats getNetworkStatsTethering(int how) {
- NetworkStack.checkNetworkStackPermission(mContext);
-
- final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- synchronized (mTetheringStatsProviders) {
- for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
- try {
- stats.combineAllValues(provider.getTetherStats(how));
- } catch (RemoteException e) {
- Log.e(TAG, "Problem reading tethering stats from " +
- mTetheringStatsProviders.get(provider) + ": " + e);
- }
- }
- }
- return stats;
+ // Remove the implementation of getNetworkStatsTethering since all callers are migrated
+ // to use INetd#tetherGetStats directly.
+ throw new UnsupportedOperationException();
}
@Override
@@ -1464,9 +1411,10 @@
throw new IllegalArgumentException("Bad child chain: " + chainName);
}
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
try {
- mNetdService.firewallEnableChildChain(chain, enable);
- } catch (RemoteException | ServiceSpecificException e) {
+ cm.setFirewallChainEnabled(chain, enable);
+ } catch (RuntimeException e) {
throw new IllegalStateException(e);
}
@@ -1538,25 +1486,10 @@
updateFirewallUidRuleLocked(chain, uid, FIREWALL_RULE_DEFAULT);
}
}
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
try {
- switch (chain) {
- case FIREWALL_CHAIN_DOZABLE:
- mNetdService.firewallReplaceUidChain("fw_dozable", true, uids);
- break;
- case FIREWALL_CHAIN_STANDBY:
- mNetdService.firewallReplaceUidChain("fw_standby", false, uids);
- break;
- case FIREWALL_CHAIN_POWERSAVE:
- mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
- break;
- case FIREWALL_CHAIN_RESTRICTED:
- mNetdService.firewallReplaceUidChain("fw_restricted", true, uids);
- break;
- case FIREWALL_CHAIN_NONE:
- default:
- Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
- }
- } catch (RemoteException e) {
+ cm.replaceFirewallChain(chain, uids);
+ } catch (RuntimeException e) {
Slog.w(TAG, "Error flushing firewall chain " + chain, e);
}
}
@@ -1572,10 +1505,10 @@
private void setFirewallUidRuleLocked(int chain, int uid, int rule) {
if (updateFirewallUidRuleLocked(chain, uid, rule)) {
- final int ruleType = getFirewallRuleType(chain, rule);
+ final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
try {
- mNetdService.firewallSetUidRule(chain, uid, ruleType);
- } catch (RemoteException | ServiceSpecificException e) {
+ cm.updateFirewallRule(chain, uid, isFirewallRuleAllow(chain, rule));
+ } catch (RuntimeException e) {
throw new IllegalStateException(e);
}
}
@@ -1645,12 +1578,12 @@
}
}
- private int getFirewallRuleType(int chain, int rule) {
+ // There are only two type of firewall rule: FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY.
+ private boolean isFirewallRuleAllow(int chain, int rule) {
if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) {
- return getFirewallType(chain) == FIREWALL_ALLOWLIST
- ? INetd.FIREWALL_RULE_DENY : INetd.FIREWALL_RULE_ALLOW;
+ return getFirewallType(chain) == FIREWALL_DENYLIST;
}
- return rule;
+ return rule == INetd.FIREWALL_RULE_ALLOW;
}
private void enforceSystemUid() {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 53c8635..9546496 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3620,8 +3620,12 @@
mInstaller.tryMountDataMirror(volumeUuid);
}
}
- } catch (Exception e) {
+ } catch (RemoteException | Installer.InstallerException e) {
Slog.wtf(TAG, e);
+ // Make sure to re-throw this exception; we must not ignore failure
+ // to prepare the user storage as it could indicate that encryption
+ // wasn't successfully set up.
+ throw new RuntimeException(e);
}
}
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 6a7afd9..2d328d8 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -539,7 +539,13 @@
@GuardedBy("mLock")
private void notifyAllPolicyListenersLocked() {
for (final PolicyListenerBinderDeath policyListener : mRegisteredPolicyListeners.values()) {
- Binder.withCleanCallingIdentity(() -> policyListener.mListener.onPolicyChanged());
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ policyListener.mListener.onPolicyChanged();
+ } catch (RemoteException e) {
+ logDbg("VcnStatusCallback threw on VCN status change", e);
+ }
+ });
}
}
@@ -548,8 +554,13 @@
@NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) {
for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo, subGroup)) {
- Binder.withCleanCallingIdentity(
- () -> cbInfo.mCallback.onVcnStatusChanged(statusCode));
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ cbInfo.mCallback.onVcnStatusChanged(statusCode);
+ } catch (RemoteException e) {
+ logDbg("VcnStatusCallback threw on VCN status change", e);
+ }
+ });
}
}
}
@@ -1222,13 +1233,17 @@
// Notify all registered StatusCallbacks for this subGroup
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo, mSubGroup)) {
- Binder.withCleanCallingIdentity(
- () ->
- cbInfo.mCallback.onGatewayConnectionError(
- gatewayConnectionName,
- errorCode,
- exceptionClass,
- exceptionMessage));
+ Binder.withCleanCallingIdentity(() -> {
+ try {
+ cbInfo.mCallback.onGatewayConnectionError(
+ gatewayConnectionName,
+ errorCode,
+ exceptionClass,
+ exceptionMessage);
+ } catch (RemoteException e) {
+ logDbg("VcnStatusCallback threw on VCN status change", e);
+ }
+ });
}
}
}
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index b48e21e..7b8cce5 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -340,17 +340,18 @@
* <p>This is designed to serve the VpnManager only; settings-based VPN profiles are managed
* exclusively by the Settings app, and passed into the platform at startup time.
*
+ * @return A unique key corresponding to this session.
* @throws IllegalArgumentException if no profile was found for the given package name.
* @hide
*/
@Override
- public void startVpnProfile(@NonNull String packageName) {
+ public String startVpnProfile(@NonNull String packageName) {
final int callingUid = Binder.getCallingUid();
verifyCallingUidAndPackage(packageName, callingUid);
final int user = UserHandle.getUserId(callingUid);
synchronized (mVpns) {
throwIfLockdownEnabled();
- mVpns.get(user).startVpnProfile(packageName);
+ return mVpns.get(user).startVpnProfile(packageName);
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 2eb59b2..54987cf 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -29,7 +29,7 @@
import android.media.AudioManager;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
import android.media.IAudioRoutesObserver;
import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.ICommunicationDeviceDispatcher;
@@ -517,12 +517,12 @@
/*package*/ static final class BtDeviceChangedData {
final @Nullable BluetoothDevice mNewDevice;
final @Nullable BluetoothDevice mPreviousDevice;
- final @NonNull BtProfileConnectionInfo mInfo;
+ final @NonNull BluetoothProfileConnectionInfo mInfo;
final @NonNull String mEventSource;
BtDeviceChangedData(@Nullable BluetoothDevice newDevice,
@Nullable BluetoothDevice previousDevice,
- @NonNull BtProfileConnectionInfo info, @NonNull String eventSource) {
+ @NonNull BluetoothProfileConnectionInfo info, @NonNull String eventSource) {
mNewDevice = newDevice;
mPreviousDevice = previousDevice;
mInfo = info;
@@ -554,9 +554,9 @@
mDevice = device;
mState = state;
mProfile = d.mInfo.getProfile();
- mSupprNoisy = d.mInfo.getSuppressNoisyIntent();
+ mSupprNoisy = d.mInfo.isSuppressNoisyIntent();
mVolume = d.mInfo.getVolume();
- mIsLeOutput = d.mInfo.getIsLeOutput();
+ mIsLeOutput = d.mInfo.isLeOutput();
mEventSource = d.mEventSource;
mAudioSystemDevice = audioDevice;
mMusicDevice = AudioSystem.DEVICE_NONE;
@@ -627,7 +627,7 @@
audioDevice = AudioSystem.DEVICE_OUT_HEARING_AID;
break;
case BluetoothProfile.LE_AUDIO:
- if (d.mInfo.getIsLeOutput()) {
+ if (d.mInfo.isLeOutput()) {
audioDevice = AudioSystem.DEVICE_OUT_BLE_HEADSET;
} else {
audioDevice = AudioSystem.DEVICE_IN_BLE_HEADSET;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index e00c8a3..070725e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -83,7 +83,7 @@
import android.media.AudioRecordingConfiguration;
import android.media.AudioRoutesInfo;
import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
import android.media.IAudioFocusDispatcher;
import android.media.IAudioModeDispatcher;
import android.media.IAudioRoutesObserver;
@@ -6301,14 +6301,14 @@
* See AudioManager.handleBluetoothActiveDeviceChanged(...)
*/
public void handleBluetoothActiveDeviceChanged(BluetoothDevice newDevice,
- BluetoothDevice previousDevice, @NonNull BtProfileConnectionInfo info) {
+ BluetoothDevice previousDevice, @NonNull BluetoothProfileConnectionInfo info) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.BLUETOOTH_STACK)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Bluetooth is the only caller allowed");
}
if (info == null) {
- throw new IllegalArgumentException("Illegal null BtProfileConnectionInfo for device "
- + previousDevice + " -> " + newDevice);
+ throw new IllegalArgumentException("Illegal null BluetoothProfileConnectionInfo for"
+ + " device " + previousDevice + " -> " + newDevice);
}
final int profile = info.getProfile();
if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 9273a5d..1c29935 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -31,7 +31,7 @@
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
import android.os.Binder;
import android.os.UserHandle;
import android.provider.Settings;
@@ -495,11 +495,13 @@
if (state == BluetoothProfile.STATE_CONNECTED) {
mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
- new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
+ new BluetoothProfileConnectionInfo(profile),
+ "mBluetoothProfileServiceListener"));
} else {
mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(null, btDevice,
- new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
+ new BluetoothProfileConnectionInfo(profile),
+ "mBluetoothProfileServiceListener"));
}
}
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index 3d5abfe..a0c5aa3 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -571,7 +571,7 @@
final boolean canCopyIntoProfile = !hasRestriction(
UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, id);
if (canCopyIntoProfile) {
- setPrimaryClipInternalLocked(
+ setPrimaryClipInternalNoClassifyLocked(
getClipboardLocked(id), clip, uid, sourcePackage);
}
}
@@ -639,7 +639,7 @@
clipboard.primaryClipListeners.getBroadcastItem(i)
.dispatchPrimaryClipChanged();
}
- } catch (RemoteException e) {
+ } catch (RemoteException | SecurityException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
diff --git a/services/core/java/com/android/server/clipboard/OWNERS b/services/core/java/com/android/server/clipboard/OWNERS
index 5449df9..0d5dbf9 100644
--- a/services/core/java/com/android/server/clipboard/OWNERS
+++ b/services/core/java/com/android/server/clipboard/OWNERS
@@ -1 +1,3 @@
per-file EmulatorClipboardMonitor.java = bohu@google.com,lfy@google.com,rkir@google.com
+
+olilan@google.com
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index fce6737..603f206 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -18,14 +18,12 @@
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_HANDOVER;
import static android.net.ConnectivityManager.MULTIPATH_PREFERENCE_RELIABILITY;
-import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
-import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
import static android.provider.Settings.Global.NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -95,6 +93,7 @@
private static String TAG = MultipathPolicyTracker.class.getSimpleName();
private static final boolean DBG = false;
+ private static final long MIN_THRESHOLD_BYTES = 2 * 1_048_576L; // 2MiB
// This context is for the current user.
private final Context mContext;
@@ -279,15 +278,11 @@
}
private NetworkIdentity getTemplateMatchingNetworkIdentity(NetworkCapabilities nc) {
- return new NetworkIdentity(
- ConnectivityManager.TYPE_MOBILE,
- 0 /* subType, unused for template matching */,
- subscriberId,
- null /* networkId, unused for matching mobile networks */,
- !nc.hasCapability(NET_CAPABILITY_NOT_ROAMING),
- !nc.hasCapability(NET_CAPABILITY_NOT_METERED),
- false /* defaultNetwork, templates should have DEFAULT_NETWORK_ALL */,
- OEM_MANAGED_ALL);
+ return new NetworkIdentity.Builder().setType(ConnectivityManager.TYPE_MOBILE)
+ .setSubscriberId(subscriberId)
+ .setRoaming(!nc.hasCapability(NET_CAPABILITY_NOT_ROAMING))
+ .setMetered(!nc.hasCapability(NET_CAPABILITY_NOT_METERED))
+ .build();
}
private long getRemainingDailyBudget(long limitBytes,
@@ -376,7 +371,7 @@
// This will only be called if the total quota for the day changed, not if usage changed
// since last time, so even if this is called very often the budget will not snap to 0
// as soon as there are less than 2MB left for today.
- if (budget > NetworkStatsManager.MIN_THRESHOLD_BYTES) {
+ if (budget > MIN_THRESHOLD_BYTES) {
if (DBG) {
Log.d(TAG, "Setting callback for " + budget + " bytes on network " + network);
}
@@ -409,8 +404,8 @@
private void registerUsageCallback(long budget) {
maybeUnregisterUsageCallback();
- mStatsManager.registerUsageCallback(mNetworkTemplate, TYPE_MOBILE, budget,
- mUsageCallback, mHandler);
+ mStatsManager.registerUsageCallback(mNetworkTemplate, budget,
+ (command) -> mHandler.post(command), mUsageCallback);
mMultipathBudget = budget;
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9a9c3ea..3fb49e4 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -151,6 +151,7 @@
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -203,6 +204,7 @@
private final NetworkInfo mNetworkInfo;
private int mLegacyState;
@VisibleForTesting protected String mPackage;
+ private String mSessionKey;
private int mOwnerUID;
private boolean mIsPackageTargetingAtLeastQ;
@VisibleForTesting
@@ -1302,6 +1304,7 @@
.setLegacyType(ConnectivityManager.TYPE_VPN)
.setLegacyTypeName("VPN")
.setBypassableVpn(mConfig.allowBypass && !mLockdown)
+ .setVpnRequiresValidation(mConfig.requiresInternetValidation)
.build();
capsBuilder.setOwnerUid(mOwnerUID);
@@ -2503,6 +2506,7 @@
mProfile = profile;
mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this);
+ mSessionKey = UUID.randomUUID().toString();
}
@Override
@@ -2824,6 +2828,7 @@
*/
private void disconnectVpnRunner() {
mActiveNetwork = null;
+ mSessionKey = null;
mIsRunning = false;
resetIkeState();
@@ -3314,7 +3319,7 @@
*
* @param packageName the package name of the app provisioning this profile
*/
- public synchronized void startVpnProfile(@NonNull String packageName) {
+ public synchronized String startVpnProfile(@NonNull String packageName) {
requireNonNull(packageName, "No package name provided");
enforceNotRestrictedUser();
@@ -3332,6 +3337,7 @@
}
startVpnProfilePrivileged(profile, packageName);
+ return mSessionKey;
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3363,6 +3369,7 @@
}
mConfig.startTime = SystemClock.elapsedRealtime();
mConfig.proxyInfo = profile.proxy;
+ mConfig.requiresInternetValidation = profile.requiresInternetValidation;
switch (profile.type) {
case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index c27293c..c12522b 100755
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -75,6 +75,8 @@
protected int mLastKeycode = HdmiCecKeycode.UNSUPPORTED_KEYCODE;
protected int mLastKeyRepeatCount = 0;
+ HdmiCecStandbyModeHandler mStandbyHandler;
+
// Stores recent changes to the active source in the CEC network.
private final ArrayBlockingQueue<HdmiCecController.Dumpable> mActiveSourceHistory =
new ArrayBlockingQueue<>(MAX_HDMI_ACTIVE_SOURCE_HISTORY);
@@ -263,6 +265,11 @@
if (dest != mAddress && dest != Constants.ADDR_BROADCAST) {
return Constants.NOT_HANDLED;
}
+ if (mService.isPowerStandby()
+ && !mService.isWakeUpMessageReceived()
+ && mStandbyHandler.handleCommand(message)) {
+ return Constants.HANDLED;
+ }
// Cache incoming message if it is included in the list of cacheable opcodes.
mCecMessageCache.cacheMessage(message);
return onMessage(message);
@@ -829,17 +836,12 @@
protected int handleVendorCommandWithId(HdmiCecMessage message) {
byte[] params = message.getParams();
int vendorId = HdmiUtils.threeBytesToInt(params);
- if (vendorId == mService.getVendorId()) {
- if (!mService.invokeVendorCommandListenersOnReceived(
- mDeviceType, message.getSource(), message.getDestination(), params, true)) {
- return Constants.ABORT_REFUSED;
- }
- } else if (message.getDestination() != Constants.ADDR_BROADCAST
- && message.getSource() != Constants.ADDR_UNREGISTERED) {
- Slog.v(TAG, "Wrong direct vendor command. Replying with <Feature Abort>");
- return Constants.ABORT_UNRECOGNIZED_OPCODE;
- } else {
+ if (message.getDestination() == Constants.ADDR_BROADCAST
+ || message.getSource() == Constants.ADDR_UNREGISTERED) {
Slog.v(TAG, "Wrong broadcast vendor command. Ignoring");
+ } else if (!mService.invokeVendorCommandListenersOnReceived(
+ mDeviceType, message.getSource(), message.getDestination(), params, true)) {
+ return Constants.ABORT_REFUSED;
}
return Constants.HANDLED;
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 0bb1285..c549b55 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -112,6 +112,7 @@
mService.readBooleanSetting(Global.HDMI_CEC_SWITCH_ENABLED, false);
mSystemAudioControlFeatureEnabled =
mService.readBooleanSetting(Global.HDMI_SYSTEM_AUDIO_CONTROL_ENABLED, true);
+ mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
}
private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml";
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 37ee76b7..4071858 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -64,6 +64,7 @@
HdmiCecLocalDevicePlayback(HdmiControlService service) {
super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
+ mStandbyHandler = new HdmiCecStandbyModeHandler(service, this);
}
@Override
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 6e7a2a0..3d218cf 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -91,8 +91,6 @@
@GuardedBy("mLock")
private boolean mSystemAudioMute = false;
- private final HdmiCecStandbyModeHandler mStandbyHandler;
-
// If true, do not do routing control/send active source for internal source.
// Set to true when the device was woken up by <Text/Image View On>.
private boolean mSkipRoutingControl;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
index 6f7473d..1c296e5 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecStandbyModeHandler.java
@@ -16,6 +16,7 @@
package com.android.server.hdmi;
+import android.hardware.hdmi.HdmiDeviceInfo;
import android.util.SparseArray;
/**
@@ -56,7 +57,8 @@
private final class AutoOnHandler implements CecMessageHandler {
@Override
public boolean handle(HdmiCecMessage message) {
- if (!mTv.getAutoWakeup()) {
+ HdmiCecLocalDeviceTv tv = (HdmiCecLocalDeviceTv) mDevice;
+ if (!tv.getAutoWakeup()) {
mAborterRefused.handle(message);
return true;
}
@@ -78,7 +80,7 @@
}
private final HdmiControlService mService;
- private final HdmiCecLocalDeviceTv mTv;
+ private final HdmiCecLocalDevice mDevice;
private final SparseArray<CecMessageHandler> mCecMessageHandlers = new SparseArray<>();
private final CecMessageHandler mDefaultHandler = new Aborter(
@@ -92,13 +94,7 @@
private final UserControlProcessedHandler
mUserControlProcessedHandler = new UserControlProcessedHandler();
- public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDeviceTv tv) {
- mService = service;
- mTv = tv;
-
- addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
- addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
-
+ private void addCommonHandlers() {
addHandler(Constants.MESSAGE_ACTIVE_SOURCE, mBystander);
addHandler(Constants.MESSAGE_REQUEST_ACTIVE_SOURCE, mBystander);
addHandler(Constants.MESSAGE_ROUTING_CHANGE, mBystander);
@@ -112,6 +108,30 @@
addHandler(Constants.MESSAGE_SYSTEM_AUDIO_MODE_STATUS, mBystander);
addHandler(Constants.MESSAGE_REPORT_AUDIO_STATUS, mBystander);
+ addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
+ addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
+ addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
+ addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
+ addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
+ addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
+ addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBypasser);
+ addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser);
+ addHandler(Constants.MESSAGE_GIVE_FEATURES, mBypasser);
+
+ addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
+
+ addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
+ addHandler(Constants.MESSAGE_ABORT, mBypasser);
+ addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
+
+ addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
+ addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
+ }
+
+ private void addTvHandlers() {
+ addHandler(Constants.MESSAGE_IMAGE_VIEW_ON, mAutoOnHandler);
+ addHandler(Constants.MESSAGE_TEXT_VIEW_ON, mAutoOnHandler);
+
// If TV supports the following messages during power-on, ignore them and do nothing,
// else reply with <Feature Abort>["Unrecognized Opcode"]
// <Deck Status>, <Tuner Device Status>, <Tuner Cleared Status>, <Timer Status>
@@ -124,24 +144,16 @@
addHandler(Constants.MESSAGE_RECORD_TV_SCREEN, mAborterIncorrectMode);
addHandler(Constants.MESSAGE_INITIATE_ARC, mAborterIncorrectMode);
addHandler(Constants.MESSAGE_TERMINATE_ARC, mAborterIncorrectMode);
+ }
- addHandler(Constants.MESSAGE_GIVE_PHYSICAL_ADDRESS, mBypasser);
- addHandler(Constants.MESSAGE_GET_MENU_LANGUAGE, mBypasser);
- addHandler(Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS, mBypasser);
- addHandler(Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID, mBypasser);
- addHandler(Constants.MESSAGE_GIVE_OSD_NAME, mBypasser);
- addHandler(Constants.MESSAGE_SET_OSD_NAME, mBypasser);
- addHandler(Constants.MESSAGE_DEVICE_VENDOR_ID, mBypasser);
- addHandler(Constants.MESSAGE_REPORT_POWER_STATUS, mBypasser);
+ public HdmiCecStandbyModeHandler(HdmiControlService service, HdmiCecLocalDevice device) {
+ mService = service;
+ mDevice = device;
- addHandler(Constants.MESSAGE_USER_CONTROL_PRESSED, mUserControlProcessedHandler);
-
- addHandler(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS, mBypasser);
- addHandler(Constants.MESSAGE_ABORT, mBypasser);
- addHandler(Constants.MESSAGE_GET_CEC_VERSION, mBypasser);
-
- addHandler(Constants.MESSAGE_VENDOR_COMMAND_WITH_ID, mAborterIncorrectMode);
- addHandler(Constants.MESSAGE_SET_SYSTEM_AUDIO_MODE, mAborterIncorrectMode);
+ addCommonHandlers();
+ if (mDevice.getType() == HdmiDeviceInfo.DEVICE_TV) {
+ addTvHandlers();
+ }
}
private void addHandler(int opcode, CecMessageHandler handler) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a571dc0..8dadf5a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1582,11 +1582,11 @@
class VendorCommandListenerRecord implements IBinder.DeathRecipient {
private final IHdmiVendorCommandListener mListener;
- private final int mDeviceType;
+ private final int mVendorId;
- public VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int deviceType) {
+ VendorCommandListenerRecord(IHdmiVendorCommandListener listener, int vendorId) {
mListener = listener;
- mDeviceType = deviceType;
+ mVendorId = vendorId;
}
@Override
@@ -2077,10 +2077,10 @@
}
@Override
- public void addVendorCommandListener(final IHdmiVendorCommandListener listener,
- final int deviceType) {
+ public void addVendorCommandListener(
+ final IHdmiVendorCommandListener listener, final int vendorId) {
initBinderCall();
- HdmiControlService.this.addVendorCommandListener(listener, deviceType);
+ HdmiControlService.this.addVendorCommandListener(listener, vendorId);
}
@Override
@@ -3219,8 +3219,9 @@
}
}
- private void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
- VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, deviceType);
+ @VisibleForTesting
+ void addVendorCommandListener(IHdmiVendorCommandListener listener, int vendorId) {
+ VendorCommandListenerRecord record = new VendorCommandListenerRecord(listener, vendorId);
try {
listener.asBinder().linkToDeath(record, 0);
} catch (RemoteException e) {
@@ -3239,8 +3240,14 @@
return false;
}
for (VendorCommandListenerRecord record : mVendorCommandListenerRecords) {
- if (record.mDeviceType != deviceType) {
- continue;
+ if (hasVendorId) {
+ int vendorId =
+ ((params[0] & 0xFF) << 16)
+ + ((params[1] & 0xFF) << 8)
+ + (params[2] & 0xFF);
+ if (record.mVendorId != vendorId) {
+ continue;
+ }
}
try {
record.mListener.onReceived(srcAddress, destAddress, params, hasVendorId);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 3e52f5e..5b7f5c8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2837,7 +2837,7 @@
return;
}
final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
- if (targetWindow != null && mLastImeTargetWindow != targetWindow) {
+ if (targetWindow != null) {
mWindowManagerInternal.updateInputMethodTargetWindow(token, targetWindow);
}
mLastImeTargetWindow = targetWindow;
diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
index ffc1aed4..91de9e5 100644
--- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java
+++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java
@@ -344,10 +344,19 @@
}
private void addActiveRoute(BluetoothRouteInfo btRoute) {
+ if (btRoute == null) {
+ if (DEBUG) {
+ Log.d(TAG, " btRoute is null");
+ }
+ return;
+ }
if (DEBUG) {
Log.d(TAG, "Adding active route: " + btRoute.route);
}
- if (btRoute == null || mActiveRoutes.contains(btRoute)) {
+ if (mActiveRoutes.contains(btRoute)) {
+ if (DEBUG) {
+ Log.d(TAG, " btRoute is already added.");
+ }
return;
}
setRouteConnectionState(btRoute, STATE_CONNECTED);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 81106b1..b66c466 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -15,12 +15,14 @@
*/
package com.android.server.net;
+import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
+import static android.net.NetworkPolicyManager.ALLOWED_REASON_NONE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
@@ -29,6 +31,7 @@
import static android.os.PowerExemptionManager.reasonCodeToString;
import static android.os.Process.INVALID_UID;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.ProcessCapability;
import android.net.NetworkPolicyManager;
@@ -81,13 +84,18 @@
private final Object mLock = new Object();
- void networkBlocked(int uid, UidBlockedState uidBlockedState) {
+ void networkBlocked(int uid, @Nullable UidBlockedState uidBlockedState) {
synchronized (mLock) {
if (LOGD || uid == mDebugUid) {
Slog.d(TAG, "Blocked state of uid: " + uidBlockedState.toString());
}
- mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
- uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+ if (uidBlockedState == null) {
+ mNetworkBlockedBuffer.networkBlocked(uid, BLOCKED_REASON_NONE, ALLOWED_REASON_NONE,
+ BLOCKED_REASON_NONE);
+ } else {
+ mNetworkBlockedBuffer.networkBlocked(uid, uidBlockedState.blockedReasons,
+ uidBlockedState.allowedReasons, uidBlockedState.effectiveBlockedReasons);
+ }
}
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e1cbdb7..6a00d06 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -24,7 +24,6 @@
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
-import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -63,7 +62,6 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkIdentity.OEM_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.SNOOZE_NEVER;
import static android.net.NetworkPolicy.WARNING_DISABLED;
@@ -100,9 +98,6 @@
import static android.net.NetworkTemplate.MATCH_CARRIER;
import static android.net.NetworkTemplate.MATCH_MOBILE;
import static android.net.NetworkTemplate.MATCH_WIFI;
-import static android.net.NetworkTemplate.buildTemplateCarrierMetered;
-import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.provider.Settings.Global.NETPOLICY_OVERRIDE_ENABLED;
@@ -131,7 +126,6 @@
import static com.android.internal.util.XmlUtils.writeLongAttribute;
import static com.android.internal.util.XmlUtils.writeStringAttribute;
import static com.android.net.module.util.NetworkStatsUtils.LIMIT_GLOBAL_ALERT;
-import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
@@ -172,7 +166,6 @@
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
-import android.net.INetworkStatsService;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkIdentity;
@@ -185,7 +178,6 @@
import android.net.NetworkStateSnapshot;
import android.net.NetworkTemplate;
import android.net.TelephonyNetworkSpecifier;
-import android.net.TrafficStats;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.BestClock;
@@ -1013,10 +1005,11 @@
userFilter.addAction(ACTION_USER_REMOVED);
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
- // listen for stats update events
- final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
- mContext.registerReceiver(
- mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
+ // listen for stats updated callbacks for interested network types.
+ mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_MOBILE).build(),
+ 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
+ mNetworkStats.registerUsageCallback(new NetworkTemplate.Builder(MATCH_WIFI).build(),
+ 0 /* thresholdBytes */, new HandlerExecutor(mHandler), mStatsCallback);
// listen for restrict background changes from notifications
final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
@@ -1221,19 +1214,16 @@
};
/**
- * Receiver that watches for {@link NetworkStatsManager} updates, which we
- * use to check against {@link NetworkPolicy#warningBytes}.
+ * Listener that watches for {@link NetworkStatsManager} updates, which
+ * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}.
*/
- private final NetworkStatsBroadcastReceiver mStatsReceiver =
- new NetworkStatsBroadcastReceiver();
- private class NetworkStatsBroadcastReceiver extends BroadcastReceiver {
- private boolean mIsAnyIntentReceived = false;
- @Override
- public void onReceive(Context context, Intent intent) {
- // on background handler thread, and verified
- // READ_NETWORK_USAGE_HISTORY permission above.
+ private final StatsCallback mStatsCallback = new StatsCallback();
+ private class StatsCallback extends NetworkStatsManager.UsageCallback {
+ private boolean mIsAnyCallbackReceived = false;
- mIsAnyIntentReceived = true;
+ @Override
+ public void onThresholdReached(int networkType, String subscriberId) {
+ mIsAnyCallbackReceived = true;
synchronized (mNetworkPoliciesSecondLock) {
updateNetworkRulesNL();
@@ -1243,11 +1233,11 @@
}
/**
- * Return whether any {@code ACTION_NETWORK_STATS_UPDATED} intent is received.
+ * Return whether any callback is received.
* Used to determine if NetworkStatsService is ready.
*/
- public boolean isAnyIntentReceived() {
- return mIsAnyIntentReceived;
+ public boolean isAnyCallbackReceived() {
+ return mIsAnyCallbackReceived;
}
};
@@ -1351,7 +1341,7 @@
};
/**
- * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
+ * Check {@link NetworkPolicy} against current {@link NetworkStatsManager}
* to show visible notifications as needed.
*/
@GuardedBy("mNetworkPoliciesSecondLock")
@@ -1474,7 +1464,7 @@
// Skip if not ready. NetworkStatsService will block public API calls until it is
// ready. To prevent NPMS be blocked on that, skip and fail fast instead.
- if (!mStatsReceiver.isAnyIntentReceived()) return null;
+ if (!mStatsCallback.isAnyCallbackReceived()) return null;
final List<NetworkStats.Bucket> stats = mDeps.getNetworkUidBytes(template, start, end);
for (final NetworkStats.Bucket entry : stats) {
@@ -1518,13 +1508,11 @@
for (int i = 0; i < mSubIdToSubscriberId.size(); i++) {
final int subId = mSubIdToSubscriberId.keyAt(i);
final String subscriberId = mSubIdToSubscriberId.valueAt(i);
- final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
- true, OEM_NONE);
- /* While OEM_NONE indicates "any non OEM managed network", OEM_NONE is meant to be a
- * placeholder value here. The probeIdent is matched against a NetworkTemplate which
- * should have its OEM managed value set to OEM_MANAGED_ALL, which will cause the
- * template to match probeIdent without regard to OEM managed status. */
+ final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+ .setType(TYPE_MOBILE)
+ .setSubscriberId(subscriberId)
+ .setMetered(true)
+ .setDefaultNetwork(true).build();
if (template.matches(probeIdent)) {
return subId;
}
@@ -1757,9 +1745,11 @@
// find and update the carrier NetworkPolicy for this subscriber id
boolean policyUpdated = false;
- final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true,
- OEM_NONE);
+ final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+ .setType(TYPE_MOBILE)
+ .setSubscriberId(subscriberId)
+ .setMetered(true)
+ .setDefaultNetwork(true).build();
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
if (template.matches(probeIdent)) {
@@ -1987,10 +1977,11 @@
for (int i = 0; i < mSubIdToSubscriberId.size(); i++) {
final int subId = mSubIdToSubscriberId.keyAt(i);
final String subscriberId = mSubIdToSubscriberId.valueAt(i);
-
- final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true,
- true, OEM_NONE);
+ final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+ .setType(TYPE_MOBILE)
+ .setSubscriberId(subscriberId)
+ .setMetered(true)
+ .setDefaultNetwork(true).build();
// Template is matched when subscriber id matches.
if (template.matches(probeIdent)) {
matchingSubIds.add(subId);
@@ -2094,11 +2085,9 @@
for (final NetworkStateSnapshot snapshot : snapshots) {
mNetIdToSubId.put(snapshot.getNetwork().getNetId(), parseSubId(snapshot));
- // Policies matched by NPMS only match by subscriber ID or by network ID. Thus subtype
- // in the object created here is never used and its value doesn't matter, so use
- // NETWORK_TYPE_UNKNOWN.
- final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
- true, TelephonyManager.NETWORK_TYPE_UNKNOWN /* subType */);
+ // Policies matched by NPMS only match by subscriber ID or by network ID.
+ final NetworkIdentity ident = new NetworkIdentity.Builder()
+ .setNetworkStateSnapshot(snapshot).setDefaultNetwork(true).build();
identified.put(snapshot, ident);
}
@@ -2295,9 +2284,11 @@
@GuardedBy("mNetworkPoliciesSecondLock")
private boolean ensureActiveCarrierPolicyAL(int subId, String subscriberId) {
// Poke around to see if we already have a policy
- final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
- TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true, true,
- OEM_NONE);
+ final NetworkIdentity probeIdent = new NetworkIdentity.Builder()
+ .setType(TYPE_MOBILE)
+ .setSubscriberId(subscriberId)
+ .setMetered(true)
+ .setDefaultNetwork(true).build();
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
if (template.matches(probeIdent)) {
@@ -2323,7 +2314,7 @@
if (dataWarningConfig == WARNING_DISABLED) {
return WARNING_DISABLED;
} else {
- return dataWarningConfig * MB_IN_BYTES;
+ return DataUnit.MEBIBYTES.toBytes(dataWarningConfig);
}
}
@@ -2348,6 +2339,18 @@
}
/**
+ * Template to match all metered carrier networks with the given IMSI.
+ *
+ * @hide
+ */
+ public static NetworkTemplate buildTemplateCarrierMetered(@NonNull String subscriberId) {
+ Objects.requireNonNull(subscriberId);
+ return new NetworkTemplate.Builder(MATCH_CARRIER)
+ .setSubscriberIds(Set.of(subscriberId))
+ .setMeteredness(METERED_YES).build();
+ }
+
+ /**
* Update the given {@link NetworkPolicy} based on any carrier-provided
* defaults via {@link SubscriptionPlan} or {@link CarrierConfigManager}.
* Leaves policy untouched if the user has modified it.
@@ -2707,7 +2710,7 @@
final List<WifiConfiguration> configs = wm.getConfiguredNetworks();
for (int i = 0; i < configs.size(); ++i) {
final WifiConfiguration config = configs.get(i);
- for (String key : config.getAllPersistableNetworkKeys()) {
+ for (String key : config.getAllNetworkKeys()) {
final Boolean metered = wifiNetworkKeys.get(key);
if (metered != null) {
Slog.d(TAG, "Found network " + key + "; upgrading metered hint");
@@ -2750,7 +2753,8 @@
out.startTag(null, TAG_NETWORK_POLICY);
writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
- final String subscriberId = template.getSubscriberId();
+ final String subscriberId = template.getSubscriberIds().isEmpty() ? null
+ : template.getSubscriberIds().iterator().next();
if (subscriberId != null) {
out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
}
@@ -3127,7 +3131,7 @@
}
// When two normalized templates conflict, prefer the most
// restrictive policy
- policy.template = NetworkTemplate.normalize(policy.template, mMergedSubscriberIds);
+ policy.template = normalizeTemplate(policy.template, mMergedSubscriberIds);
final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
if (existing == null || existing.compareTo(policy) > 0) {
if (existing != null) {
@@ -3138,6 +3142,46 @@
}
}
+ /**
+ * Examine the given template and normalize it.
+ * We pick the "lowest" merged subscriber as the primary
+ * for key purposes, and expand the template to match all other merged
+ * subscribers.
+ *
+ * There can be multiple merged subscriberIds for multi-SIM devices.
+ *
+ * <p>
+ * For example, given an incoming template matching B, and the currently
+ * active merge set [A,B], we'd return a new template that primarily matches
+ * A, but also matches B.
+ */
+ private static NetworkTemplate normalizeTemplate(@NonNull NetworkTemplate template,
+ @NonNull List<String[]> mergedList) {
+ // Now there are several types of network which uses Subscriber Id to store network
+ // information. For instance:
+ // 1. A merged carrier wifi network which has TYPE_WIFI with a Subscriber Id.
+ // 2. A typical cellular network could have TYPE_MOBILE with a Subscriber Id.
+
+ if (template.getSubscriberIds().isEmpty()) return template;
+
+ for (final String[] merged : mergedList) {
+ // TODO: Handle incompatible subscriberIds if that happens in practice.
+ for (final String subscriberId : template.getSubscriberIds()) {
+ if (com.android.net.module.util.CollectionUtils.contains(merged, subscriberId)) {
+ // Requested template subscriber is part of the merged group; return
+ // a template that matches all merged subscribers.
+ return new NetworkTemplate.Builder(template.getMatchRule())
+ .setWifiNetworkKeys(template.getWifiNetworkKeys())
+ .setSubscriberIds(Set.of(merged))
+ .setMeteredness(template.getMeteredness())
+ .build();
+ }
+ }
+ }
+
+ return template;
+ }
+
@Override
public void snoozeLimit(NetworkTemplate template) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
@@ -3472,7 +3516,7 @@
* {@link NetworkStatsProvider#onSetWarningAndLimit(String, long, long)}.
*/
@Override
- public void onStatsProviderWarningOrLimitReached() {
+ public void notifyStatsProviderWarningOrLimitReached() {
enforceAnyPermissionOf(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
// This API may be called before the system is ready.
synchronized (mNetworkPoliciesSecondLock) {
@@ -3492,9 +3536,9 @@
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
.setTitle("G-Mobile")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
- .setDataUsage(1 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(1),
ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
@@ -3502,15 +3546,15 @@
.setTitle("G-Mobile Happy")
.setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
- .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
.setTitle("G-Mobile, Charged after limit")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_BILLED)
- .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
ZonedDateTime.now().minusHours(36).toInstant().toEpochMilli())
.build());
} else if ("month_soft".equals(fake)) {
@@ -3519,25 +3563,25 @@
.setTitle("G-Mobile is the carriers name who this plan belongs to")
.setSummary("Crazy unlimited bandwidth plan with incredibly long title "
+ "that should be cut off to prevent UI from looking terrible")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(1 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(1),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
.setTitle("G-Mobile, Throttled after limit")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
.setTitle("G-Mobile, No data connection after limit")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
- .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
@@ -3545,25 +3589,25 @@
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"))
.setTitle("G-Mobile is the carriers name who this plan belongs to")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(6 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(6),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
.setTitle("G-Mobile, Throttled after limit")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
.createRecurringMonthly(ZonedDateTime.parse("2017-03-14T00:00:00.000Z"))
.setTitle("G-Mobile, No data connection after limit")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
- .setDataUsage(5 * TrafficStats.GB_IN_BYTES,
+ .setDataUsage(DataUnit.GIBIBYTES.toBytes(5),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
@@ -3577,9 +3621,9 @@
.createNonrecurring(ZonedDateTime.now().minusDays(20),
ZonedDateTime.now().plusDays(10))
.setTitle("G-Mobile")
- .setDataLimit(512 * TrafficStats.MB_IN_BYTES,
+ .setDataLimit(DataUnit.MEBIBYTES.toBytes(512),
SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
- .setDataUsage(100 * TrafficStats.MB_IN_BYTES,
+ .setDataUsage(DataUnit.MEBIBYTES.toBytes(100),
ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
.build());
} else if ("prepaid_crazy".equals(fake)) {
@@ -3587,9 +3631,9 @@
.createNonrecurring(ZonedDateTime.now().minusDays(20),
ZonedDateTime.now().plusDays(10))
.setTitle("G-Mobile Anytime")
- .setDataLimit(512 * TrafficStats.MB_IN_BYTES,
+ .setDataLimit(DataUnit.MEBIBYTES.toBytes(512),
SubscriptionPlan.LIMIT_BEHAVIOR_DISABLED)
- .setDataUsage(100 * TrafficStats.MB_IN_BYTES,
+ .setDataUsage(DataUnit.MEBIBYTES.toBytes(100),
ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
@@ -3597,9 +3641,9 @@
ZonedDateTime.now().plusDays(20))
.setTitle("G-Mobile Nickel Nights")
.setSummary("5¢/GB between 1-5AM")
- .setDataLimit(5 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(5),
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(15 * TrafficStats.MB_IN_BYTES,
+ .setDataUsage(DataUnit.MEBIBYTES.toBytes(15),
ZonedDateTime.now().minusHours(30).toInstant().toEpochMilli())
.build());
plans.add(SubscriptionPlan.Builder
@@ -3607,9 +3651,9 @@
ZonedDateTime.now().plusDays(20))
.setTitle("G-Mobile Bonus 3G")
.setSummary("Unlimited 3G data")
- .setDataLimit(1 * TrafficStats.GB_IN_BYTES,
+ .setDataLimit(DataUnit.GIBIBYTES.toBytes(1),
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(300 * TrafficStats.MB_IN_BYTES,
+ .setDataUsage(DataUnit.MEBIBYTES.toBytes(300),
ZonedDateTime.now().minusHours(1).toInstant().toEpochMilli())
.build());
} else if ("unlimited".equals(fake)) {
@@ -3619,7 +3663,7 @@
.setTitle("G-Mobile Awesome")
.setDataLimit(SubscriptionPlan.BYTES_UNLIMITED,
SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED)
- .setDataUsage(50 * TrafficStats.MB_IN_BYTES,
+ .setDataUsage(DataUnit.MEBIBYTES.toBytes(50),
ZonedDateTime.now().minusHours(3).toInstant().toEpochMilli())
.build());
}
@@ -5098,7 +5142,8 @@
// make sure stats are recorded frequently enough; we aim
// for 2MB threshold for 2GB/month rules.
final long persistThreshold = lowestRule / 1000;
- mNetworkStats.advisePersistThreshold(persistThreshold);
+ // TODO: Sync internal naming with the API surface.
+ mNetworkStats.setDefaultGlobalAlert(persistThreshold);
return true;
}
case MSG_UPDATE_INTERFACE_QUOTAS: {
@@ -5469,7 +5514,7 @@
private long getTotalBytes(NetworkTemplate template, long start, long end) {
// Skip if not ready. NetworkStatsService will block public API calls until it is
// ready. To prevent NPMS be blocked on that, skip and fail fast instead.
- if (!mStatsReceiver.isAnyIntentReceived()) return 0;
+ if (!mStatsCallback.isAnyCallbackReceived()) return 0;
return mDeps.getNetworkTotalBytes(template, start, end);
}
@@ -5588,7 +5633,11 @@
NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
NetworkTemplate templateCarrier = subscriber != null
? buildTemplateCarrierMetered(subscriber) : null;
- NetworkTemplate templateMobile = buildTemplateMobileAll(subscriber);
+ NetworkTemplate templateMobile = subscriber != null
+ ? new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setSubscriberIds(Set.of(subscriber))
+ .setMeteredness(android.net.NetworkStats.METERED_YES)
+ .build() : null;
for (NetworkPolicy policy : policies) {
// All policies loaded from disk will be carrier templates, and setting will also only
// set carrier templates, but we clear mobile templates just in case one is set by
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 8fd545f..5a5f9ef 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -40,7 +40,6 @@
import dalvik.system.BlockGuard;
import dalvik.system.VMRuntime;
-import java.io.FileDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -681,28 +680,6 @@
}
}
- public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
- throws InstallerException {
- if (!checkBeforeRemote()) return;
- BlockGuard.getVmPolicy().onPathAccess(filePath);
- try {
- mInstalld.installApkVerity(filePath, verityInput, contentSize);
- } catch (Exception e) {
- throw InstallerException.from(e);
- }
- }
-
- public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)
- throws InstallerException {
- if (!checkBeforeRemote()) return;
- BlockGuard.getVmPolicy().onPathAccess(filePath);
- try {
- mInstalld.assertFsverityRootHashMatches(filePath, expectedHash);
- } catch (Exception e) {
- throw InstallerException.from(e);
- }
- }
-
public boolean reconcileSecondaryDexFile(String apkPath, String packageName, int uid,
String[] isas, @Nullable String volumeUuid, int flags) throws InstallerException {
for (int i = 0; i < isas.length; i++) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index bc28cff..2d3cbfe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -12118,14 +12118,14 @@
* Returns if forced apk verification can be skipped for the whole package, including splits.
*/
private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
- if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) {
+ if (!VerityUtils.hasFsverity(pkg.getBaseApkPath())) {
return false;
}
// TODO: Allow base and splits to be verified individually.
String[] splitCodePaths = pkg.getSplitCodePaths();
if (!ArrayUtils.isEmpty(splitCodePaths)) {
for (int i = 0; i < splitCodePaths.length; i++) {
- if (!canSkipForcedApkVerification(splitCodePaths[i])) {
+ if (!VerityUtils.hasFsverity(splitCodePaths[i])) {
return false;
}
}
@@ -12134,33 +12134,6 @@
}
/**
- * Returns if forced apk verification can be skipped, depending on current FSVerity setup and
- * whether the apk contains signed root hash. Note that the signer's certificate still needs to
- * match one in a trusted source, and should be done separately.
- */
- private boolean canSkipForcedApkVerification(String apkPath) {
- if (!PackageManagerServiceUtils.isLegacyApkVerityEnabled()) {
- return VerityUtils.hasFsverity(apkPath);
- }
-
- try {
- final byte[] rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath);
- if (rootHashObserved == null) {
- return false; // APK does not contain Merkle tree root hash.
- }
- synchronized (mInstallLock) {
- // Returns whether the observed root hash matches what kernel has.
- mInstaller.assertFsverityRootHashMatches(apkPath, rootHashObserved);
- return true;
- }
- } catch (InstallerException | IOException | DigestException |
- NoSuchAlgorithmException e) {
- Slog.w(TAG, "Error in fsverity check. Fallback to full apk verification.", e);
- }
- return false;
- }
-
- /**
* Adds a new package to the internal data structures during platform initialization.
* <p>After adding, the package is known to the system and available for querying.
* <p>For packages located on the device ROM [eg. packages located in /system, /vendor,
@@ -21192,9 +21165,7 @@
*/
private void setUpFsVerityIfPossible(AndroidPackage pkg) throws InstallerException,
PrepareFailure, IOException, DigestException, NoSuchAlgorithmException {
- final boolean standardMode = PackageManagerServiceUtils.isApkVerityEnabled();
- final boolean legacyMode = PackageManagerServiceUtils.isLegacyApkVerityEnabled();
- if (!standardMode && !legacyMode) {
+ if (!PackageManagerServiceUtils.isApkVerityEnabled()) {
return;
}
@@ -21205,39 +21176,25 @@
// Collect files we care for fs-verity setup.
ArrayMap<String, String> fsverityCandidates = new ArrayMap<>();
- if (legacyMode) {
- synchronized (mLock) {
- final PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName());
- if (ps != null && ps.isPrivileged()) {
- fsverityCandidates.put(pkg.getBaseApkPath(), null);
- if (pkg.getSplitCodePaths() != null) {
- for (String splitPath : pkg.getSplitCodePaths()) {
- fsverityCandidates.put(splitPath, null);
- }
- }
- }
- }
- } else {
- // NB: These files will become only accessible if the signing key is loaded in kernel's
- // .fs-verity keyring.
- fsverityCandidates.put(pkg.getBaseApkPath(),
- VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
+ // NB: These files will become only accessible if the signing key is loaded in kernel's
+ // .fs-verity keyring.
+ fsverityCandidates.put(pkg.getBaseApkPath(),
+ VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
- final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
- pkg.getBaseApkPath());
- if (new File(dmPath).exists()) {
- fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
- }
+ final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
+ pkg.getBaseApkPath());
+ if (new File(dmPath).exists()) {
+ fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
+ }
- if (pkg.getSplitCodePaths() != null) {
- for (String path : pkg.getSplitCodePaths()) {
- fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
+ if (pkg.getSplitCodePaths() != null) {
+ for (String path : pkg.getSplitCodePaths()) {
+ fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
- final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
- if (new File(splitDmPath).exists()) {
- fsverityCandidates.put(splitDmPath,
- VerityUtils.getFsveritySignatureFilePath(splitDmPath));
- }
+ final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
+ if (new File(splitDmPath).exists()) {
+ fsverityCandidates.put(splitDmPath,
+ VerityUtils.getFsveritySignatureFilePath(splitDmPath));
}
}
}
@@ -21246,40 +21203,14 @@
final String filePath = entry.getKey();
final String signaturePath = entry.getValue();
- if (!legacyMode) {
- // fs-verity is optional for now. Only set up if signature is provided.
- if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
- try {
- VerityUtils.setUpFsverity(filePath, signaturePath);
- } catch (IOException e) {
- throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
- "Failed to enable fs-verity: " + e);
- }
- }
- continue;
- }
-
- // In legacy mode, fs-verity can only be enabled by process with CAP_SYS_ADMIN.
- final VerityUtils.SetupResult result = VerityUtils.generateApkVeritySetupData(filePath);
- if (result.isOk()) {
- if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling verity to " + filePath);
- final FileDescriptor fd = result.getUnownedFileDescriptor();
+ // fs-verity is optional for now. Only set up if signature is provided.
+ if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
try {
- final byte[] rootHash = VerityUtils.generateApkVerityRootHash(filePath);
- try {
- // A file may already have fs-verity, e.g. when reused during a split
- // install. If the measurement succeeds, no need to attempt to set up.
- mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
- } catch (InstallerException e) {
- mInstaller.installApkVerity(filePath, fd, result.getContentSize());
- mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
- }
- } finally {
- IoUtils.closeQuietly(fd);
+ VerityUtils.setUpFsverity(filePath, signaturePath);
+ } catch (IOException e) {
+ throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
+ "Failed to enable fs-verity: " + e);
}
- } else if (result.isFailed()) {
- throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
- "Failed to generate verity");
}
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 8b5abf3..8970049 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -591,12 +591,6 @@
/** Default is to not use fs-verity since it depends on kernel support. */
private static final int FSVERITY_DISABLED = 0;
- /**
- * Experimental implementation targeting priv apps, with Android specific kernel patches to
- * extend fs-verity.
- */
- private static final int FSVERITY_LEGACY = 1;
-
/** Standard fs-verity. */
private static final int FSVERITY_ENABLED = 2;
@@ -607,10 +601,6 @@
== FSVERITY_ENABLED;
}
- static boolean isLegacyApkVerityEnabled() {
- return SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED) == FSVERITY_LEGACY;
- }
-
/** Returns true to force apk verification if the package is considered privileged. */
static boolean isApkVerificationForced(@Nullable PackageSetting ps) {
// TODO(b/154310064): re-enable.
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 045a295..5047690 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -22,6 +22,7 @@
import android.content.pm.UserInfo;
import android.os.Environment;
import android.os.FileUtils;
+import android.os.RecoverySystem;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.os.SystemProperties;
@@ -115,6 +116,13 @@
// Try one last time; if we fail again we're really in trouble
prepareUserDataLI(volumeUuid, userId, userSerial,
flags | StorageManager.FLAG_STORAGE_DE, false);
+ } else {
+ try {
+ Log.e(TAG, "prepareUserData failed", e);
+ RecoverySystem.rebootPromptAndWipeUserData(mContext, "prepareUserData failed");
+ } catch (IOException e2) {
+ throw new RuntimeException("error rebooting into recovery", e2);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 1ef2025..1fa948c 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -18,28 +18,17 @@
import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
-import static android.app.usage.NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN;
-import static android.app.usage.NetworkStatsManager.FLAG_POLL_FORCE;
-import static android.app.usage.NetworkStatsManager.FLAG_POLL_ON_OPEN;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static android.net.NetworkIdentity.OEM_PAID;
-import static android.net.NetworkIdentity.OEM_PRIVATE;
-import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
-import static android.net.NetworkStats.METERED_ALL;
import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkStats.ROAMING_ALL;
import static android.net.NetworkTemplate.MATCH_ETHERNET;
-import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
-import static android.net.NetworkTemplate.MATCH_WIFI_WILDCARD;
-import static android.net.NetworkTemplate.NETWORK_TYPE_ALL;
+import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.NetworkTemplate.OEM_MANAGED_ALL;
-import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
-import static android.net.NetworkTemplate.buildTemplateMobileWithRatType;
-import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
-import static android.net.NetworkTemplate.getAllCollapsedRatTypes;
+import static android.net.NetworkTemplate.OEM_MANAGED_PAID;
+import static android.net.NetworkTemplate.OEM_MANAGED_PRIVATE;
import static android.os.Debug.getIonHeapsSizeKb;
import static android.os.Process.LAST_SHARED_APPLICATION_GID;
import static android.os.Process.getUidForPid;
@@ -80,6 +69,7 @@
import android.app.RuntimeAppOpAccessMessage;
import android.app.StatsManager;
import android.app.StatsManager.PullAtomMetadata;
+import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.UidTraffic;
@@ -93,8 +83,6 @@
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.net.ConnectivityManager;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
import android.net.Network;
import android.net.NetworkRequest;
import android.net.NetworkStats;
@@ -188,6 +176,7 @@
import com.android.internal.os.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.FrameworkStatsLog;
+import com.android.net.module.util.NetworkStatsUtils;
import com.android.role.RoleManagerLocal;
import com.android.server.BinderCallsStatsService;
import com.android.server.LocalManagerRegistry;
@@ -235,7 +224,7 @@
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.function.BiConsumer;
+import java.util.function.Function;
/**
* SystemService containing PullAtomCallbacks that are registered with statsd.
@@ -331,6 +320,7 @@
private WifiManager mWifiManager;
private TelephonyManager mTelephony;
private SubscriptionManager mSubscriptionManager;
+ private NetworkStatsManager mNetworkStatsManager;
@GuardedBy("mKernelWakelockLock")
private KernelWakelockReader mKernelWakelockReader;
@@ -776,7 +766,7 @@
mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
mStatsSubscriptionsListener = new StatsSubscriptionsListener(mSubscriptionManager);
mStorageManager = (StorageManager) mContext.getSystemService(StorageManager.class);
-
+ mNetworkStatsManager = mContext.getSystemService(NetworkStatsManager.class);
// Initialize DiskIO
mStoragedUidIoStatsReader = new StoragedUidIoStatsReader();
@@ -966,32 +956,6 @@
registerOemManagedBytesTransfer();
}
- /**
- * Return the {@code INetworkStatsSession} object that holds the necessary properties needed
- * for the subsequent queries to {@link com.android.server.net.NetworkStatsService}. Or
- * null if the service or binder cannot be obtained. Calling this method will trigger poll
- * in NetworkStatsService with once per 15 seconds rate-limit, unless {@code bypassRateLimit}
- * is set to true. This is needed in {@link #getUidNetworkStatsSnapshotForTemplate}, where
- * bypassing the limit is necessary for perfd to supply realtime stats to developers looking at
- * the network usage of their app.
- */
- @Nullable
- private INetworkStatsSession getNetworkStatsSession(boolean bypassRateLimit) {
- final INetworkStatsService networkStatsService =
- INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
- if (networkStatsService == null) return null;
-
- try {
- return networkStatsService.openSessionForUsageStats(
- FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN | (bypassRateLimit ? FLAG_POLL_FORCE
- : FLAG_POLL_ON_OPEN), mContext.getOpPackageName());
- } catch (RemoteException e) {
- Slog.e(TAG, "Cannot get NetworkStats session", e);
- return null;
- }
- }
-
private IThermalService getIThermalService() {
synchronized (mThermalLock) {
if (mThermalService == null) {
@@ -1122,8 +1086,8 @@
case FrameworkStatsLog.WIFI_BYTES_TRANSFER: {
final NetworkStats stats = getUidNetworkStatsSnapshotForTransport(TRANSPORT_WIFI);
if (stats != null) {
- ret.add(new NetworkStatsExt(stats.groupedByUid(), new int[] {TRANSPORT_WIFI},
- /*slicedByFgbg=*/false));
+ ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
+ new int[] {TRANSPORT_WIFI}, /*slicedByFgbg=*/false));
}
break;
}
@@ -1139,7 +1103,7 @@
final NetworkStats stats =
getUidNetworkStatsSnapshotForTransport(TRANSPORT_CELLULAR);
if (stats != null) {
- ret.add(new NetworkStatsExt(stats.groupedByUid(),
+ ret.add(new NetworkStatsExt(sliceNetworkStatsByUid(stats),
new int[] {TRANSPORT_CELLULAR}, /*slicedByFgbg=*/false));
}
break;
@@ -1155,9 +1119,10 @@
}
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED: {
final NetworkStats wifiStats = getUidNetworkStatsSnapshotForTemplate(
- buildTemplateWifiWildcard(), /*includeTags=*/true);
+ new NetworkTemplate.Builder(MATCH_WIFI).build(), /*includeTags=*/true);
final NetworkStats cellularStats = getUidNetworkStatsSnapshotForTemplate(
- buildTemplateMobileWildcard(), /*includeTags=*/true);
+ new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setMeteredness(METERED_YES).build(), /*includeTags=*/true);
if (wifiStats != null && cellularStats != null) {
final NetworkStats stats = wifiStats.add(cellularStats);
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
@@ -1202,13 +1167,14 @@
Slog.e(TAG, "baseline is null for " + atomTag + ", return.");
return StatsManager.PULL_SKIP;
}
+
final NetworkStatsExt diff = new NetworkStatsExt(
- item.stats.subtract(baseline.stats).removeEmptyEntries(), item.transports,
+ removeEmptyEntries(item.stats.subtract(baseline.stats)), item.transports,
item.slicedByFgbg, item.slicedByTag, item.slicedByMetered, item.ratType,
item.subInfo, item.oemManaged);
// If no diff, skip.
- if (diff.stats.size() == 0) continue;
+ if (!diff.stats.iterator().hasNext()) continue;
switch (atomTag) {
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
@@ -1227,25 +1193,32 @@
return StatsManager.PULL_SUCCESS;
}
+ @NonNull private static NetworkStats removeEmptyEntries(NetworkStats stats) {
+ NetworkStats ret = new NetworkStats(0, 1);
+ for (NetworkStats.Entry e : stats) {
+ if (e.getRxBytes() != 0 || e.getRxPackets() != 0 || e.getTxBytes() != 0
+ || e.getTxPackets() != 0 || e.getOperations() != 0) {
+ ret = ret.addEntry(e);
+ }
+ }
+ return ret;
+ }
+
private void addNetworkStats(int atomTag, @NonNull List<StatsEvent> ret,
@NonNull NetworkStatsExt statsExt) {
- int size = statsExt.stats.size();
- final NetworkStats.Entry entry = new NetworkStats.Entry(); // For recycling
- for (int j = 0; j < size; j++) {
- statsExt.stats.getValues(j, entry);
+ for (NetworkStats.Entry entry : statsExt.stats) {
StatsEvent statsEvent;
-
if (statsExt.slicedByFgbg) {
// MobileBytesTransferByFgBg atom or WifiBytesTransferByFgBg atom.
statsEvent = FrameworkStatsLog.buildStatsEvent(
- atomTag, entry.uid,
- (entry.set > 0), entry.rxBytes, entry.rxPackets, entry.txBytes,
- entry.txPackets);
+ atomTag, entry.getUid(),
+ (entry.getSet() > 0), entry.getRxBytes(), entry.getRxPackets(),
+ entry.getTxBytes(), entry.getTxPackets());
} else {
// MobileBytesTransfer atom or WifiBytesTransfer atom.
statsEvent = FrameworkStatsLog.buildStatsEvent(
- atomTag, entry.uid, entry.rxBytes,
- entry.rxPackets, entry.txBytes, entry.txPackets);
+ atomTag, entry.getUid(), entry.getRxBytes(),
+ entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets());
}
ret.add(statsEvent);
}
@@ -1253,33 +1226,31 @@
private void addBytesTransferByTagAndMeteredAtoms(@NonNull NetworkStatsExt statsExt,
@NonNull List<StatsEvent> pulledData) {
- final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
- for (int i = 0; i < statsExt.stats.size(); i++) {
- statsExt.stats.getValues(i, entry);
+ for (NetworkStats.Entry entry : statsExt.stats) {
pulledData.add(FrameworkStatsLog.buildStatsEvent(
- FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.uid,
- entry.metered == NetworkStats.METERED_YES, entry.tag, entry.rxBytes,
- entry.rxPackets, entry.txBytes, entry.txPackets));
+ FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED, entry.getUid(),
+ entry.getMetered() == NetworkStats.METERED_YES, entry.getTag(),
+ entry.getRxBytes(), entry.getRxPackets(), entry.getTxBytes(),
+ entry.getTxPackets()));
}
}
private void addDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
@NonNull List<StatsEvent> pulledData) {
- // Workaround for 5G NSA mode, see {@link NetworkTemplate#NETWORK_TYPE_5G_NSA}.
+ // Workaround for 5G NSA mode, see {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
// 5G NSA mode means the primary cell is LTE with a secondary connection to an
// NR cell. To mitigate risk, NetworkStats is currently storing this state as
// a fake RAT type rather than storing the boolean separately.
- final boolean is5GNsa = statsExt.ratType == NetworkTemplate.NETWORK_TYPE_5G_NSA;
+ final boolean is5GNsa = statsExt.ratType == NetworkStatsManager.NETWORK_TYPE_5G_NSA;
// Report NR connected in 5G non-standalone mode, or if the RAT type is NR to begin with.
final boolean isNR = is5GNsa || statsExt.ratType == TelephonyManager.NETWORK_TYPE_NR;
- final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
- for (int i = 0; i < statsExt.stats.size(); i++) {
- statsExt.stats.getValues(i, entry);
+ for (NetworkStats.Entry entry : statsExt.stats) {
pulledData.add(FrameworkStatsLog.buildStatsEvent(
- FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER, entry.set, entry.rxBytes,
- entry.rxPackets, entry.txBytes, entry.txPackets,
+ FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER,
+ entry.getSet(), entry.getRxBytes(), entry.getRxPackets(),
+ entry.getTxBytes(), entry.getTxPackets(),
is5GNsa ? TelephonyManager.NETWORK_TYPE_LTE : statsExt.ratType,
// Fill information about subscription, these cannot be null since invalid data
// would be filtered when adding into subInfo list.
@@ -1293,38 +1264,35 @@
private void addOemDataUsageBytesTransferAtoms(@NonNull NetworkStatsExt statsExt,
@NonNull List<StatsEvent> pulledData) {
- final NetworkStats.Entry entry = new NetworkStats.Entry(); // for recycling
final int oemManaged = statsExt.oemManaged;
for (final int transport : statsExt.transports) {
- for (int i = 0; i < statsExt.stats.size(); i++) {
- statsExt.stats.getValues(i, entry);
+ for (NetworkStats.Entry entry : statsExt.stats) {
pulledData.add(FrameworkStatsLog.buildStatsEvent(
- FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.uid, (entry.set > 0),
- oemManaged, transport, entry.rxBytes, entry.rxPackets, entry.txBytes,
- entry.txPackets));
+ FrameworkStatsLog.OEM_MANAGED_BYTES_TRANSFER, entry.getUid(),
+ (entry.getSet() > 0), oemManaged, transport, entry.getRxBytes(),
+ entry.getRxPackets(), entry.getTxBytes(), entry.getTxPackets()));
}
}
}
@NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForOemManaged() {
- final int[] transports = new int[] {MATCH_ETHERNET, MATCH_MOBILE_WILDCARD,
- MATCH_WIFI_WILDCARD};
- final int[] oemManagedTypes = new int[] {OEM_PAID | OEM_PRIVATE, OEM_PAID, OEM_PRIVATE};
+ final int[] matchRules = new int[] {MATCH_ETHERNET, MATCH_MOBILE, MATCH_WIFI};
+ final int[] oemManagedTypes = new int[] {OEM_MANAGED_PAID | OEM_MANAGED_PRIVATE,
+ OEM_MANAGED_PAID, OEM_MANAGED_PRIVATE};
final List<NetworkStatsExt> ret = new ArrayList<>();
- for (final int transport : transports) {
+ for (final int matchRule : matchRules) {
for (final int oemManaged : oemManagedTypes) {
- /* A null subscriberId will set wildcard=true, since we aren't trying to select a
- specific ssid or subscriber. */
- final NetworkTemplate template = new NetworkTemplate(transport,
- /*subscriberId=*/null, /*matchSubscriberIds=*/null, /*networkId=*/null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
- oemManaged);
+ // Subscriber Ids and Wifi Network Keys will not be set since the purpose is to
+ // slice statistics of different OEM managed networks among all network types.
+ // Thus, specifying networks through their identifiers are not needed.
+ final NetworkTemplate template = new NetworkTemplate.Builder(matchRule)
+ .setOemManaged(oemManaged).build();
final NetworkStats stats = getUidNetworkStatsSnapshotForTemplate(template, true);
if (stats != null) {
ret.add(new NetworkStatsExt(sliceNetworkStatsByUidTagAndMetered(stats),
- new int[] {transport}, /*slicedByFgbg=*/true, /*slicedByTag=*/true,
+ new int[] {matchRule}, /*slicedByFgbg=*/true, /*slicedByTag=*/true,
/*slicedByMetered=*/true, TelephonyManager.NETWORK_TYPE_UNKNOWN,
/*subInfo=*/null, oemManaged));
}
@@ -1338,10 +1306,18 @@
* Create a snapshot of NetworkStats for a given transport.
*/
@Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
- final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
- ? NetworkTemplate.buildTemplateMobileWithRatType(
- /*subscriptionId=*/null, NETWORK_TYPE_ALL, METERED_YES)
- : NetworkTemplate.buildTemplateWifiWildcard();
+ NetworkTemplate template = null;
+ switch (transport) {
+ case TRANSPORT_CELLULAR:
+ template = new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setMeteredness(METERED_YES).build();
+ break;
+ case TRANSPORT_WIFI:
+ template = new NetworkTemplate.Builder(MATCH_WIFI).build();
+ break;
+ default:
+ Log.wtf(TAG, "Unexpected transport.");
+ }
return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
}
@@ -1357,22 +1333,32 @@
final long currentTimeInMillis = MICROSECONDS.toMillis(SystemClock.currentTimeMicro());
final long bucketDuration = Settings.Global.getLong(mContext.getContentResolver(),
NETSTATS_UID_BUCKET_DURATION, NETSTATS_UID_DEFAULT_BUCKET_DURATION_MS);
- try {
- // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats
- // history when query in every second in order to show realtime statistics. However,
- // this is not a good long-term solution since NetworkStatsService will make frequent
- // I/O and also block main thread when polling.
- // Consider making perfd queries NetworkStatsService directly.
- final NetworkStats stats = getNetworkStatsSession(template.getMatchRule()
- == NetworkTemplate.MATCH_WIFI_WILDCARD).getSummaryForAllUid(template,
- currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
- currentTimeInMillis, includeTags);
- return stats;
- } catch (RemoteException | NullPointerException e) {
- Slog.e(TAG, "Pulling netstats for template=" + template + " and includeTags="
- + includeTags + " causes error", e);
+
+ // TODO (b/156313635): This is short-term hack to allow perfd gets updated networkStats
+ // history when query in every second in order to show realtime statistics. However,
+ // this is not a good long-term solution since NetworkStatsService will make frequent
+ // I/O and also block main thread when polling.
+ // Consider making perfd queries NetworkStatsService directly.
+ if (template.getMatchRule() == MATCH_WIFI && template.getSubscriberIds().isEmpty()) {
+ mNetworkStatsManager.forceUpdate();
}
- return null;
+
+ final android.app.usage.NetworkStats queryNonTaggedStats =
+ mNetworkStatsManager.querySummary(
+ template, currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
+ currentTimeInMillis);
+
+ final NetworkStats nonTaggedStats =
+ NetworkStatsUtils.fromPublicNetworkStats(queryNonTaggedStats);
+ if (!includeTags) return nonTaggedStats;
+
+ final android.app.usage.NetworkStats queryTaggedStats =
+ mNetworkStatsManager.queryTaggedSummary(template,
+ currentTimeInMillis - elapsedMillisSinceBoot - bucketDuration,
+ currentTimeInMillis);
+ final NetworkStats taggedStats =
+ NetworkStatsUtils.fromPublicNetworkStats(queryTaggedStats);
+ return nonTaggedStats.add(taggedStats);
}
@NonNull private List<NetworkStatsExt> getDataUsageBytesTransferSnapshotForSub(
@@ -1380,8 +1366,10 @@
final List<NetworkStatsExt> ret = new ArrayList<>();
for (final int ratType : getAllCollapsedRatTypes()) {
final NetworkTemplate template =
- buildTemplateMobileWithRatType(subInfo.subscriberId, ratType,
- METERED_YES);
+ new NetworkTemplate.Builder(MATCH_MOBILE)
+ .setSubscriberIds(Set.of(subInfo.subscriberId))
+ .setRatType(ratType)
+ .setMeteredness(METERED_YES).build();
final NetworkStats stats =
getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
if (stats != null) {
@@ -1394,27 +1382,72 @@
return ret;
}
+ /**
+ * Return all supported collapsed RAT types that could be returned by
+ * {@link android.app.usage.NetworkStatsManager#getCollapsedRatType(int)}.
+ */
+ @NonNull
+ private static int[] getAllCollapsedRatTypes() {
+ final int[] ratTypes = TelephonyManager.getAllNetworkTypes();
+ final HashSet<Integer> collapsedRatTypes = new HashSet<>();
+ for (final int ratType : ratTypes) {
+ collapsedRatTypes.add(NetworkStatsManager.getCollapsedRatType(ratType));
+ }
+ // Add NETWORK_TYPE_5G_NSA to the returned list since 5G NSA is a virtual RAT type and
+ // it is not in TelephonyManager#NETWORK_TYPE_* constants.
+ // See {@link NetworkStatsManager#NETWORK_TYPE_5G_NSA}.
+ collapsedRatTypes.add(
+ NetworkStatsManager.getCollapsedRatType(NetworkStatsManager.NETWORK_TYPE_5G_NSA));
+ // Ensure that unknown type is returned.
+ collapsedRatTypes.add(TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ return com.android.net.module.util.CollectionUtils.toIntArray(collapsedRatTypes);
+ }
+
+ @NonNull private NetworkStats sliceNetworkStatsByUid(@NonNull NetworkStats stats) {
+ return sliceNetworkStats(stats,
+ (entry) -> {
+ return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
+ NetworkStats.SET_ALL, NetworkStats.TAG_NONE,
+ NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+ NetworkStats.DEFAULT_NETWORK_ALL,
+ entry.getRxBytes(), entry.getRxPackets(),
+ entry.getTxBytes(), entry.getTxPackets(), 0);
+ });
+ }
+
@NonNull private NetworkStats sliceNetworkStatsByFgbg(@NonNull NetworkStats stats) {
return sliceNetworkStats(stats,
- (newEntry, oldEntry) -> {
- newEntry.set = oldEntry.set;
+ (entry) -> {
+ return new NetworkStats.Entry(null /* IFACE_ALL */, NetworkStats.UID_ALL,
+ entry.getSet(), NetworkStats.TAG_NONE,
+ NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+ NetworkStats.DEFAULT_NETWORK_ALL,
+ entry.getRxBytes(), entry.getRxPackets(),
+ entry.getTxBytes(), entry.getTxPackets(), 0);
});
}
@NonNull private NetworkStats sliceNetworkStatsByUidAndFgbg(@NonNull NetworkStats stats) {
return sliceNetworkStats(stats,
- (newEntry, oldEntry) -> {
- newEntry.uid = oldEntry.uid;
- newEntry.set = oldEntry.set;
+ (entry) -> {
+ return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
+ entry.getSet(), NetworkStats.TAG_NONE,
+ NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+ NetworkStats.DEFAULT_NETWORK_ALL,
+ entry.getRxBytes(), entry.getRxPackets(),
+ entry.getTxBytes(), entry.getTxPackets(), 0);
});
}
@NonNull private NetworkStats sliceNetworkStatsByUidTagAndMetered(@NonNull NetworkStats stats) {
return sliceNetworkStats(stats,
- (newEntry, oldEntry) -> {
- newEntry.uid = oldEntry.uid;
- newEntry.tag = oldEntry.tag;
- newEntry.metered = oldEntry.metered;
+ (entry) -> {
+ return new NetworkStats.Entry(null /* IFACE_ALL */, entry.getUid(),
+ NetworkStats.SET_ALL, entry.getTag(),
+ entry.getMetered(), NetworkStats.ROAMING_ALL,
+ NetworkStats.DEFAULT_NETWORK_ALL,
+ entry.getRxBytes(), entry.getRxPackets(),
+ entry.getTxBytes(), entry.getTxPackets(), 0);
});
}
@@ -1424,46 +1457,27 @@
*
* This function iterates through each NetworkStats.Entry, sets its dimensions equal to the
* default state (with the presumption that we don't want to slice on anything), and then
- * applies the slicer lambda to allow users to control which dimensions to slice on. This is
- * adapted from groupedByUid within NetworkStats.java
+ * applies the slicer lambda to allow users to control which dimensions to slice on.
*
- * @param slicer An operation taking into two parameters, new NetworkStats.Entry and old
- * NetworkStats.Entry, that should be used to copy state from the old to the new.
+ * @param slicer An operation taking one parameter, NetworkStats.Entry, that should be used to
+ * get the state from entry to replace the default value.
* This is useful for slicing by particular dimensions. For example, if we wished
* to slice by uid and tag, we could write the following lambda:
- * (new, old) -> {
- * new.uid = old.uid;
- * new.tag = old.tag;
+ * (entry) -> {
+ * return new NetworkStats.Entry(null, entry.getUid(),
+ * NetworkStats.SET_ALL, entry.getTag(),
+ * NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+ * NetworkStats.DEFAULT_NETWORK_ALL,
+ * entry.getRxBytes(), entry.getRxPackets(),
+ * entry.getTxBytes(), entry.getTxPackets(), 0);
* }
- * If no slicer is provided, the data is not sliced by any dimensions.
* @return new NeworkStats object appropriately sliced
*/
@NonNull private NetworkStats sliceNetworkStats(@NonNull NetworkStats stats,
- @Nullable BiConsumer<NetworkStats.Entry, NetworkStats.Entry> slicer) {
- final NetworkStats ret = new NetworkStats(stats.getElapsedRealtime(), 1);
-
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- entry.uid = NetworkStats.UID_ALL;
- entry.iface = NetworkStats.IFACE_ALL;
- entry.set = NetworkStats.SET_ALL;
- entry.tag = NetworkStats.TAG_NONE;
- entry.metered = NetworkStats.METERED_ALL;
- entry.roaming = NetworkStats.ROAMING_ALL;
- entry.defaultNetwork = NetworkStats.DEFAULT_NETWORK_ALL;
-
- final NetworkStats.Entry recycle = new NetworkStats.Entry(); // used for retrieving values
- for (int i = 0; i < stats.size(); i++) {
- stats.getValues(i, recycle);
- if (slicer != null) {
- slicer.accept(entry, recycle);
- }
-
- entry.rxBytes = recycle.rxBytes;
- entry.rxPackets = recycle.rxPackets;
- entry.txBytes = recycle.txBytes;
- entry.txPackets = recycle.txPackets;
- // Operations purposefully omitted since we don't use them for statsd.
- ret.combineValues(entry);
+ @NonNull Function<NetworkStats.Entry, NetworkStats.Entry> slicer) {
+ NetworkStats ret = new NetworkStats(0, 1);
+ for (NetworkStats.Entry e : stats) {
+ ret = ret.addEntry(slicer.apply(e));
}
return ret;
}
diff --git a/services/core/java/com/android/server/tracing/TracingServiceProxy.java b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
index ff2f08b..27c0bee 100644
--- a/services/core/java/com/android/server/tracing/TracingServiceProxy.java
+++ b/services/core/java/com/android/server/tracing/TracingServiceProxy.java
@@ -15,34 +15,56 @@
*/
package com.android.server.tracing;
+import android.Manifest;
+import android.annotation.NonNull;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
import android.os.Binder;
+import android.os.IMessenger;
+import android.os.Message;
+import android.os.ParcelFileDescriptor;
+import android.os.ParcelFileDescriptor.AutoCloseInputStream;
+import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
import android.os.UserHandle;
+import android.service.tracing.TraceReportService;
import android.tracing.ITracingServiceProxy;
+import android.tracing.TraceReportParams;
import android.util.Log;
+import android.util.LruCache;
+import android.util.Slog;
+import com.android.internal.infra.ServiceConnector;
import com.android.server.SystemService;
+import java.io.IOException;
+
/**
* TracingServiceProxy is the system_server intermediary between the Perfetto tracing daemon and the
- * system tracing app Traceur.
+ * other components (e.g. system tracing app Traceur, trace reporting apps).
*
* Access to this service is restricted via SELinux. Normal apps do not have access.
*
* @hide
*/
public class TracingServiceProxy extends SystemService {
- private static final String TAG = "TracingServiceProxy";
-
public static final String TRACING_SERVICE_PROXY_BINDER_NAME = "tracing.proxy";
-
+ private static final String TAG = "TracingServiceProxy";
private static final String TRACING_APP_PACKAGE_NAME = "com.android.traceur";
private static final String TRACING_APP_ACTIVITY = "com.android.traceur.StopTraceService";
+ private static final int MAX_CACHED_REPORTER_SERVICES = 8;
+
+ // The maximum size of the trace allowed if the option |usePipeForTesting| is set.
+ // Note: this size MUST be smaller than the buffer size of the pipe (i.e. what you can
+ // write to the pipe without blocking) to avoid system_server blocking on this.
+ // (on Linux, the minimum value is 4K i.e. 1 minimally sized page).
+ private static final int MAX_FILE_SIZE_BYTES_TO_PIPE = 1024;
+
// Keep this in sync with the definitions in TraceService
private static final String INTENT_ACTION_NOTIFY_SESSION_STOPPED =
"com.android.traceur.NOTIFY_SESSION_STOPPED";
@@ -51,16 +73,22 @@
private final Context mContext;
private final PackageManager mPackageManager;
+ private final LruCache<ComponentName, ServiceConnector<IMessenger>> mCachedReporterServices;
private final ITracingServiceProxy.Stub mTracingServiceProxy = new ITracingServiceProxy.Stub() {
/**
- * Notifies system tracing app that a tracing session has ended. If a session is repurposed
- * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
- * there is no buffer available to dump.
- */
+ * Notifies system tracing app that a tracing session has ended. If a session is repurposed
+ * for use in a bugreport, sessionStolen can be set to indicate that tracing has ended but
+ * there is no buffer available to dump.
+ */
@Override
public void notifyTraceSessionEnded(boolean sessionStolen) {
- notifyTraceur(sessionStolen);
+ TracingServiceProxy.this.notifyTraceur(sessionStolen);
+ }
+
+ @Override
+ public void reportTrace(@NonNull TraceReportParams params) {
+ TracingServiceProxy.this.reportTrace(params);
}
};
@@ -68,6 +96,7 @@
super(context);
mContext = context;
mPackageManager = context.getPackageManager();
+ mCachedReporterServices = new LruCache<>(MAX_CACHED_REPORTER_SERVICES);
}
@Override
@@ -103,4 +132,119 @@
Log.e(TAG, "Failed to locate Traceur", e);
}
}
+
+ private void reportTrace(@NonNull TraceReportParams params) {
+ // We don't need to do any permission checks on the caller because access
+ // to this service is guarded by SELinux.
+ ComponentName component = new ComponentName(params.reporterPackageName,
+ params.reporterClassName);
+ if (!hasBindServicePermission(component)) {
+ return;
+ }
+ boolean hasDumpPermission = hasPermission(component, Manifest.permission.DUMP);
+ boolean hasUsageStatsPermission = hasPermission(component,
+ Manifest.permission.PACKAGE_USAGE_STATS);
+ if (!hasDumpPermission || !hasUsageStatsPermission) {
+ return;
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ reportTrace(getOrCreateReporterService(component), params);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void reportTrace(
+ @NonNull ServiceConnector<IMessenger> reporterService,
+ @NonNull TraceReportParams params) {
+ reporterService.post(messenger -> {
+ if (params.usePipeForTesting) {
+ ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
+ try (AutoCloseInputStream i = new AutoCloseInputStream(params.fd)) {
+ try (AutoCloseOutputStream o = new AutoCloseOutputStream(pipe[1])) {
+ byte[] array = i.readNBytes(MAX_FILE_SIZE_BYTES_TO_PIPE);
+ if (array.length == MAX_FILE_SIZE_BYTES_TO_PIPE) {
+ throw new IllegalArgumentException(
+ "Trace file too large when |usePipeForTesting| is set.");
+ }
+ o.write(array);
+ }
+ }
+ params.fd = pipe[0];
+ }
+
+ Message message = Message.obtain();
+ message.what = TraceReportService.MSG_REPORT_TRACE;
+ message.obj = params;
+ messenger.send(message);
+ }).whenComplete((res, err) -> {
+ if (err != null) {
+ Slog.e(TAG, "Failed to report trace", err);
+ }
+ try {
+ params.fd.close();
+ } catch (IOException ignored) {
+ }
+ });
+ }
+
+ private ServiceConnector<IMessenger> getOrCreateReporterService(
+ @NonNull ComponentName component) {
+ ServiceConnector<IMessenger> connector = mCachedReporterServices.get(component);
+ if (connector == null) {
+ Intent intent = new Intent();
+ intent.setComponent(component);
+ connector = new ServiceConnector.Impl<IMessenger>(
+ mContext, intent,
+ Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY,
+ mContext.getUser().getIdentifier(), IMessenger.Stub::asInterface) {
+ private static final long DISCONNECT_TIMEOUT_MS = 15_000;
+ private static final long REQUEST_TIMEOUT_MS = 10_000;
+
+ @Override
+ protected long getAutoDisconnectTimeoutMs() {
+ return DISCONNECT_TIMEOUT_MS;
+ }
+
+ @Override
+ protected long getRequestTimeoutMs() {
+ return REQUEST_TIMEOUT_MS;
+ }
+ };
+ mCachedReporterServices.put(intent.getComponent(), connector);
+ }
+ return connector;
+ }
+
+ private boolean hasPermission(@NonNull ComponentName componentName,
+ @NonNull String permission) throws SecurityException {
+ if (mPackageManager.checkPermission(permission, componentName.getPackageName())
+ != PackageManager.PERMISSION_GRANTED) {
+ Slog.e(TAG,
+ "Trace reporting service " + componentName.toShortString() + " does not have "
+ + permission + " permission");
+ return false;
+ }
+ return true;
+ }
+
+ private boolean hasBindServicePermission(@NonNull ComponentName componentName) {
+ ServiceInfo info;
+ try {
+ info = mPackageManager.getServiceInfo(componentName, 0);
+ } catch (NameNotFoundException ex) {
+ Slog.e(TAG,
+ "Trace reporting service " + componentName.toShortString() + " does not exist");
+ return false;
+ }
+ if (!Manifest.permission.BIND_TRACE_REPORT_SERVICE.equals(info.permission)) {
+ Slog.e(TAG,
+ "Trace reporting service " + componentName.toShortString()
+ + " does not request " + Manifest.permission.BIND_TRACE_REPORT_SERVICE
+ + " permission; instead requests " + info.permission);
+ return false;
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index e0cc8e1..f29c40f 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -39,10 +39,13 @@
import android.net.vcn.VcnGatewayConnectionConfig;
import android.net.vcn.VcnManager.VcnErrorCode;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.Message;
import android.os.ParcelUuid;
import android.provider.Settings;
+import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -57,6 +60,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -148,6 +152,10 @@
@NonNull private final VcnContentResolver mContentResolver;
@NonNull private final ContentObserver mMobileDataSettingsObserver;
+ @NonNull
+ private final Map<Integer, VcnUserMobileDataStateListener> mMobileDataStateListeners =
+ new ArrayMap<>();
+
/**
* Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs.
*
@@ -221,6 +229,9 @@
// Update mIsMobileDataEnabled before starting handling of NetworkRequests.
mIsMobileDataEnabled = getMobileDataStatus();
+ // Register mobile data state listeners.
+ updateMobileDataStateListeners();
+
// Register to receive cached and future NetworkRequests
mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener);
}
@@ -348,6 +359,12 @@
gatewayConnection.teardownAsynchronously();
}
+ // Unregister MobileDataStateListeners
+ for (VcnUserMobileDataStateListener listener : mMobileDataStateListeners.values()) {
+ getTelephonyManager().unregisterTelephonyCallback(listener);
+ }
+ mMobileDataStateListeners.clear();
+
mCurrentStatus = VCN_STATUS_CODE_INACTIVE;
}
@@ -454,11 +471,40 @@
gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot);
}
+ updateMobileDataStateListeners();
+
// Update the mobile data state after updating the subscription snapshot as a change in
// subIds for a subGroup may affect the mobile data state.
handleMobileDataToggled();
}
+ private void updateMobileDataStateListeners() {
+ final Set<Integer> subIdsInGroup = mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup);
+ final HandlerExecutor executor = new HandlerExecutor(this);
+
+ // Register new callbacks
+ for (int subId : subIdsInGroup) {
+ if (!mMobileDataStateListeners.containsKey(subId)) {
+ final VcnUserMobileDataStateListener listener =
+ new VcnUserMobileDataStateListener();
+
+ getTelephonyManagerForSubid(subId).registerTelephonyCallback(executor, listener);
+ mMobileDataStateListeners.put(subId, listener);
+ }
+ }
+
+ // Unregister old callbacks
+ Iterator<Entry<Integer, VcnUserMobileDataStateListener>> iterator =
+ mMobileDataStateListeners.entrySet().iterator();
+ while (iterator.hasNext()) {
+ final Entry<Integer, VcnUserMobileDataStateListener> entry = iterator.next();
+ if (!subIdsInGroup.contains(entry.getKey())) {
+ getTelephonyManager().unregisterTelephonyCallback(entry.getValue());
+ iterator.remove();
+ }
+ }
+ }
+
private void handleMobileDataToggled() {
final boolean oldMobileDataEnabledStatus = mIsMobileDataEnabled;
mIsMobileDataEnabled = getMobileDataStatus();
@@ -493,11 +539,8 @@
}
private boolean getMobileDataStatus() {
- final TelephonyManager genericTelMan =
- mVcnContext.getContext().getSystemService(TelephonyManager.class);
-
for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) {
- if (genericTelMan.createForSubscriptionId(subId).isDataEnabled()) {
+ if (getTelephonyManagerForSubid(subId).isDataEnabled()) {
return true;
}
}
@@ -517,6 +560,14 @@
return request.canBeSatisfiedBy(builder.build());
}
+ private TelephonyManager getTelephonyManager() {
+ return mVcnContext.getContext().getSystemService(TelephonyManager.class);
+ }
+
+ private TelephonyManager getTelephonyManagerForSubid(int subid) {
+ return getTelephonyManager().createForSubscriptionId(subid);
+ }
+
private String getLogPrefix() {
return "["
+ LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
@@ -670,6 +721,16 @@
}
}
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ class VcnUserMobileDataStateListener extends TelephonyCallback
+ implements TelephonyCallback.UserMobileDataStateListener {
+
+ @Override
+ public void onUserMobileDataStateChanged(boolean enabled) {
+ sendMessage(obtainMessage(MSG_EVENT_MOBILE_DATA_TOGGLED));
+ }
+ }
+
/** External dependencies used by Vcn, for injection in tests */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public static class Dependencies {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 6149bcf..b685d48 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1038,6 +1038,8 @@
pw.print(" forceNewConfig="); pw.println(forceNewConfig);
pw.print(prefix); pw.print("mActivityType=");
pw.println(activityTypeToString(getActivityType()));
+ pw.print(prefix); pw.print("mImeInsetsFrozenUntilStartInput=");
+ pw.println(mImeInsetsFrozenUntilStartInput);
if (requestedVrComponent != null) {
pw.print(prefix);
pw.print("requestedVrComponent=");
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9335846..bb8d6ef 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3969,11 +3969,11 @@
* which controls the visibility and animation of the input method window.
*/
void updateImeInputAndControlTarget(WindowState target) {
+ if (target != null && target.mActivityRecord != null) {
+ target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
+ }
if (mImeInputTarget != target) {
ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
- if (target != null && target.mActivityRecord != null) {
- target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
- }
setImeInputTarget(target);
updateImeControlTarget();
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index c7bf8ecf..94f0e24 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -85,6 +85,8 @@
private boolean mAnimationStartDelayed;
+ private boolean mAnimationFinished;
+
/**
* @param animatable The object to animate.
* @param staticAnimationFinishedCallback Callback to invoke when an animation has finished
@@ -134,6 +136,7 @@
|| anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
resetAndInvokeFinish.run();
}
+ mAnimationFinished = true;
}
};
}
@@ -289,6 +292,9 @@
Slog.w(TAG, "Unable to transfer animation, surface or parent is null");
cancelAnimation();
return;
+ } else if (from.mAnimationFinished) {
+ Slog.w(TAG, "Unable to transfer animation, because " + from + " animation is finished");
+ return;
}
endDelayingAnimationStart();
final Transaction t = mAnimatable.getPendingTransaction();
@@ -367,6 +373,7 @@
SurfaceControl leash = mLeash;
mLeash = null;
final boolean scheduleAnim = removeLeash(t, mAnimatable, leash, destroyLeash);
+ mAnimationFinished = false;
if (scheduleAnim) {
mService.scheduleAnimationLocked();
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e7005da..e48b5e1 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -141,8 +141,8 @@
"libutils",
"libhwui",
"libbpf_android",
- "libnetdbpf",
"libnetdutils",
+ "libnetworkstats",
"libpsi",
"libdataloader",
"libincfs",
diff --git a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
index ccb4f59..cba54b3 100644
--- a/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
+++ b/services/core/jni/com_android_server_UsbAlsaJackDetector.cpp
@@ -25,7 +25,6 @@
#include <stdio.h>
#include <string.h>
-#include <asm/byteorder.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
index d29d3fc..9917bcb 100644
--- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp
+++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp
@@ -15,16 +15,14 @@
*/
#define LOG_TAG "UsbHostManagerJNI"
-#include "utils/Log.h"
-
+#include <nativehelper/JNIHelp.h>
#include <stdlib.h>
+#include <usbhost/usbhost.h>
+#include <usbhost/usbhost_jni.h>
#include "jni.h"
-#include <nativehelper/JNIHelp.h>
+#include "utils/Log.h"
-#include <usbhost/usbhost.h>
-
-#define MAX_DESCRIPTORS_LENGTH 4096
static const int USB_CONTROL_TRANSFER_TIMEOUT_MS = 200;
// com.android.server.usb.descriptors
@@ -41,26 +39,9 @@
}
int fd = usb_device_get_fd(device);
- if (fd < 0) {
- usb_device_close(device);
- return NULL;
- }
-
- // from android_hardware_UsbDeviceConnection_get_desc()
- jbyte buffer[MAX_DESCRIPTORS_LENGTH];
- lseek(fd, 0, SEEK_SET);
- int numBytes = read(fd, buffer, sizeof(buffer));
- jbyteArray ret = NULL;
+ jbyteArray descriptors = usb_jni_read_descriptors(env, fd);
usb_device_close(device);
-
- if (numBytes > 0) {
- ret = env->NewByteArray(numBytes);
- env->SetByteArrayRegion(ret, 0, numBytes, buffer);
- } else {
- ALOGE("error reading descriptors\n");
- }
-
- return ret;
+ return descriptors;
}
jstring JNICALL Java_com_android_server_usb_descriptors_UsbDescriptorParser_getDescriptorString_1native(
diff --git a/services/core/jni/com_android_server_UsbDeviceManager.cpp b/services/core/jni/com_android_server_UsbDeviceManager.cpp
index 3ab5920..0a9ce2f 100644
--- a/services/core/jni/com_android_server_UsbDeviceManager.cpp
+++ b/services/core/jni/com_android_server_UsbDeviceManager.cpp
@@ -25,7 +25,6 @@
#include "MtpDescriptors.h"
#include <stdio.h>
-#include <asm/byteorder.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
diff --git a/services/core/jni/com_android_server_UsbHostManager.cpp b/services/core/jni/com_android_server_UsbHostManager.cpp
index a629b69..e29d2ca 100644
--- a/services/core/jni/com_android_server_UsbHostManager.cpp
+++ b/services/core/jni/com_android_server_UsbHostManager.cpp
@@ -23,7 +23,6 @@
#include "android_runtime/Log.h"
#include <stdio.h>
-#include <asm/byteorder.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@@ -31,8 +30,6 @@
#include <usbhost/usbhost.h>
-#define MAX_DESCRIPTORS_LENGTH 4096
-
namespace android
{
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 5178132..f8a8168 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -16,20 +16,18 @@
#define LOG_TAG "NetworkStatsNative"
+#include <cutils/qtaguid.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "core_jni_helpers.h"
#include <jni.h>
#include <nativehelper/ScopedUtfChars.h>
-#include <utils/misc.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <utils/Log.h>
+#include <utils/misc.h>
-#include "android-base/unique_fd.h"
#include "bpf/BpfUtils.h"
#include "netdbpf/BpfNetworkStats.h"
@@ -104,10 +102,15 @@
}
}
+static int deleteTagData(JNIEnv* /* env */, jclass /* clazz */, jint uid) {
+ return qtaguid_deleteTagData(0, uid);
+}
+
static const JNINativeMethod gMethods[] = {
{"nativeGetTotalStat", "(I)J", (void*)getTotalStat},
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat},
{"nativeGetUidStat", "(II)J", (void*)getUidStat},
+ {"nativeDeleteTagData", "(I)I", (void*)deleteTagData},
};
int register_android_server_net_NetworkStatsService(JNIEnv* env) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 37a84f3..1c9d584 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -32,6 +32,7 @@
import android.app.admin.DevicePolicyManager;
import android.app.admin.FactoryResetProtectionPolicy;
import android.app.admin.PasswordPolicy;
+import android.app.admin.PreferentialNetworkServiceConfig;
import android.graphics.Color;
import android.os.Bundle;
import android.os.PersistableBundle;
@@ -294,6 +295,8 @@
public boolean mAdminCanGrantSensorsPermissions;
public boolean mPreferentialNetworkServiceEnabled =
DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT;
+ public PreferentialNetworkServiceConfig mPreferentialNetworkServiceConfig =
+ PreferentialNetworkServiceConfig.DEFAULT;
private static final boolean USB_DATA_SIGNALING_ENABLED_DEFAULT = true;
boolean mUsbDataSignalingEnabled = USB_DATA_SIGNALING_ENABLED_DEFAULT;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index df98390..564b608 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -109,6 +109,8 @@
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
@@ -179,6 +181,7 @@
import android.app.admin.ParcelableGranteeMap;
import android.app.admin.PasswordMetrics;
import android.app.admin.PasswordPolicy;
+import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.SecurityLog;
import android.app.admin.SecurityLog.SecurityEvent;
import android.app.admin.StartInstallingUpdateCallback;
@@ -3277,14 +3280,14 @@
updatePermissionPolicyCache(userId);
updateAdminCanGrantSensorsPermissionCache(userId);
- final boolean preferentialNetworkServiceEnabled;
+ final PreferentialNetworkServiceConfig preferentialNetworkServiceConfig;
synchronized (getLockObject()) {
ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userId);
- preferentialNetworkServiceEnabled = owner != null
- ? owner.mPreferentialNetworkServiceEnabled
- : DevicePolicyManager.PREFERENTIAL_NETWORK_SERVICE_ENABLED_DEFAULT;
+ preferentialNetworkServiceConfig = owner != null
+ ? owner.mPreferentialNetworkServiceConfig
+ : PreferentialNetworkServiceConfig.DEFAULT;
}
- updateNetworkPreferenceForUser(userId, preferentialNetworkServiceEnabled);
+ updateNetworkPreferenceForUser(userId, preferentialNetworkServiceConfig);
startOwnerService(userId, "start-user");
}
@@ -3301,7 +3304,7 @@
@Override
void handleStopUser(int userId) {
- updateNetworkPreferenceForUser(userId, false);
+ updateNetworkPreferenceForUser(userId, PreferentialNetworkServiceConfig.DEFAULT);
stopOwnerService(userId, "stop-user");
}
@@ -11845,7 +11848,7 @@
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(isProfileOwner(caller),
"Caller is not profile owner;"
- + " only profile owner may control the preferntial network service");
+ + " only profile owner may control the preferential network service");
synchronized (getLockObject()) {
final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(
caller.getUserId());
@@ -11882,6 +11885,47 @@
}
@Override
+ public void setPreferentialNetworkServiceConfig(
+ PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) {
+ if (!mHasFeature) {
+ return;
+ }
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isProfileOwner(caller),
+ "Caller is not profile owner;"
+ + " only profile owner may control the preferential network service");
+ synchronized (getLockObject()) {
+ final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(
+ caller.getUserId());
+ if (!requiredAdmin.mPreferentialNetworkServiceConfig.equals(
+ preferentialNetworkServiceConfig)) {
+ requiredAdmin.mPreferentialNetworkServiceConfig = preferentialNetworkServiceConfig;
+ saveSettingsLocked(caller.getUserId());
+ }
+ }
+ updateNetworkPreferenceForUser(caller.getUserId(), preferentialNetworkServiceConfig);
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums.SET_PREFERENTIAL_NETWORK_SERVICE_ENABLED)
+ .setBoolean(preferentialNetworkServiceConfig.isEnabled())
+ .write();
+ }
+
+ @Override
+ public PreferentialNetworkServiceConfig getPreferentialNetworkServiceConfig() {
+ if (!mHasFeature) {
+ return PreferentialNetworkServiceConfig.DEFAULT;
+ }
+
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isProfileOwner(caller),
+ "Caller is not profile owner");
+ synchronized (getLockObject()) {
+ final ActiveAdmin requiredAdmin = getProfileOwnerAdminLocked(caller.getUserId());
+ return requiredAdmin.mPreferentialNetworkServiceConfig;
+ }
+ }
+
+ @Override
public void setLockTaskPackages(ComponentName who, String[] packages)
throws SecurityException {
Objects.requireNonNull(who, "ComponentName is null");
@@ -17537,11 +17581,48 @@
if (!isManagedProfile(userId)) {
return;
}
- int networkPreference = preferentialNetworkServiceEnabled
- ? PROFILE_NETWORK_PREFERENCE_ENTERPRISE : PROFILE_NETWORK_PREFERENCE_DEFAULT;
ProfileNetworkPreference.Builder preferenceBuilder =
new ProfileNetworkPreference.Builder();
- preferenceBuilder.setPreference(networkPreference);
+ if (preferentialNetworkServiceEnabled) {
+ preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+ preferenceBuilder.setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1);
+ } else {
+ preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
+ }
+ List<ProfileNetworkPreference> preferences = new ArrayList<>();
+ preferences.add(preferenceBuilder.build());
+ mInjector.binderWithCleanCallingIdentity(() ->
+ mInjector.getConnectivityManager().setProfileNetworkPreferences(
+ UserHandle.of(userId), preferences,
+ null /* executor */, null /* listener */));
+ }
+
+ private void updateNetworkPreferenceForUser(int userId,
+ PreferentialNetworkServiceConfig preferentialNetworkServiceConfig) {
+ if (!isManagedProfile(userId)) {
+ return;
+ }
+ ProfileNetworkPreference.Builder preferenceBuilder =
+ new ProfileNetworkPreference.Builder();
+ if (preferentialNetworkServiceConfig.isEnabled()) {
+ if (preferentialNetworkServiceConfig.isFallbackToDefaultConnectionAllowed()) {
+ preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE);
+ } else {
+ preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK);
+ }
+ } else {
+ preferenceBuilder.setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT);
+ }
+ List<Integer> allowedUids = Arrays.stream(
+ preferentialNetworkServiceConfig.getIncludedUids()).boxed().collect(
+ Collectors.toList());
+ List<Integer> excludedUids = Arrays.stream(
+ preferentialNetworkServiceConfig.getExcludedUids()).boxed().collect(
+ Collectors.toList());
+ preferenceBuilder.setIncludedUids(allowedUids);
+ preferenceBuilder.setExcludedUids(excludedUids);
+ preferenceBuilder.setPreferenceEnterpriseId(
+ preferentialNetworkServiceConfig.getNetworkId());
List<ProfileNetworkPreference> preferences = new ArrayList<>();
preferences.add(preferenceBuilder.build());
mInjector.binderWithCleanCallingIdentity(() ->
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2303495..710a9cf 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -54,6 +54,7 @@
import android.net.ConnectivityManager;
import android.net.ConnectivityModuleConnector;
import android.net.NetworkStackClient;
+import android.net.TrafficStats;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -1338,7 +1339,6 @@
VcnManagementService vcnManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
- NsdService serviceDiscovery = null;
WindowManagerService wm = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
@@ -1839,6 +1839,7 @@
try {
networkStats = NetworkStatsService.create(context);
ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats);
+ TrafficStats.init(context);
} catch (Throwable e) {
reportWtf("starting NetworkStats Service", e);
}
@@ -1941,16 +1942,6 @@
}
t.traceEnd();
- t.traceBegin("StartNsdService");
- try {
- serviceDiscovery = NsdService.create(context);
- ServiceManager.addService(
- Context.NSD_SERVICE, serviceDiscovery);
- } catch (Throwable e) {
- reportWtf("starting Service Discovery Service", e);
- }
- t.traceEnd();
-
t.traceBegin("StartSystemUpdateManagerService");
try {
ServiceManager.addService(Context.SYSTEM_UPDATE_SERVICE,
diff --git a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
index 9e1445c..bdea679 100644
--- a/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
+++ b/services/tests/servicestests/src/com/android/server/audio/AudioDeviceBrokerTest.java
@@ -30,7 +30,7 @@
import android.content.Intent;
import android.media.AudioManager;
import android.media.AudioSystem;
-import android.media.BtProfileConnectionInfo;
+import android.media.BluetoothProfileConnectionInfo;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -100,7 +100,7 @@
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
- BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
+ BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource"));
Thread.sleep(2 * MAX_MESSAGE_HANDLING_DELAY_MS);
verify(mSpyDevInventory, times(1)).setBluetoothActiveDevice(
any(AudioDeviceBroker.BtDeviceInfo.class)
@@ -208,13 +208,13 @@
// first connection: ensure the device is connected as a starting condition for the test
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
- BtProfileConnectionInfo.a2dpInfo(true, 1), "testSource"));
+ BluetoothProfileConnectionInfo.createA2dpInfo(true, 1), "testSource"));
Thread.sleep(MAX_MESSAGE_HANDLING_DELAY_MS);
// disconnection
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(null, mFakeBtDevice,
- BtProfileConnectionInfo.a2dpInfo(false, -1), "testSource"));
+ BluetoothProfileConnectionInfo.createA2dpInfo(false, -1), "testSource"));
if (delayAfterDisconnection > 0) {
Thread.sleep(delayAfterDisconnection);
}
@@ -222,7 +222,7 @@
// reconnection
mAudioDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(mFakeBtDevice, null,
- BtProfileConnectionInfo.a2dpInfo(true, 2), "testSource"));
+ BluetoothProfileConnectionInfo.createA2dpInfo(true, 2), "testSource"));
Thread.sleep(AudioService.BECOMING_NOISY_DELAY_MS + MAX_MESSAGE_HANDLING_DELAY_MS);
// Verify disconnection has been cancelled and we're seeing two connections attempts,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index a63aa6a..3511fc1 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -39,7 +39,9 @@
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
+import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
import static android.net.InetAddresses.parseNumericAddress;
+import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
@@ -89,6 +91,7 @@
import android.app.admin.DevicePolicyManagerLiteInternal;
import android.app.admin.FactoryResetProtectionPolicy;
import android.app.admin.PasswordMetrics;
+import android.app.admin.PreferentialNetworkServiceConfig;
import android.app.admin.SystemUpdatePolicy;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -4109,6 +4112,7 @@
ProfileNetworkPreference preferenceDetails2 =
new ProfileNetworkPreference.Builder()
.setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE)
+ .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
.build();
List<ProfileNetworkPreference> preferences2 = new ArrayList<>();
preferences2.add(preferenceDetails);
@@ -4118,6 +4122,164 @@
}
@Test
+ public void testSetPreferentialNetworkServiceConfig_noProfileOwner() throws Exception {
+ assertExpectException(SecurityException.class, null,
+ () -> dpm.setPreferentialNetworkServiceConfig(
+ PreferentialNetworkServiceConfig.DEFAULT));
+ }
+
+ @Test
+ public void testIsPreferentialNetworkServiceEnabled_noProfileOwner() throws Exception {
+ assertExpectException(SecurityException.class, null,
+ () -> dpm.isPreferentialNetworkServiceEnabled());
+ }
+
+ @Test
+ public void testSetPreferentialNetworkServiceConfig_invalidConfig() throws Exception {
+ final int managedProfileUserId = 15;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+ addManagedProfile(admin1, managedProfileAdminUid, admin1);
+ mContext.binder.callingUid = managedProfileAdminUid;
+
+ PreferentialNetworkServiceConfig.Builder preferentialNetworkServiceConfigBuilder =
+ new PreferentialNetworkServiceConfig.Builder();
+ assertExpectException(NullPointerException.class, null,
+ () -> preferentialNetworkServiceConfigBuilder.setIncludedUids(null));
+ assertExpectException(NullPointerException.class, null,
+ () -> preferentialNetworkServiceConfigBuilder.setExcludedUids(null));
+ assertExpectException(IllegalArgumentException.class, null,
+ () -> preferentialNetworkServiceConfigBuilder.setNetworkId(6));
+ int[] includedUids = new int[]{1, 2};
+ int[] excludedUids = new int[]{3, 4};
+ preferentialNetworkServiceConfigBuilder.setIncludedUids(includedUids);
+ preferentialNetworkServiceConfigBuilder.setExcludedUids(excludedUids);
+
+ assertExpectException(IllegalStateException.class, null,
+ () -> preferentialNetworkServiceConfigBuilder.build());
+ }
+
+ @Test
+ public void testSetPreferentialNetworkServiceConfig_defaultPreference() throws Exception {
+ final int managedProfileUserId = 15;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+ addManagedProfile(admin1, managedProfileAdminUid, admin1);
+ mContext.binder.callingUid = managedProfileAdminUid;
+
+ dpm.setPreferentialNetworkServiceConfig(PreferentialNetworkServiceConfig.DEFAULT);
+ assertThat(dpm.isPreferentialNetworkServiceEnabled()).isFalse();
+ assertThat(dpm.getPreferentialNetworkServiceConfig()
+ .isEnabled()).isFalse();
+
+ ProfileNetworkPreference preferenceDetails =
+ new ProfileNetworkPreference.Builder()
+ .setPreference(PROFILE_NETWORK_PREFERENCE_DEFAULT)
+ .build();
+ List<ProfileNetworkPreference> preferences = new ArrayList<>();
+ preferences.add(preferenceDetails);
+ verify(getServices().connectivityManager, times(1))
+ .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+ null, null);
+ }
+
+ @Test
+ public void testSetPreferentialNetworkServiceConfig_enterprisePreference() throws Exception {
+ PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
+ (new PreferentialNetworkServiceConfig.Builder())
+ .setEnabled(true)
+ .setNetworkId(NET_ENTERPRISE_ID_1)
+ .build();
+
+ final int managedProfileUserId = 15;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+ addManagedProfile(admin1, managedProfileAdminUid, admin1);
+ mContext.binder.callingUid = managedProfileAdminUid;
+
+ dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled);
+ assertThat(dpm.getPreferentialNetworkServiceConfig()
+ .isEnabled()).isTrue();
+ ProfileNetworkPreference preferenceDetails =
+ new ProfileNetworkPreference.Builder()
+ .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE)
+ .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+ .build();
+ List<ProfileNetworkPreference> preferences = new ArrayList<>();
+ preferences.add(preferenceDetails);
+ verify(getServices().connectivityManager, times(1))
+ .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+ null, null);
+ }
+
+ @Test
+ public void testSetPreferentialNetworkServiceConfig_enterprisePreferenceIncludedUids()
+ throws Exception {
+ final int managedProfileUserId = 15;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+ addManagedProfile(admin1, managedProfileAdminUid, admin1);
+ mContext.binder.callingUid = managedProfileAdminUid;
+
+ PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
+ (new PreferentialNetworkServiceConfig.Builder())
+ .setEnabled(true)
+ .setNetworkId(NET_ENTERPRISE_ID_1)
+ .setFallbackToDefaultConnectionAllowed(false)
+ .setIncludedUids(new int[]{1, 2})
+ .build();
+ dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled);
+ assertThat(dpm.getPreferentialNetworkServiceConfig()
+ .isEnabled()).isTrue();
+ List<Integer> includedList = new ArrayList<>();
+ includedList.add(1);
+ includedList.add(2);
+ ProfileNetworkPreference preferenceDetails =
+ new ProfileNetworkPreference.Builder()
+ .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK)
+ .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+ .setIncludedUids(includedList)
+ .build();
+ List<ProfileNetworkPreference> preferences = new ArrayList<>();
+ preferences.add(preferenceDetails);
+ verify(getServices().connectivityManager, times(1))
+ .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+ null, null);
+ }
+
+ @Test
+ public void testSetPreferentialNetworkServiceConfig_enterprisePreferenceExcludedUids()
+ throws Exception {
+ final int managedProfileUserId = 15;
+ final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
+ addManagedProfile(admin1, managedProfileAdminUid, admin1);
+ mContext.binder.callingUid = managedProfileAdminUid;
+
+ PreferentialNetworkServiceConfig preferentialNetworkServiceConfigEnabled =
+ (new PreferentialNetworkServiceConfig.Builder())
+ .setEnabled(true)
+ .setNetworkId(NET_ENTERPRISE_ID_1)
+ .setFallbackToDefaultConnectionAllowed(false)
+ .setExcludedUids(new int[]{1, 2})
+ .build();
+
+ dpm.setPreferentialNetworkServiceConfig(preferentialNetworkServiceConfigEnabled);
+ assertThat(dpm.getPreferentialNetworkServiceConfig()
+ .isEnabled()).isTrue();
+ List<Integer> excludedUids = new ArrayList<>();
+ excludedUids.add(1);
+ excludedUids.add(2);
+ ProfileNetworkPreference preferenceDetails =
+ new ProfileNetworkPreference.Builder()
+ .setPreference(PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK)
+ .setPreferenceEnterpriseId(NET_ENTERPRISE_ID_1)
+ .setExcludedUids(excludedUids)
+ .build();
+ List<ProfileNetworkPreference> preferences = new ArrayList<>();
+ preferences.clear();
+ preferences.add(preferenceDetails);
+ verify(getServices().connectivityManager, times(1))
+ .setProfileNetworkPreferences(UserHandle.of(managedProfileUserId), preferences,
+ null, null);
+ }
+
+ @Test
public void testSetSystemSettingFailWithNonWhitelistedSettings() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 01bd04c..77e49ad 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -43,6 +43,7 @@
import android.hardware.hdmi.HdmiPortInfo;
import android.hardware.hdmi.IHdmiCecVolumeControlFeatureListener;
import android.hardware.hdmi.IHdmiControlStatusChangeListener;
+import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.os.Binder;
import android.os.IPowerManager;
import android.os.IThermalService;
@@ -886,6 +887,117 @@
}
@Test
+ public void addVendorCommandListener_receiveCallback_VendorCmdNoIdTest() {
+ int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
+ int sourceAddress = Constants.ADDR_TV;
+ byte[] params = {0x00, 0x01, 0x02, 0x03};
+ int vendorId = 0x123456;
+ mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+
+ VendorCommandListener vendorCmdListener =
+ new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
+ mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage vendorCommandNoId =
+ HdmiCecMessageBuilder.buildVendorCommand(sourceAddress, destAddress, params);
+ mNativeWrapper.onCecMessage(vendorCommandNoId);
+ mTestLooper.dispatchAll();
+ assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue();
+ assertThat(vendorCmdListener.mParamsCorrect).isTrue();
+ assertThat(vendorCmdListener.mHasVendorId).isFalse();
+ }
+
+ @Test
+ public void addVendorCommandListener_receiveCallback_VendorCmdWithIdTest() {
+ int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
+ int sourceAddress = Constants.ADDR_TV;
+ byte[] params = {0x00, 0x01, 0x02, 0x03};
+ int vendorId = 0x123456;
+ mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+
+ VendorCommandListener vendorCmdListener =
+ new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
+ mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage vendorCommandWithId =
+ HdmiCecMessageBuilder.buildVendorCommandWithId(
+ sourceAddress, destAddress, vendorId, params);
+ mNativeWrapper.onCecMessage(vendorCommandWithId);
+ mTestLooper.dispatchAll();
+ assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isTrue();
+ assertThat(vendorCmdListener.mParamsCorrect).isTrue();
+ assertThat(vendorCmdListener.mHasVendorId).isTrue();
+ }
+
+ @Test
+ public void addVendorCommandListener_noCallback_VendorCmdDiffIdTest() {
+ int destAddress = mHdmiControlServiceSpy.playback().getDeviceInfo().getLogicalAddress();
+ int sourceAddress = Constants.ADDR_TV;
+ byte[] params = {0x00, 0x01, 0x02, 0x03};
+ int vendorId = 0x123456;
+ int diffVendorId = 0x345678;
+ mHdmiControlServiceSpy.setPowerStatus(HdmiControlManager.POWER_STATUS_ON);
+
+ VendorCommandListener vendorCmdListener =
+ new VendorCommandListener(sourceAddress, destAddress, params, vendorId);
+ mHdmiControlServiceSpy.addVendorCommandListener(vendorCmdListener, vendorId);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage vendorCommandWithDiffId =
+ HdmiCecMessageBuilder.buildVendorCommandWithId(
+ sourceAddress, destAddress, diffVendorId, params);
+ mNativeWrapper.onCecMessage(vendorCommandWithDiffId);
+ mTestLooper.dispatchAll();
+ assertThat(vendorCmdListener.mVendorCommandCallbackReceived).isFalse();
+ }
+
+ private static class VendorCommandListener extends IHdmiVendorCommandListener.Stub {
+ boolean mVendorCommandCallbackReceived = false;
+ boolean mParamsCorrect = false;
+ boolean mHasVendorId = false;
+
+ int mSourceAddress;
+ int mDestAddress;
+ byte[] mParams;
+ int mVendorId;
+
+ VendorCommandListener(int sourceAddress, int destAddress, byte[] params, int vendorId) {
+ this.mSourceAddress = sourceAddress;
+ this.mDestAddress = destAddress;
+ this.mParams = params.clone();
+ this.mVendorId = vendorId;
+ }
+
+ @Override
+ public void onReceived(
+ int sourceAddress, int destAddress, byte[] params, boolean hasVendorId) {
+ mVendorCommandCallbackReceived = true;
+ if (mSourceAddress == sourceAddress && mDestAddress == destAddress) {
+ byte[] expectedParams;
+ if (hasVendorId) {
+ // If the command has vendor ID, we have to add it to mParams.
+ expectedParams = new byte[params.length];
+ expectedParams[0] = (byte) ((mVendorId >> 16) & 0xFF);
+ expectedParams[1] = (byte) ((mVendorId >> 8) & 0xFF);
+ expectedParams[2] = (byte) (mVendorId & 0xFF);
+ System.arraycopy(mParams, 0, expectedParams, 3, mParams.length);
+ } else {
+ expectedParams = params.clone();
+ }
+ if (Arrays.equals(expectedParams, params)) {
+ mParamsCorrect = true;
+ }
+ }
+ mHasVendorId = hasVendorId;
+ }
+
+ @Override
+ public void onControlStateChanged(boolean enabled, int reason) {}
+ }
+
+ @Test
public void dispatchMessageToLocalDevice_broadcastMessage_returnsHandled() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildStandby(
Constants.ADDR_TV,
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 9a6f61e..94cf20f 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -51,9 +51,9 @@
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.net.NetworkStats.METERED_NO;
import static android.net.NetworkStats.METERED_YES;
-import static android.net.NetworkTemplate.buildTemplateCarrierMetered;
-import static android.net.NetworkTemplate.buildTemplateWifi;
-import static android.net.TrafficStats.MB_IN_BYTES;
+import static android.net.NetworkTemplate.MATCH_CARRIER;
+import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_THRESHOLD_DISABLED;
import static android.telephony.CarrierConfigManager.DATA_CYCLE_USE_PLATFORM_DEFAULT;
@@ -71,7 +71,6 @@
import static com.android.server.net.NetworkPolicyManagerService.TYPE_RAPID;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
import static com.android.server.net.NetworkPolicyManagerService.UidBlockedState.getEffectiveBlockedReasons;
-import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -95,6 +94,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -204,6 +204,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.TimeZone;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
@@ -228,10 +229,12 @@
private static final int TEST_SUB_ID = 42;
private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS);
-
- private static NetworkTemplate sTemplateWifi = buildTemplateWifi(TEST_WIFI_NETWORK_KEY);
+ private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI)
+ .setWifiNetworkKeys(Set.of(TEST_WIFI_NETWORK_KEY)).build();
private static NetworkTemplate sTemplateCarrierMetered =
- buildTemplateCarrierMetered(TEST_IMSI);
+ new NetworkTemplate.Builder(MATCH_CARRIER)
+ .setSubscriberIds(Set.of(TEST_IMSI))
+ .setMeteredness(METERED_YES).build();
/**
* Path on assets where files used by {@link NetPolicyXml} are located.
@@ -495,8 +498,14 @@
verify(mNetworkManager).registerObserver(networkObserver.capture());
mNetworkObserver = networkObserver.getValue();
- // Simulate NetworkStatsService broadcast stats updated to signal its readiness.
- mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_UPDATED));
+ // Catch UsageCallback during systemReady(). Simulate NetworkStatsService triggered
+ // stats updated callback to signal its readiness.
+ final ArgumentCaptor<NetworkStatsManager.UsageCallback> usageObserver =
+ ArgumentCaptor.forClass(NetworkStatsManager.UsageCallback.class);
+ verify(mStatsManager, times(2))
+ .registerUsageCallback(any(), anyLong(), any(), usageObserver.capture());
+ usageObserver.getValue().onThresholdReached(
+ new NetworkTemplate.Builder(MATCH_MOBILE).build());
NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, "");
mDefaultWarningBytes = defaultPolicy.warningBytes;
@@ -1153,11 +1162,12 @@
mPolicyListener.expect().onMeteredIfacesChanged(any());
setNetworkPolicies(new NetworkPolicy(
- sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
+ sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, DataUnit.MEBIBYTES.toBytes(1),
+ DataUnit.MEBIBYTES.toBytes(2), false));
mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(TEST_IFACE,
- (2 * MB_IN_BYTES) - 512);
+ DataUnit.MEBIBYTES.toBytes(2) - 512);
}
@Test
@@ -1245,7 +1255,7 @@
reset(mTelephonyManager, mNetworkManager, mNotifManager);
TelephonyManager tmSub = expectMobileDefaults();
- mService.snoozeLimit(NetworkTemplate.buildTemplateCarrierMetered(TEST_IMSI));
+ mService.snoozeLimit(sTemplateCarrierMetered);
mService.updateNetworks();
verify(tmSub, atLeastOnce()).setPolicyDataEnabled(true);
@@ -1746,7 +1756,7 @@
}
private void triggerOnStatsProviderWarningOrLimitReached() throws InterruptedException {
- mService.onStatsProviderWarningOrLimitReached();
+ mService.notifyStatsProviderWarningOrLimitReached();
// Wait for processing of MSG_STATS_PROVIDER_WARNING_OR_LIMIT_REACHED.
postMsgAndWaitForCompletion();
verify(mStatsManager).forceUpdate();
@@ -1948,7 +1958,7 @@
assertEquals("Unexpected number of network policies", 1, policies.length);
NetworkPolicy actualPolicy = policies[0];
assertEquals("Unexpected template match rule in network policies",
- NetworkTemplate.MATCH_WIFI,
+ MATCH_WIFI,
actualPolicy.template.getMatchRule());
assertEquals("Unexpected subscriberIds size in network policies",
actualPolicy.template.getSubscriberIds().size(), 0);
@@ -2019,7 +2029,10 @@
private static NetworkPolicy buildFakeCarrierPolicy(int cycleDay, long warningBytes,
long limitBytes, boolean inferred) {
- final NetworkTemplate template = buildTemplateCarrierMetered(FAKE_SUBSCRIBER_ID);
+ // TODO: Refactor this to use sTemplateCarrierMetered.
+ final NetworkTemplate template = new NetworkTemplate.Builder(MATCH_CARRIER)
+ .setSubscriberIds(Set.of(FAKE_SUBSCRIBER_ID))
+ .setMeteredness(METERED_YES).build();
return new NetworkPolicy(template, cycleDay, TimeZone.getDefault().getID(), warningBytes,
limitBytes, SNOOZE_NEVER, SNOOZE_NEVER, true, inferred);
}
@@ -2046,7 +2059,7 @@
private static NetworkStateSnapshot buildWifi() {
WifiInfo mockWifiInfo = mock(WifiInfo.class);
when(mockWifiInfo.makeCopy(anyLong())).thenReturn(mockWifiInfo);
- when(mockWifiInfo.getCurrentNetworkKey()).thenReturn(TEST_WIFI_NETWORK_KEY);
+ when(mockWifiInfo.getNetworkKey()).thenReturn(TEST_WIFI_NETWORK_KEY);
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(TEST_IFACE);
final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
@@ -2092,7 +2105,7 @@
}
private void verifyAdvisePersistThreshold() throws Exception {
- verify(mStatsManager).advisePersistThreshold(anyLong());
+ verify(mStatsManager).setDefaultGlobalAlert(anyLong());
}
private static class TestAbstractFuture<T> extends AbstractFuture<T> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 6f04f17..29fa2d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -37,6 +37,7 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Process.NOBODY_UID;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.InsetsState.ITYPE_IME;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
@@ -127,6 +128,8 @@
import android.view.IRemoteAnimationRunner.Stub;
import android.view.IWindowManager;
import android.view.IWindowSession;
+import android.view.InsetsSource;
+import android.view.InsetsState;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.Surface;
@@ -2884,6 +2887,41 @@
assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
}
+ @UseTestDisplay(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testImeInsetsFrozenFlag_resetWhenReportedToBeImeInputTarget() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+
+ InsetsSource imeSource = new InsetsSource(ITYPE_IME);
+ app.getInsetsState().addSource(imeSource);
+ mDisplayContent.setImeLayeringTarget(app);
+ mDisplayContent.updateImeInputAndControlTarget(app);
+
+ InsetsState state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
+ assertFalse(state.getSource(ITYPE_IME).isVisible());
+ assertTrue(state.getSource(ITYPE_IME).getFrame().isEmpty());
+
+ // Simulate app is closing and expect IME insets is frozen.
+ mDisplayContent.mOpeningApps.clear();
+ app.mActivityRecord.commitVisibility(false, false);
+ app.mActivityRecord.onWindowsGone();
+ assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+ // Simulate app re-start input or turning screen off/on then unlocked by un-secure
+ // keyguard to back to the app, expect IME insets is not frozen
+ imeSource.setFrame(new Rect(100, 400, 500, 500));
+ app.getInsetsState().addSource(imeSource);
+ app.getInsetsState().setSourceVisible(ITYPE_IME, true);
+ mDisplayContent.updateImeInputAndControlTarget(app);
+ assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+ // Verify when IME is visible and the app can receive the right IME insets from policy.
+ makeWindowVisibleAndDrawn(app, mImeWindow);
+ state = mDisplayContent.getInsetsPolicy().getInsetsForWindow(app);
+ assertTrue(state.getSource(ITYPE_IME).isVisible());
+ assertEquals(state.getSource(ITYPE_IME).getFrame(), imeSource.getFrame());
+ }
+
private void assertHasStartingWindow(ActivityRecord atoken) {
assertNotNull(atoken.mStartingSurface);
assertNotNull(atoken.mStartingData);
diff --git a/services/wallpapereffectsgeneration/OWNERS b/services/wallpapereffectsgeneration/OWNERS
new file mode 100644
index 0000000..d2d3e2c0
--- /dev/null
+++ b/services/wallpapereffectsgeneration/OWNERS
@@ -0,0 +1,4 @@
+susharon@google.com
+shanh@google.com
+huiwu@google.com
+srazdan@google.com
diff --git a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
index 1252965..9a991a1 100644
--- a/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
+++ b/telephony/common/com/android/internal/telephony/util/TelephonyUtils.java
@@ -107,6 +107,25 @@
}
}
+ /**
+ * Convenience method for running the provided action in the provided
+ * executor enclosed in
+ * {@link Binder#clearCallingIdentity}/{@link Binder#restoreCallingIdentity}
+ *
+ * Any exception thrown by the given action will need to be handled by caller.
+ *
+ */
+ public static void runWithCleanCallingIdentity(
+ @NonNull Runnable action, @NonNull Executor executor) {
+ if (action != null) {
+ if (executor != null) {
+ executor.execute(() -> runWithCleanCallingIdentity(action));
+ } else {
+ runWithCleanCallingIdentity(action);
+ }
+ }
+ }
+
/**
* Convenience method for running the provided action enclosed in
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e59c2e41..d7135a5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -168,7 +168,10 @@
/**
* This flag specifies whether VoLTE availability is based on provisioning. By default this is
* false.
+ * Used for UCE to determine if EAB provisioning checks should be based on provisioning.
+ * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead.
*/
+ @Deprecated
public static final String
KEY_CARRIER_VOLTE_PROVISIONED_BOOL = "carrier_volte_provisioned_bool";
@@ -349,6 +352,12 @@
KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
/**
+ * Flag indicating if the carrier supports tethering of mobile data.
+ */
+ public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL =
+ "carrier_supports_tethering_bool";
+
+ /**
* Flag indicating whether radio is to be restarted on error PDP_FAIL_REGULAR_DEACTIVATION
* This is false by default.
*
@@ -858,7 +867,12 @@
/**
* Flag specifying whether provisioning is required for VoLTE, Video Telephony, and WiFi
* Calling.
+
+ * Combines VoLTE, VT, VoWiFI calling provisioning into one parameter.
+ * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for
+ * finer-grained control.
*/
+ @Deprecated
public static final String KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
= "carrier_volte_provisioning_required_bool";
@@ -872,7 +886,11 @@
* and enable the UT over IMS capability for the subscription when the subscription is loaded.
*
* The default value for this key is {@code false}.
+ *
+ * @deprecated Use {@link Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE} instead for
+ * determining if UT requires provisioning.
*/
+ @Deprecated
public static final String KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL =
"carrier_ut_provisioning_required_bool";
@@ -4402,12 +4420,10 @@
"carrier_auto_cancel_cs_notification";
/**
- * Passing this value as {@link KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the
+ * Passing this value as {@link #KEY_SUBSCRIPTION_GROUP_UUID_STRING} will remove the
* subscription from a group instead of adding it to a group.
*
- * TODO: Expose in a future release.
- *
- * @hide
+ * <p>This value will work all the way back to {@link android.os.Build.VERSION_CODES#Q}.
*/
public static final String REMOVE_GROUP_UUID_STRING = "00000000-0000-0000-0000-000000000000";
@@ -4420,9 +4436,7 @@
* <p>If set to {@link #REMOVE_GROUP_UUID_STRING}, then the subscription will be removed from
* its current group.
*
- * TODO: unhide this key.
- *
- * @hide
+ * <p>This key will work all the way back to {@link android.os.Build.VERSION_CODES#Q}.
*/
public static final String KEY_SUBSCRIPTION_GROUP_UUID_STRING =
"subscription_group_uuid_string";
@@ -4447,17 +4461,15 @@
"data_switch_validation_min_gap_long";
/**
- * A boolean property indicating whether this subscription should be managed as an opportunistic
- * subscription.
- *
- * If true, then this subscription will be selected based on available coverage and will not be
- * available for a user in settings menus for selecting macro network providers. If unset,
- * defaults to “false”.
- *
- * TODO: unhide this key.
- *
- * @hide
- */
+ * A boolean property indicating whether this subscription should be managed as an opportunistic
+ * subscription.
+ *
+ * If true, then this subscription will be selected based on available coverage and will not be
+ * available for a user in settings menus for selecting macro network providers. If unset,
+ * defaults to “false”.
+ *
+ * <p>This key will work all the way back to {@link android.os.Build.VERSION_CODES#Q}.
+ */
public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL =
"is_opportunistic_subscription_bool";
@@ -4637,6 +4649,95 @@
public static final String KEY_RCS_REQUEST_RETRY_INTERVAL_MILLIS_LONG =
KEY_PREFIX + "rcs_request_retry_interval_millis_long";
+ /**
+ * A bundle which specifies the MMTEL capability and registration technology
+ * that requires provisioning. If a tuple is not present, the
+ * framework will not require that the tuple requires provisioning before
+ * enabling the capability.
+ * <p> Possible keys in this bundle are
+ * <ul>
+ * <li>{@link #KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY}</li>
+ * <li>{@link #KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY}</li>
+ * <li>{@link #KEY_CAPABILITY_TYPE_UT_INT_ARRAY}</li>
+ * <li>{@link #KEY_CAPABILITY_TYPE_SMS_INT_ARRAY}</li>
+ * <li>{@link #KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY}</li>
+ * </ul>
+ * <p> The values are defined in
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+ */
+ public static final String KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE =
+ KEY_PREFIX + "mmtel_requires_provisioning_bundle";
+
+ /**
+ * This MmTelFeature supports Voice calling (IR.92)
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE
+ */
+ public static final String KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_voice_int_array";
+
+ /**
+ * This MmTelFeature supports Video (IR.94)
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO
+ */
+ public static final String KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_video_int_array";
+
+ /**
+ * This MmTelFeature supports XCAP over Ut for supplementary services. (IR.92)
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT
+ */
+ public static final String KEY_CAPABILITY_TYPE_UT_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_ut_int_array";
+
+ /**
+ * This MmTelFeature supports SMS (IR.92)
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS
+ */
+ public static final String KEY_CAPABILITY_TYPE_SMS_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_sms_int_array";
+
+ /**
+ * This MmTelFeature supports Call Composer (section 2.4 of RCC.20)
+ * @see MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_CALL_COMPOSER
+ */
+ public static final String KEY_CAPABILITY_CALL_COMPOSER_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_call_composer_int_array";
+
+ /**
+ * A bundle which specifies the RCS capability and registration technology
+ * that requires provisioning. If a tuple is not present, the
+ * framework will not require that the tuple requires provisioning before
+ * enabling the capability.
+ * <p> Possible keys in this bundle are
+ * <ul>
+ * <li>{@link #KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY}</li>
+ * <li>{@link #KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY}</li>
+ * </ul>
+ * <p> The values are defined in
+ * {@link android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech}
+ */
+ public static final String KEY_RCS_REQUIRES_PROVISIONING_BUNDLE =
+ KEY_PREFIX + "rcs_requires_provisioning_bundle";
+
+ /**
+ * This carrier supports User Capability Exchange using SIP OPTIONS as defined by the
+ * framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS.
+ * If not set, this RcsFeature should not service capability requests.
+ * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE
+ */
+ public static final String KEY_CAPABILITY_TYPE_OPTIONS_UCE_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_options_uce_int_array";
+
+ /**
+ * This carrier supports User Capability Exchange using a presence server as defined by the
+ * framework. If set, the RcsFeature should support capability exchange using a presence
+ * server. If not set, this RcsFeature should not publish capabilities or service capability
+ * requests using presence.
+ * @see RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE
+ */
+ public static final String KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY =
+ KEY_PREFIX + "key_capability_type_presence_uce_int_array";
+
private Ims() {}
private static PersistableBundle getDefaults() {
@@ -4673,6 +4774,20 @@
"+g.gsma.rcs.botversion=\"#=1,#=2\"",
"+g.gsma.rcs.cpimext"});
+ /**
+ * @see #KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
+ */
+ PersistableBundle mmtel_requires_provisioning_int_array = new PersistableBundle();
+ defaults.putPersistableBundle(
+ KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE, mmtel_requires_provisioning_int_array);
+
+ /**
+ * @see #KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+ */
+ PersistableBundle rcs_requires_provisioning_int_array = new PersistableBundle();
+ defaults.putPersistableBundle(
+ KEY_RCS_REQUIRES_PROVISIONING_BUNDLE, rcs_requires_provisioning_int_array);
+
return defaults;
}
}
@@ -4883,6 +4998,10 @@
/** Specifies the PCO id for IPv4 Epdg server address */
public static final String KEY_EPDG_PCO_ID_IPV4_INT = KEY_PREFIX + "epdg_pco_id_ipv4_int";
+ /** Controls if the IKE tunnel setup supports EAP-AKA fast reauth */
+ public static final String KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL =
+ KEY_PREFIX + "supports_eap_aka_fast_reauth_bool";
+
/** @hide */
@IntDef({AUTHENTICATION_METHOD_EAP_ONLY, AUTHENTICATION_METHOD_CERT})
public @interface AuthenticationMethodType {}
@@ -5029,6 +5148,7 @@
defaults.putBoolean(KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL, false);
defaults.putInt(KEY_EPDG_PCO_ID_IPV6_INT, 0);
defaults.putInt(KEY_EPDG_PCO_ID_IPV4_INT, 0);
+ defaults.putBoolean(KEY_SUPPORTS_EAP_AKA_FAST_REAUTH_BOOL, false);
return defaults;
}
@@ -5416,6 +5536,7 @@
sDefaults.putBoolean(KEY_VOICE_PRIVACY_DISABLE_UI_BOOL, false);
sDefaults.putBoolean(KEY_WORLD_PHONE_BOOL, false);
sDefaults.putBoolean(KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true);
+ sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
sDefaults.putBoolean(KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL, false);
sDefaults.putIntArray(KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY, new int[]{});
sDefaults.putInt(KEY_VOLTE_REPLACEMENT_RAT_INT, 0);
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index fc76f99..6b9871c 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -160,6 +160,26 @@
return new SipDelegateManager(mContext, subscriptionId, sRcsCache, sTelephonyCache);
}
+
+ /**
+ * Create an instance of {@link ProvisioningManager} for the subscription id specified.
+ * <p>
+ * Provides a ProvisioningManager instance to carrier apps to update carrier provisioning
+ * information, as well as provides a callback so that apps can listen for changes
+ * in MMTEL/RCS provisioning
+ * @param subscriptionId The ID of the subscription that this ProvisioningManager will use.
+ * @throws IllegalArgumentException if the subscription is invalid.
+ * @return a ProvisioningManager instance with the specific subscription ID.
+ */
+ @NonNull
+ public ProvisioningManager getProvisioningManager(int subscriptionId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
+ throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
+ }
+
+ return new ProvisioningManager(subscriptionId);
+ }
+
private static IImsRcsController getIImsRcsControllerInterface() {
return IImsRcsController.Stub.asInterface(
TelephonyFrameworkInitializer
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index f728324..4e32a55 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3820,6 +3820,11 @@
* {@link #PHONE_NUMBER_SOURCE_UICC UICC} and decide if the previously set phone number
* of source {@link #PHONE_NUMBER_SOURCE_CARRIER carrier} should be updated.
*
+ * <p>The API provides no guarantees of what format the number is in: the format can vary
+ * depending on the {@code source} and the network etc. Programmatic parsing should be done
+ * cautiously, for example, after formatting the number to a consistent format with
+ * {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}.
+ *
* <p>Note the assumption is that one subscription (which usually means one SIM) has
* only one phone number. The multiple sources backup each other so hopefully at least one
* is availavle. For example, for a carrier that doesn't typically set phone numbers
@@ -3878,6 +3883,11 @@
* from available sources in the following order: {@link #PHONE_NUMBER_SOURCE_CARRIER}
* > {@link #PHONE_NUMBER_SOURCE_UICC} > {@link #PHONE_NUMBER_SOURCE_IMS}.
*
+ * <p>The API provides no guarantees of what format the number is in: the format can vary
+ * depending on the underlying source and the network etc. Programmatic parsing should be done
+ * cautiously, for example, after formatting the number to a consistent format with
+ * {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}.
+ *
* @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
* for the default one.
* @return the phone number, or an empty string if not available.
@@ -3916,6 +3926,9 @@
* <p>The API is suitable for carrier apps to provide a phone number, for example when
* it's not possible to update {@link #PHONE_NUMBER_SOURCE_UICC UICC} directly.
*
+ * <p>It's recommended that the phone number is formatted to well-known formats,
+ * for example, by {@link PhoneNumberUtils} {@code formatNumber*} methods.
+ *
* @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
* for the default one.
* @param number the phone number, or an empty string to remove the previously set number.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9ac9d66..4934f11 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8765,7 +8765,8 @@
* @param allowedNetworkTypes The bitmask of allowed network types.
* @return true on success; false on any failure.
* @hide
- * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead.
+ * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead with reason
+ * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@@ -8799,10 +8800,7 @@
/**
* To indicate allowed network type change is requested by user.
- *
- * @hide
*/
- @SystemApi
public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0;
/**
@@ -8821,10 +8819,7 @@
* Carrier configuration won't affect the settings configured through
* other reasons and will result in allowing network types that are in both
* configurations (i.e intersection of both sets).
- *
- * @hide
*/
- @SystemApi
public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2;
/**
@@ -8838,35 +8833,23 @@
/**
* Set the allowed network types of the device and provide the reason triggering the allowed
* network change.
+ * <p>Requires permission: android.Manifest.MODIFY_PHONE_STATE or
+ * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+ *
* This can be called for following reasons
* <ol>
* <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER}
- * <li>Allowed network types control by power manager
- * {@link #ALLOWED_NETWORK_TYPES_REASON_POWER}
* <li>Allowed network types control by carrier {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER}
- * <li>Allowed network types control by the user-controlled "Allow 2G" toggle
- * {@link #ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G}
* </ol>
* This API will result in allowing an intersection of allowed network types for all reasons,
* including the configuration done through other reasons.
*
- * The functionality of this API with the parameter
- * {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} is the same as the API
- * {@link TelephonyManager#setAllowedNetworkTypes}. Use this API instead of
- * {@link TelephonyManager#setAllowedNetworkTypes}.
- * <p>
- * If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
- * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
- * setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
- * setPreferredNetworkTypesBitmap is used instead.
- *
* @param reason the reason the allowed network type change is taking place
- * @param allowedNetworkTypes The bitmask of allowed network types.
+ * @param allowedNetworkTypes The bitmask of allowed network type
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
- * @hide
+ * @throws SecurityException if the caller does not have the required privileges
*/
- @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
@@ -8896,18 +8879,19 @@
*
* {@link #getAllowedNetworkTypesForReason} returns allowed network type for a
* specific reason.
+ * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or
+ * that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* @param reason the reason the allowed network type change is taking place
* @return the allowed network type bitmask
* @throws IllegalStateException if the Telephony process is not currently available.
* @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed.
- * @hide
+ * @throws SecurityException if the caller does not have the required permission/privileges
*/
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
@RequiresFeature(
enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
value = TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK)
- @SystemApi
public @NetworkTypeBitMask long getAllowedNetworkTypesForReason(
@AllowedNetworkTypesReason int reason) {
if (!isValidAllowedNetworkTypesReason(reason)) {
@@ -11487,7 +11471,11 @@
private final int mErrorCode;
- /** @hide */
+ /**
+ * An exception with ModemActivityInfo specific error codes.
+ *
+ * @param errorCode a ModemActivityInfoError code.
+ */
public ModemActivityInfoException(@ModemActivityInfoError int errorCode) {
mErrorCode = errorCode;
}
@@ -13022,127 +13010,88 @@
// 2G
/**
* network type bitmask unknown.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_UNKNOWN = 0L;
/**
* network type bitmask indicating the support of radio tech GSM.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_GSM = (1 << (NETWORK_TYPE_GSM -1));
/**
* network type bitmask indicating the support of radio tech GPRS.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_GPRS = (1 << (NETWORK_TYPE_GPRS -1));
/**
* network type bitmask indicating the support of radio tech EDGE.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_EDGE = (1 << (NETWORK_TYPE_EDGE -1));
/**
* network type bitmask indicating the support of radio tech CDMA(IS95A/IS95B).
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_CDMA = (1 << (NETWORK_TYPE_CDMA -1));
/**
* network type bitmask indicating the support of radio tech 1xRTT.
- * @hide
*/
- @SystemApi
+ @SuppressLint("AllUpper")
public static final long NETWORK_TYPE_BITMASK_1xRTT = (1 << (NETWORK_TYPE_1xRTT - 1));
// 3G
/**
* network type bitmask indicating the support of radio tech EVDO 0.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_EVDO_0 = (1 << (NETWORK_TYPE_EVDO_0 -1));
/**
* network type bitmask indicating the support of radio tech EVDO A.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_EVDO_A = (1 << (NETWORK_TYPE_EVDO_A - 1));
/**
* network type bitmask indicating the support of radio tech EVDO B.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_EVDO_B = (1 << (NETWORK_TYPE_EVDO_B -1));
/**
* network type bitmask indicating the support of radio tech EHRPD.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_EHRPD = (1 << (NETWORK_TYPE_EHRPD -1));
/**
* network type bitmask indicating the support of radio tech HSUPA.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_HSUPA = (1 << (NETWORK_TYPE_HSUPA -1));
/**
* network type bitmask indicating the support of radio tech HSDPA.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_HSDPA = (1 << (NETWORK_TYPE_HSDPA -1));
/**
* network type bitmask indicating the support of radio tech HSPA.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_HSPA = (1 << (NETWORK_TYPE_HSPA -1));
/**
* network type bitmask indicating the support of radio tech HSPAP.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_HSPAP = (1 << (NETWORK_TYPE_HSPAP -1));
/**
* network type bitmask indicating the support of radio tech UMTS.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_UMTS = (1 << (NETWORK_TYPE_UMTS -1));
/**
* network type bitmask indicating the support of radio tech TD_SCDMA.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_TD_SCDMA = (1 << (NETWORK_TYPE_TD_SCDMA -1));
// 4G
/**
* network type bitmask indicating the support of radio tech LTE.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_LTE = (1 << (NETWORK_TYPE_LTE -1));
/**
* network type bitmask indicating the support of radio tech LTE CA (carrier aggregation).
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_LTE_CA = (1 << (NETWORK_TYPE_LTE_CA -1));
/**
* network type bitmask indicating the support of radio tech NR(New Radio) 5G.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_NR = (1 << (NETWORK_TYPE_NR -1));
/**
* network type bitmask indicating the support of radio tech IWLAN.
- * @hide
*/
- @SystemApi
public static final long NETWORK_TYPE_BITMASK_IWLAN = (1 << (NETWORK_TYPE_IWLAN -1));
/** @hide */
@@ -13197,12 +13146,11 @@
/**
* @return Modem supported radio access family bitmask
*
- * <p>Requires permission: {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} or
+ * <p>Requires permission: android.Manifest.READ_PRIVILEGED_PHONE_STATE or
* that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
- * @hide
+ *
+ * @throws SecurityException if the caller does not have the required permission
*/
- @SystemApi
- @TestApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @NetworkTypeBitMask long getSupportedRadioAccessFamily() {
try {
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 051d6c5..13d8c7b 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -259,9 +259,10 @@
}
/**
- * Unthrottles the APN on the current transport. There is no matching "APN throttle" method.
- * Instead, the APN is throttled when {@link IDataService#setupDataCall} fails within
- * the time specified by {@link DataCallResponse#getRetryDurationMillis}.
+ * Unthrottles the APN on the current transport.
+ * The APN is throttled when {@link IDataService#setupDataCall} fails within
+ * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain
+ * throttled until this method is called.
* <p/>
* see: {@link DataCallResponse#getRetryDurationMillis}
*
@@ -282,9 +283,9 @@
/**
* Unthrottles the DataProfile on the current transport.
- * There is no matching "DataProfile throttle" method.
- * Instead, the DataProfile is throttled when {@link IDataService#setupDataCall} fails within
- * the time specified by {@link DataCallResponse#getRetryDurationMillis}.
+ * The DataProfile is throttled when {@link IDataService#setupDataCall} fails within
+ * the time specified by {@link DataCallResponse#getRetryDurationMillis} and will remain
+ * throttled until this method is called.
* <p/>
* see: {@link DataCallResponse#getRetryDurationMillis}
*
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
index dfe5e6c9..d65286f 100755
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -27,10 +27,12 @@
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsVideoCallProvider;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Executor;
/**
* Provides the call initiation/termination, and media exchange between two IMS endpoints.
@@ -522,6 +524,7 @@
private final IImsCallSession miSession;
private boolean mClosed = false;
private Listener mListener;
+ private Executor mListenerExecutor = Runnable::run;
/** @hide */
public ImsCallSession(IImsCallSession iSession) {
@@ -538,9 +541,9 @@
}
/** @hide */
- public ImsCallSession(IImsCallSession iSession, Listener listener) {
+ public ImsCallSession(IImsCallSession iSession, Listener listener, Executor executor) {
this(iSession);
- setListener(listener);
+ setListener(listener, executor);
}
/**
@@ -738,10 +741,14 @@
* override the previous listener.
*
* @param listener to listen to the session events of this object
+ * @param executor an Executor that will execute callbacks
* @hide
*/
- public void setListener(Listener listener) {
+ public void setListener(Listener listener, Executor executor) {
mListener = listener;
+ if (executor != null) {
+ mListenerExecutor = executor;
+ }
}
/**
@@ -1205,44 +1212,56 @@
*/
@Override
public void callSessionInitiating(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionInitiating(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionInitiating(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionProgressing(ImsStreamMediaProfile profile) {
- if (mListener != null) {
- mListener.callSessionProgressing(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionProgressing(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionInitiated(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionStarted(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionStarted(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionInitiatingFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionInitiatedFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionStartFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionTerminated(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionTerminated(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1250,44 +1269,56 @@
*/
@Override
public void callSessionHeld(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionHeld(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionHeld(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionHoldFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionHoldFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionHoldReceived(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionHoldReceived(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionHoldReceived(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionResumed(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionResumed(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionResumed(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionResumeFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionResumeFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionResumeReceived(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionResumeReceived(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionResumeReceived(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1310,15 +1341,17 @@
*/
@Override
public void callSessionMergeComplete(IImsCallSession newSession) {
- if (mListener != null) {
- if (newSession != null) {
- // New session created after conference
- mListener.callSessionMergeComplete(new ImsCallSession(newSession));
- } else {
- // Session already exists. Hence no need to pass
- mListener.callSessionMergeComplete(null);
- }
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ if (newSession != null) {
+ // New session created after conference
+ mListener.callSessionMergeComplete(new ImsCallSession(newSession));
+ } else {
+ // Session already exists. Hence no need to pass
+ mListener.callSessionMergeComplete(null);
+ }
+ }
+ }, mListenerExecutor);
}
/**
@@ -1328,9 +1361,11 @@
*/
@Override
public void callSessionMergeFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionMergeFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1338,23 +1373,29 @@
*/
@Override
public void callSessionUpdated(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionUpdated(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionUpdated(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionUpdateFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionUpdateFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionUpdateReceived(ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionUpdateReceived(ImsCallSession.this, profile);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1363,26 +1404,33 @@
@Override
public void callSessionConferenceExtended(IImsCallSession newSession,
ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionConferenceExtended(ImsCallSession.this,
- new ImsCallSession(newSession), profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionConferenceExtended(ImsCallSession.this,
+ new ImsCallSession(newSession), profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionConferenceExtendFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionConferenceExtendFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionConferenceExtendFailed(
+ ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionConferenceExtendReceived(IImsCallSession newSession,
ImsCallProfile profile) {
- if (mListener != null) {
- mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
- new ImsCallSession(newSession), profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionConferenceExtendReceived(ImsCallSession.this,
+ new ImsCallSession(newSession), profile);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1391,32 +1439,41 @@
*/
@Override
public void callSessionInviteParticipantsRequestDelivered() {
- if (mListener != null) {
- mListener.callSessionInviteParticipantsRequestDelivered(ImsCallSession.this);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionInviteParticipantsRequestDelivered(
+ ImsCallSession.this);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionInviteParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
- reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionInviteParticipantsRequestFailed(ImsCallSession.this,
+ reasonInfo);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionRemoveParticipantsRequestDelivered() {
- if (mListener != null) {
- mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRemoveParticipantsRequestDelivered(ImsCallSession.this);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionRemoveParticipantsRequestFailed(ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
- reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRemoveParticipantsRequestFailed(ImsCallSession.this,
+ reasonInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1424,9 +1481,11 @@
*/
@Override
public void callSessionConferenceStateUpdated(ImsConferenceState state) {
- if (mListener != null) {
- mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionConferenceStateUpdated(ImsCallSession.this, state);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1434,9 +1493,12 @@
*/
@Override
public void callSessionUssdMessageReceived(int mode, String ussdMessage) {
- if (mListener != null) {
- mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode, ussdMessage);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionUssdMessageReceived(ImsCallSession.this, mode,
+ ussdMessage);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1452,10 +1514,12 @@
*/
@Override
public void callSessionMayHandover(int srcNetworkType, int targetNetworkType) {
- if (mListener != null) {
- mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
- targetNetworkType);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionMayHandover(ImsCallSession.this, srcNetworkType,
+ targetNetworkType);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1464,10 +1528,12 @@
@Override
public void callSessionHandover(int srcNetworkType, int targetNetworkType,
ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
- targetNetworkType, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionHandover(ImsCallSession.this, srcNetworkType,
+ targetNetworkType, reasonInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1476,10 +1542,12 @@
@Override
public void callSessionHandoverFailed(int srcNetworkType, int targetNetworkType,
ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
- targetNetworkType, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionHandoverFailed(ImsCallSession.this, srcNetworkType,
+ targetNetworkType, reasonInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1487,9 +1555,11 @@
*/
@Override
public void callSessionTtyModeReceived(int mode) {
- if (mListener != null) {
- mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionTtyModeReceived(ImsCallSession.this, mode);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1499,16 +1569,22 @@
* otherwise.
*/
public void callSessionMultipartyStateChanged(boolean isMultiParty) {
- if (mListener != null) {
- mListener.callSessionMultipartyStateChanged(ImsCallSession.this, isMultiParty);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionMultipartyStateChanged(ImsCallSession.this,
+ isMultiParty);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionSuppServiceReceived(ImsSuppServiceNotification suppServiceInfo ) {
- if (mListener != null) {
- mListener.callSessionSuppServiceReceived(ImsCallSession.this, suppServiceInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionSuppServiceReceived(ImsCallSession.this,
+ suppServiceInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1516,9 +1592,12 @@
*/
@Override
public void callSessionRttModifyRequestReceived(ImsCallProfile callProfile) {
- if (mListener != null) {
- mListener.callSessionRttModifyRequestReceived(ImsCallSession.this, callProfile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRttModifyRequestReceived(ImsCallSession.this,
+ callProfile);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1526,9 +1605,11 @@
*/
@Override
public void callSessionRttModifyResponseReceived(int status) {
- if (mListener != null) {
- mListener.callSessionRttModifyResponseReceived(status);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRttModifyResponseReceived(status);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1536,9 +1617,11 @@
*/
@Override
public void callSessionRttMessageReceived(String rttMessage) {
- if (mListener != null) {
- mListener.callSessionRttMessageReceived(rttMessage);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRttMessageReceived(rttMessage);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1546,23 +1629,29 @@
*/
@Override
public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) {
- if (mListener != null) {
- mListener.callSessionRttAudioIndicatorChanged(profile);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRttAudioIndicatorChanged(profile);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionTransferred() {
- if (mListener != null) {
- mListener.callSessionTransferred(ImsCallSession.this);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionTransferred(ImsCallSession.this);
+ }
+ }, mListenerExecutor);
}
@Override
public void callSessionTransferFailed(@Nullable ImsReasonInfo reasonInfo) {
- if (mListener != null) {
- mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1571,9 +1660,11 @@
*/
@Override
public void callSessionDtmfReceived(char dtmf) {
- if (mListener != null) {
- mListener.callSessionDtmfReceived(dtmf);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionDtmfReceived(dtmf);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1581,9 +1672,11 @@
*/
@Override
public void callQualityChanged(CallQuality callQuality) {
- if (mListener != null) {
- mListener.callQualityChanged(callQuality);
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callQualityChanged(callQuality);
+ }
+ }, mListenerExecutor);
}
/**
@@ -1593,10 +1686,12 @@
@Override
public void callSessionRtpHeaderExtensionsReceived(
@NonNull List<RtpHeaderExtension> extensions) {
- if (mListener != null) {
- mListener.callSessionRtpHeaderExtensionsReceived(
- new ArraySet<RtpHeaderExtension>(extensions));
- }
+ TelephonyUtils.runWithCleanCallingIdentity(()-> {
+ if (mListener != null) {
+ mListener.callSessionRtpHeaderExtensionsReceived(
+ new ArraySet<RtpHeaderExtension>(extensions));
+ }
+ }, mListenerExecutor);
}
}
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 9ab5aeb..be233b8 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.LongDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -41,14 +42,22 @@
import android.telephony.ims.stub.SipTransportImplBase;
import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
/**
* Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend
@@ -172,8 +181,28 @@
// call ImsFeature#onFeatureRemoved.
private final SparseArray<SparseArray<ImsFeature>> mFeaturesBySlot = new SparseArray<>();
- private IImsServiceControllerListener mListener;
+ // A map of slot id -> boolean array, where each entry in the boolean array corresponds to an
+ // ImsFeature that was created for a slot id and not a sub id for backwards compatibility
+ // purposes.
+ private final SparseArray<SparseBooleanArray> mCreateImsFeatureWithSlotIdFlagMap =
+ new SparseArray<>();
+ private IImsServiceControllerListener mListener;
+ private Executor mExecutor;
+
+ /**
+ * Create a new ImsService.
+ * <p>
+ * Method stubs called from the framework will be called asynchronously. Vendor specifies the
+ * {@link Executor} that the methods stubs will be called. If mExecutor is set to null by
+ * vendor use Runnable::run.
+ */
+ public ImsService() {
+ mExecutor = ImsService.this.getExecutor();
+ if (mExecutor == null) {
+ mExecutor = Runnable::run;
+ }
+ }
/**
* Listener that notifies the framework of ImsService changes.
@@ -200,79 +229,163 @@
}
@Override
- public IImsMmTelFeature createMmTelFeature(int slotId) {
- return createMmTelFeatureInternal(slotId);
+ public IImsMmTelFeature createMmTelFeature(int slotId, int subId) {
+ MmTelFeature f = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
+ if (f == null) {
+ return executeMethodAsyncForResult(() -> createMmTelFeatureInternal(slotId, subId),
+ "createMmTelFeature");
+ } else {
+ return f.getBinder();
+ }
}
@Override
- public IImsRcsFeature createRcsFeature(int slotId) {
- return createRcsFeatureInternal(slotId);
+ public IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
+ MmTelFeature f = (MmTelFeature) getImsFeature(slotId, ImsFeature.FEATURE_MMTEL);
+ if (f == null) {
+ return executeMethodAsyncForResult(() -> createEmergencyOnlyMmTelFeatureInternal(
+ slotId), "createEmergencyOnlyMmTelFeature");
+ } else {
+ return f.getBinder();
+ }
+ }
+
+ @Override
+ public IImsRcsFeature createRcsFeature(int slotId, int subId) {
+ RcsFeature f = (RcsFeature) getImsFeature(slotId, ImsFeature.FEATURE_RCS);
+ if (f == null) {
+ return executeMethodAsyncForResult(() ->
+ createRcsFeatureInternal(slotId, subId), "createRcsFeature");
+ } else {
+ return f.getBinder();
+ }
}
@Override
public void addFeatureStatusCallback(int slotId, int featureType,
IImsFeatureStatusCallback c) {
- ImsService.this.addImsFeatureStatusCallback(slotId, featureType, c);
+ executeMethodAsync(() -> ImsService.this.addImsFeatureStatusCallback(
+ slotId, featureType, c), "addFeatureStatusCallback");
}
@Override
public void removeFeatureStatusCallback(int slotId, int featureType,
IImsFeatureStatusCallback c) {
- ImsService.this.removeImsFeatureStatusCallback(slotId, featureType, c);
+ executeMethodAsync(() -> ImsService.this.removeImsFeatureStatusCallback(
+ slotId, featureType, c), "removeFeatureStatusCallback");
}
@Override
- public void removeImsFeature(int slotId, int featureType) {
- ImsService.this.removeImsFeature(slotId, featureType);
+ public void removeImsFeature(int slotId, int featureType, boolean changeSubId) {
+ if (changeSubId && isImsFeatureCreatedForSlot(slotId, featureType)) {
+ Log.w(LOG_TAG, "Do not remove Ims feature for compatibility");
+ return;
+ }
+ executeMethodAsync(() -> ImsService.this.removeImsFeature(slotId, featureType),
+ "removeImsFeature");
+ setImsFeatureCreatedForSlot(slotId, featureType, false);
}
@Override
public ImsFeatureConfiguration querySupportedImsFeatures() {
- return ImsService.this.querySupportedImsFeatures();
+ return executeMethodAsyncForResult(() -> ImsService.this.querySupportedImsFeatures(),
+ "ImsFeatureConfiguration");
}
@Override
public long getImsServiceCapabilities() {
- long caps = ImsService.this.getImsServiceCapabilities();
- long sanitizedCaps = sanitizeCapabilities(caps);
- if (caps != sanitizedCaps) {
- Log.w(LOG_TAG, "removing invalid bits from field: 0x"
- + Long.toHexString(caps ^ sanitizedCaps));
- }
- return sanitizedCaps;
+ return executeMethodAsyncForResult(() -> {
+ long caps = ImsService.this.getImsServiceCapabilities();
+ long sanitizedCaps = sanitizeCapabilities(caps);
+ if (caps != sanitizedCaps) {
+ Log.w(LOG_TAG, "removing invalid bits from field: 0x"
+ + Long.toHexString(caps ^ sanitizedCaps));
+ }
+ return sanitizedCaps;
+ }, "getImsServiceCapabilities");
}
@Override
public void notifyImsServiceReadyForFeatureCreation() {
- ImsService.this.readyForFeatureCreation();
+ executeMethodAsync(() -> ImsService.this.readyForFeatureCreation(),
+ "notifyImsServiceReadyForFeatureCreation");
}
@Override
- public IImsConfig getConfig(int slotId) {
- ImsConfigImplBase c = ImsService.this.getConfig(slotId);
- return c != null ? c.getIImsConfig() : null;
+ public IImsConfig getConfig(int slotId, int subId) {
+ return executeMethodAsyncForResult(() -> {
+ ImsConfigImplBase c =
+ ImsService.this.getConfigForSubscription(slotId, subId);
+ if (c != null) {
+ c.setDefaultExecutor(mExecutor);
+ return c.getIImsConfig();
+ } else {
+ return null;
+ }
+ }, "getConfig");
}
@Override
- public IImsRegistration getRegistration(int slotId) {
- ImsRegistrationImplBase r = ImsService.this.getRegistration(slotId);
- return r != null ? r.getBinder() : null;
+ public IImsRegistration getRegistration(int slotId, int subId) {
+ return executeMethodAsyncForResult(() -> {
+ ImsRegistrationImplBase r =
+ ImsService.this.getRegistrationForSubscription(slotId, subId);
+ if (r != null) {
+ r.setDefaultExecutor(mExecutor);
+ return r.getBinder();
+ } else {
+ return null;
+ }
+ }, "getRegistration");
}
@Override
public ISipTransport getSipTransport(int slotId) {
- SipTransportImplBase s = ImsService.this.getSipTransport(slotId);
- return s != null ? s.getBinder() : null;
+ return executeMethodAsyncForResult(() -> {
+ SipTransportImplBase s = ImsService.this.getSipTransport(slotId);
+ if (s != null) {
+ s.setDefaultExecutor(mExecutor);
+ return s.getBinder();
+ } else {
+ return null;
+ }
+ }, "getSipTransport");
}
@Override
- public void enableIms(int slotId) {
- ImsService.this.enableIms(slotId);
+ public void enableIms(int slotId, int subId) {
+ executeMethodAsync(() ->
+ ImsService.this.enableImsForSubscription(slotId, subId), "enableIms");
}
@Override
- public void disableIms(int slotId) {
- ImsService.this.disableIms(slotId);
+ public void disableIms(int slotId, int subId) {
+ executeMethodAsync(() ->
+ ImsService.this.disableImsForSubscription(slotId, subId), "disableIms");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName) {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "ImsService Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ return null;
+ }
}
};
@@ -288,18 +401,11 @@
return null;
}
- /**
- * @hide
- */
- @VisibleForTesting
- public SparseArray<ImsFeature> getFeatures(int slotId) {
- return mFeaturesBySlot.get(slotId);
- }
-
- private IImsMmTelFeature createMmTelFeatureInternal(int slotId) {
- MmTelFeature f = createMmTelFeature(slotId);
+ private IImsMmTelFeature createMmTelFeatureInternal(int slotId, int subscriptionId) {
+ MmTelFeature f = createMmTelFeatureForSubscription(slotId, subscriptionId);
if (f != null) {
setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
+ f.setDefaultExecutor(mExecutor);
return f.getBinder();
} else {
Log.e(LOG_TAG, "createMmTelFeatureInternal: null feature returned.");
@@ -307,9 +413,22 @@
}
}
- private IImsRcsFeature createRcsFeatureInternal(int slotId) {
- RcsFeature f = createRcsFeature(slotId);
+ private IImsMmTelFeature createEmergencyOnlyMmTelFeatureInternal(int slotId) {
+ MmTelFeature f = createEmergencyOnlyMmTelFeature(slotId);
if (f != null) {
+ setupFeature(f, slotId, ImsFeature.FEATURE_MMTEL);
+ f.setDefaultExecutor(mExecutor);
+ return f.getBinder();
+ } else {
+ Log.e(LOG_TAG, "createEmergencyOnlyMmTelFeatureInternal: null feature returned.");
+ return null;
+ }
+ }
+
+ private IImsRcsFeature createRcsFeatureInternal(int slotId, int subI) {
+ RcsFeature f = createRcsFeatureForSubscription(slotId, subI);
+ if (f != null) {
+ f.setDefaultExecutor(mExecutor);
setupFeature(f, slotId, ImsFeature.FEATURE_RCS);
return f.getBinder();
} else {
@@ -388,6 +507,49 @@
f.onFeatureRemoved();
features.remove(featureType);
}
+
+ }
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public ImsFeature getImsFeature(int slotId, int featureType) {
+ synchronized (mFeaturesBySlot) {
+ // Get SparseArray for Features, by querying slot Id
+ SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
+ if (features == null) {
+ return null;
+ }
+ return features.get(featureType);
+ }
+ }
+
+ private void setImsFeatureCreatedForSlot(int slotId,
+ @ImsFeature.FeatureType int featureType, boolean createdForSlot) {
+ synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
+ getImsFeatureCreatedForSlot(slotId).put(featureType, createdForSlot);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @VisibleForTesting
+ public boolean isImsFeatureCreatedForSlot(int slotId,
+ @ImsFeature.FeatureType int featureType) {
+ synchronized (mCreateImsFeatureWithSlotIdFlagMap) {
+ return getImsFeatureCreatedForSlot(slotId).get(featureType);
+ }
+ }
+
+ private SparseBooleanArray getImsFeatureCreatedForSlot(int slotId) {
+ SparseBooleanArray createFlag = mCreateImsFeatureWithSlotIdFlagMap.get(slotId);
+ if (createFlag == null) {
+ createFlag = new SparseBooleanArray();
+ mCreateImsFeatureWithSlotIdFlagMap.put(slotId, createFlag);
+ }
+ return createFlag;
}
/**
@@ -446,27 +608,95 @@
}
/**
+ * The framework has enabled IMS for the subscription specified, the ImsService should register
+ * for IMS and perform all appropriate initialization to bring up all ImsFeatures.
+ *
+ * @param slotId The slot ID that IMS will be enabled for.
+ * @param subscriptionId The subscription ID that IMS will be enabled for.
+ */
+ public void enableImsForSubscription(int slotId, int subscriptionId) {
+ enableIms(slotId);
+ }
+
+ /**
+ * The framework has disabled IMS for the subscription specified. The ImsService must deregister
+ * for IMS and set capability status to false for all ImsFeatures.
+ * @param slotId The slot ID that IMS will be disabled for.
+ * @param subscriptionId The subscription ID that IMS will be disabled for.
+ */
+ public void disableImsForSubscription(int slotId, int subscriptionId) {
+ disableIms(slotId);
+ }
+
+ /**
* The framework has enabled IMS for the slot specified, the ImsService should register for IMS
* and perform all appropriate initialization to bring up all ImsFeatures.
+ * @deprecated Use {@link #enableImsForSubscription} instead.
*/
+ @Deprecated
public void enableIms(int slotId) {
}
/**
* The framework has disabled IMS for the slot specified. The ImsService must deregister for IMS
* and set capability status to false for all ImsFeatures.
+ * @deprecated Use {@link #disableImsForSubscription} instead.
*/
+ @Deprecated
public void disableIms(int slotId) {
}
/**
* When called, the framework is requesting that a new {@link MmTelFeature} is created for the
+ * specified subscription.
+ *
+ * @param subscriptionId The subscription ID that the MMTEL Feature is being created for.
+ * @return The newly created {@link MmTelFeature} associated with the subscription or null if
+ * the feature is not supported.
+ */
+ public @Nullable MmTelFeature createMmTelFeatureForSubscription(int slotId,
+ int subscriptionId) {
+ setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
+ return createMmTelFeature(slotId);
+ }
+
+ /**
+ * When called, the framework is requesting that a new {@link RcsFeature} is created for the
+ * specified subscription.
+ *
+ * @param subscriptionId The subscription ID that the RCS Feature is being created for.
+ * @return The newly created {@link RcsFeature} associated with the subscription or null if the
+ * feature is not supported.
+ */
+ public @Nullable RcsFeature createRcsFeatureForSubscription(int slotId, int subscriptionId) {
+ setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_RCS, true);
+ return createRcsFeature(slotId);
+ }
+
+ /**
+ * When called, the framework is requesting that a new emergency-only {@link MmTelFeature} is
+ * created for the specified slot. For emergency calls, there is no known Subscription Id.
+ *
+ * @param slotId The slot ID that the MMTEL Feature is being created for.
+ * @return An MmTelFeature instance to be used for the slot ID when there is not
+ * subscription inserted. Only requested when there is no subscription active on
+ * the specified slot.
+ */
+ public @Nullable MmTelFeature createEmergencyOnlyMmTelFeature(int slotId) {
+ setImsFeatureCreatedForSlot(slotId, ImsFeature.FEATURE_MMTEL, true);
+ return createMmTelFeature(slotId);
+ }
+
+ /**
+ * When called, the framework is requesting that a new {@link MmTelFeature} is created for the
* specified slot.
+ * @deprecated Use {@link #createMmTelFeatureForSubscription} instead
*
* @param slotId The slot ID that the MMTEL Feature is being created for.
* @return The newly created {@link MmTelFeature} associated with the slot or null if the
* feature is not supported.
*/
+ @Deprecated
public MmTelFeature createMmTelFeature(int slotId) {
return null;
}
@@ -474,32 +704,62 @@
/**
* When called, the framework is requesting that a new {@link RcsFeature} is created for the
* specified slot.
+ * @deprecated Use {@link #createRcsFeatureForSubscription} instead
*
* @param slotId The slot ID that the RCS Feature is being created for.
* @return The newly created {@link RcsFeature} associated with the slot or null if the feature
* is not supported.
*/
+ @Deprecated
public RcsFeature createRcsFeature(int slotId) {
return null;
}
/**
+ * Return the {@link ImsConfigImplBase} implementation associated with the provided
+ * subscription. This will be used by the platform to get/set specific IMS related
+ * configurations.
+ *
+ * @param subscriptionId The subscription ID that the IMS configuration is associated with.
+ * @return ImsConfig implementation that is associated with the specified subscription.
+ */
+ public @NonNull ImsConfigImplBase getConfigForSubscription(int slotId, int subscriptionId) {
+ return getConfig(slotId);
+ }
+
+ /**
+ * Return the {@link ImsRegistrationImplBase} implementation associated with the provided
+ * subscription.
+ *
+ * @param subscriptionId The subscription ID that is associated with the IMS Registration.
+ * @return the ImsRegistration implementation associated with the subscription.
+ */
+ public @NonNull ImsRegistrationImplBase getRegistrationForSubscription(int slotId,
+ int subscriptionId) {
+ return getRegistration(slotId);
+ }
+
+ /**
* Return the {@link ImsConfigImplBase} implementation associated with the provided slot. This
* will be used by the platform to get/set specific IMS related configurations.
+ * @deprecated use {@link #getConfigForSubscription} instead.
*
* @param slotId The slot that the IMS configuration is associated with.
* @return ImsConfig implementation that is associated with the specified slot.
*/
+ @Deprecated
public ImsConfigImplBase getConfig(int slotId) {
return new ImsConfigImplBase();
}
/**
* Return the {@link ImsRegistrationImplBase} implementation associated with the provided slot.
+ * @deprecated use {@link #getRegistrationForSubscription} instead.
*
* @param slotId The slot that is associated with the IMS Registration.
* @return the ImsRegistration implementation associated with the slot.
*/
+ @Deprecated
public ImsRegistrationImplBase getRegistration(int slotId) {
return new ImsRegistrationImplBase();
}
@@ -562,4 +822,15 @@
result.append("}");
return result.toString();
}
+
+ /**
+ * The ImsService will now be able to define an Executor that the ImsService can be used to
+ * execute the methods. By default all ImsService level method calls will use this Executor.
+ * The ImsService has set the default executor as Runnable::run,
+ * Should be override or default executor will be used.
+ * @return an Executor used to execute methods called remotely by the framework.
+ */
+ public @NonNull Executor getExecutor() {
+ return Runnable::run;
+ }
}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index abc5606..5aef8a6 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -33,6 +33,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyManager;
+import android.telephony.ims.aidl.IFeatureProvisioningCallback;
import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.aidl.IRcsConfigCallback;
import android.telephony.ims.feature.MmTelFeature;
@@ -53,17 +54,11 @@
* IMS provisioning keys are defined per carrier or OEM using OMA-DM or other provisioning
* applications and may vary. It is up to the carrier and OEM applications to ensure that the
* correct provisioning keys are being used when integrating with a vendor's ImsService.
- *
- * Note: For compatibility purposes, the integer values [0 - 99] used in
- * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys
- * previously defined in the Android framework. Please do not redefine new provisioning keys in this
- * range or it may generate collisions with existing keys. Some common constants have also been
- * defined in this class to make integrating with other system apps easier.
- * @hide
*/
-@SystemApi
public class ProvisioningManager {
+ private static final String TAG = "ProvisioningManager";
+
/**@hide*/
@StringDef(prefix = "STRING_QUERY_RESULT_ERROR_", value = {
STRING_QUERY_RESULT_ERROR_GENERIC,
@@ -74,14 +69,18 @@
/**
* The query from {@link #getProvisioningStringValue(int)} has resulted in an unspecified error.
+ * @hide
*/
+ @SystemApi
public static final String STRING_QUERY_RESULT_ERROR_GENERIC =
"STRING_QUERY_RESULT_ERROR_GENERIC";
/**
* The query from {@link #getProvisioningStringValue(int)} has resulted in an error because the
* ImsService implementation was not ready for provisioning queries.
+ * @hide
*/
+ @SystemApi
public static final String STRING_QUERY_RESULT_ERROR_NOT_READY =
"STRING_QUERY_RESULT_ERROR_NOT_READY";
@@ -93,12 +92,16 @@
/**
* The integer result of provisioning for the queried key is disabled.
+ * @hide
*/
+ @SystemApi
public static final int PROVISIONING_VALUE_DISABLED = 0;
/**
* The integer result of provisioning for the queried key is enabled.
+ * @hide
*/
+ @SystemApi
public static final int PROVISIONING_VALUE_ENABLED = 1;
@@ -443,27 +446,31 @@
/**
* Override the user-defined WiFi Roaming enabled setting for this subscription, defined in
- * {@link SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI}, for the purposes of provisioning
- * the subscription for WiFi Calling.
+ * {@link android.telephony.SubscriptionManager#WFC_ROAMING_ENABLED_CONTENT_URI},
+ * for the purposes of provisioning the subscription for WiFi Calling.
*
- * @see #getProvisioningIntValue(int)
* @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ * @hide
*/
+ @SystemApi
public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26;
/**
* Override the user-defined WiFi mode for this subscription, defined in
- * {@link SubscriptionManager#WFC_MODE_CONTENT_URI}, for the purposes of provisioning
- * this subscription for WiFi Calling.
+ * {@link android.telephony.SubscriptionManager#WFC_MODE_CONTENT_URI},
+ * for the purposes of provisioning this subscription for WiFi Calling.
*
* Valid values for this key are:
* {@link ImsMmTelManager#WIFI_MODE_WIFI_ONLY},
* {@link ImsMmTelManager#WIFI_MODE_CELLULAR_PREFERRED}, or
* {@link ImsMmTelManager#WIFI_MODE_WIFI_PREFERRED}.
*
- * @see #getProvisioningIntValue(int)
* @see #setProvisioningIntValue(int, int)
+ * @see #getProvisioningIntValue(int)
+ * @hide
*/
+ @SystemApi
public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27;
/**
@@ -862,7 +869,9 @@
* <p>Value is in String format.
* @see #setProvisioningStringValue(int, String)
* @see #getProvisioningStringValue(int)
+ * @hide
*/
+ @SystemApi
public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67;
/**
@@ -884,7 +893,9 @@
/**
* Callback for IMS provisioning changes.
+ * @hide
*/
+ @SystemApi
public static class Callback {
private static class CallbackBinder extends IImsConfigCallback.Stub {
@@ -954,11 +965,105 @@
}
}
+ /**
+ * Callback for IMS provisioning feature changes.
+ */
+ public static class FeatureProvisioningCallback {
+
+ private static class CallbackBinder extends IFeatureProvisioningCallback.Stub {
+
+ private final FeatureProvisioningCallback mFeatureProvisioningCallback;
+ private Executor mExecutor;
+
+ private CallbackBinder(FeatureProvisioningCallback featureProvisioningCallback) {
+ mFeatureProvisioningCallback = featureProvisioningCallback;
+ }
+
+ @Override
+ public final void onFeatureProvisioningChanged(
+ int capability, int tech, boolean isProvisioned) {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ mFeatureProvisioningCallback.onFeatureProvisioningChanged(
+ capability, tech, isProvisioned));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @Override
+ public final void onRcsFeatureProvisioningChanged(
+ int capability, int tech, boolean isProvisioned) {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() ->
+ mFeatureProvisioningCallback.onRcsFeatureProvisioningChanged(
+ capability, tech, isProvisioned));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ private void setExecutor(Executor executor) {
+ mExecutor = executor;
+ }
+ }
+
+ private final CallbackBinder mBinder = new CallbackBinder(this);
+
+ /**
+ * The IMS MMTEL provisioning has changed for a specific capability and IMS
+ * registration technology.
+ * @param capability The MMTEL capability that provisioning has changed for.
+ * @param tech The IMS registration technology associated with the MMTEL capability that
+ * provisioning has changed for.
+ * @param isProvisioned {@code true} if the capability is provisioned for the technology
+ * specified, or {@code false} if the capability is not provisioned for the technology
+ * specified.
+ */
+ public void onFeatureProvisioningChanged(
+ @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+ boolean isProvisioned) {
+ // Base Implementation
+ }
+
+ /**
+ * The IMS RCS provisioning has changed for a specific capability and IMS
+ * registration technology.
+ * @param capability The RCS capability that provisioning has changed for.
+ * @param tech The IMS registration technology associated with the RCS capability that
+ * provisioning has changed for.
+ * @param isProvisioned {@code true} if the capability is provisioned for the technology
+ * specified, or {@code false} if the capability is not provisioned for the technology
+ * specified.
+ */
+ public void onRcsFeatureProvisioningChanged(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+ boolean isProvisioned) {
+ // Base Implementation
+ }
+
+ /**@hide*/
+ public final IFeatureProvisioningCallback getBinder() {
+ return mBinder;
+ }
+
+ /**@hide*/
+ public void setExecutor(Executor executor) {
+ mBinder.setExecutor(executor);
+ }
+ }
+
private int mSubId;
/**
* The callback for RCS provisioning changes.
+ * @hide
*/
+ @SystemApi
public static class RcsProvisioningCallback {
private static class CallbackBinder extends IRcsConfigCallback.Stub {
@@ -1096,7 +1201,9 @@
* @param subId The ID of the subscription that this ProvisioningManager will use.
* @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
* @throws IllegalArgumentException if the subscription is invalid.
+ * @hide
*/
+ @SystemApi
public static @NonNull ProvisioningManager createForSubscriptionId(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid subscription ID");
@@ -1105,7 +1212,9 @@
return new ProvisioningManager(subId);
}
- private ProvisioningManager(int subId) {
+ /**@hide*/
+ //@SystemApi
+ public ProvisioningManager(int subId) {
mSubId = subId;
}
@@ -1114,6 +1223,12 @@
*
* When the subscription associated with this callback is removed (SIM removed, ESIM swap,
* etc...), this callback will automatically be removed.
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+ * </ul>
+ *
* @param executor The {@link Executor} to call the callback methods on
* @param callback The provisioning callbackto be registered.
* @see #unregisterProvisioningChangedCallback(Callback)
@@ -1124,7 +1239,9 @@
* the {@link ImsService} associated with the subscription is not available. This can happen if
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerProvisioningChangedCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull Callback callback) throws ImsException {
@@ -1142,12 +1259,20 @@
* Unregister an existing {@link Callback}. When the subscription associated with this
* callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be
* removed. If this method is called for an inactive subscription, it will result in a no-op.
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
+ * </ul>
+ *
* @param callback The existing {@link Callback} to be removed.
* @see #registerProvisioningChangedCallback(Executor, Callback)
*
* @throws IllegalArgumentException if the subscription associated with this callback is
* invalid.
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
try {
@@ -1158,6 +1283,62 @@
}
/**
+ * Register a new {@link FeatureProvisioningCallback}, which is used to listen for
+ * IMS feature provisioning updates.
+ * <p>
+ * When the subscription associated with this callback is removed (SIM removed,
+ * ESIM swap,etc...), this callback will automatically be removed.
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+ * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+ * <li>or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
+ * @param executor The executor that the callback methods will be called on.
+ * @param callback The callback instance being registered.
+ * @throws ImsException if the subscription associated with this callback is
+ * valid, but the {@link ImsService the service crashed, for example. See
+ * {@link ImsException#getCode()} for a more detailed reason.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+ public void registerFeatureProvisioningChangedCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull FeatureProvisioningCallback callback) throws ImsException {
+ callback.setExecutor(executor);
+ try {
+ getITelephony().registerFeatureProvisioningChangedCallback(mSubId,
+ callback.getBinder());
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
+ } catch (RemoteException | IllegalStateException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ /**
+ * Unregisters a previously registered {@link FeatureProvisioningCallback}
+ * instance. When the subscription associated with this
+ * callback is removed (SIM removed, ESIM swap, etc...), this callback will
+ * automatically be removed. If this method is called for an inactive
+ * subscription, it will result in a no-op.
+ *
+ * @param callback The existing {@link FeatureProvisioningCallback} to be removed.
+ * @see #registerFeatureProvisioningChangedCallback(Executor, FeatureProvisioningCallback)
+ */
+ public void unregisterFeatureProvisioningChangedCallback(
+ @NonNull FeatureProvisioningCallback callback) {
+ try {
+ getITelephony().unregisterFeatureProvisioningChangedCallback(mSubId,
+ callback.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* Query for the integer value associated with the provided key.
*
* This operation is blocking and should not be performed on the UI thread.
@@ -1166,7 +1347,9 @@
* @return an integer value for the provided key, or
* {@link ImsConfigImplBase#CONFIG_RESULT_UNKNOWN} if the key doesn't exist.
* @throws IllegalArgumentException if the key provided was invalid.
+ * @hide
*/
+ @SystemApi
@WorkerThread
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public int getProvisioningIntValue(int key) {
@@ -1186,7 +1369,9 @@
* @return a String value for the provided key, {@code null} if the key doesn't exist, or
* {@link StringResultError} if there was an error getting the value for the provided key.
* @throws IllegalArgumentException if the key provided was invalid.
+ * @hide
*/
+ @SystemApi
@WorkerThread
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @Nullable @StringResultError String getProvisioningStringValue(int key) {
@@ -1207,7 +1392,15 @@
* @param key An integer that represents the provisioning key, which is defined by the OEM.
* @param value a integer value for the provided key.
* @return the result of setting the configuration value.
+ * @hide
+ *
+ * Note: For compatibility purposes, the integer values [0 - 99] used in
+ * {@link #setProvisioningIntValue(int, int)} have been reserved for existing provisioning keys
+ * previously defined in the Android framework. Please do not redefine new provisioning keys
+ * in this range or it may generate collisions with existing keys. Some common constants have
+ * also been defined in this class to make integrating with other system apps easier.
*/
+ @SystemApi
@WorkerThread
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public @ImsConfigImplBase.SetConfigResult int setProvisioningIntValue(int key, int value) {
@@ -1227,7 +1420,9 @@
* should be appropriately namespaced to avoid collision.
* @param value a String value for the provided key.
* @return the result of setting the configuration value.
+ * @hide
*/
+ @SystemApi
@WorkerThread
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public @ImsConfigImplBase.SetConfigResult int setProvisioningStringValue(int key,
@@ -1247,8 +1442,14 @@
* does not support the capability/technology combination specified, this operation will be a
* no-op.
*
- * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL
- * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
+ * <p>Requires Permission:
+ * <ul>
+ * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+ * <li>or that the calling app has carrier privileges (see</li>
+ * <li>{@link TelephonyManager#hasCarrierPrivileges}).</li>
+ * </ul>
+ *
+ * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
* @param isProvisioned true if the device is provisioned for UT over IMS, false otherwise.
*/
@WorkerThread
@@ -1256,9 +1457,10 @@
public void setProvisioningStatusForCapability(
@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) {
+
try {
getITelephony().setImsProvisioningStatusForCapability(mSubId, capability, tech,
- isProvisioned);
+ isProvisioned);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -1272,14 +1474,21 @@
* {@link ImsRegistrationImplBase.ImsRegistrationTech} combination specified, this method will
* always return {@code true}.
*
- * @see CarrierConfigManager#KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL
- * @see CarrierConfigManager#KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL
+ * <p> Requires Permission:
+ * <ul>
+ * <li>android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+ * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+ * <li>or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
+ * @see CarrierConfigManager.Ims#KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE
* @return true if the device is provisioned for the capability or does not require
* provisioning, false if the capability does require provisioning and has not been
* provisioned yet.
*/
@WorkerThread
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public boolean getProvisioningStatusForCapability(
@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int tech) {
@@ -1297,17 +1506,93 @@
* {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method will always return
* {@code true}.
*
- * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+ * @see CarrierConfigManager.Ims#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
* @return true if the device is provisioned for the capability or does not require
* provisioning, false if the capability does require provisioning and has not been
* provisioned yet.
+ * @deprecated Use {@link #getRcsProvisioningStatusForCapability(int, int)} instead,
+ * as this only retrieves provisioning information for
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}
+ * @hide
*/
+ @Deprecated
+ @SystemApi
@WorkerThread
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean getRcsProvisioningStatusForCapability(
@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
try {
- return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability);
+ return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Get the provisioning status for the IMS RCS capability specified.
+ *
+ * If provisioning is not required for the queried
+ * {@link RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag} this method
+ * will always return {@code true}.
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+ * <li>or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
+ * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
+ * @return true if the device is provisioned for the capability or does not require
+ * provisioning, false if the capability does require provisioning and has not been
+ * provisioned yet.
+ */
+ @WorkerThread
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+ public boolean getRcsProvisioningStatusForCapability(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+ try {
+ return getITelephony().getRcsProvisioningStatusForCapability(mSubId, capability, tech);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Set the provisioning status for the IMS RCS capability using the specified subscription.
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE}</li>
+ * <li>or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+
+ * Provisioning may or may not be required, depending on the carrier configuration. If
+ * provisioning is not required for the carrier associated with this subscription or the device
+ * does not support the capability/technology combination specified, this operation will be a
+ * no-op.
+ *
+ * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+ * @param isProvisioned true if the device is provisioned for the RCS capability specified,
+ * false otherwise.
+ * @deprecated Use {@link #setRcsProvisioningStatusForCapability(int, int, boolean)} instead,
+ * as this method only sets provisioning information for
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}
+ * @hide
+ */
+ @Deprecated
+ @SystemApi
+ @WorkerThread
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setRcsProvisioningStatusForCapability(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ boolean isProvisioned) {
+ try {
+ getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE, isProvisioned);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -1321,7 +1606,14 @@
* does not support the capability/technology combination specified, this operation will be a
* no-op.
*
- * @see CarrierConfigManager#KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL
+ * <p> Requires Permission:
+ * <ul>
+ * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li>
+ * <li>or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
+ * @see CarrierConfigManager.Ims#KEY_RCS_REQUIRES_PROVISIONING_BUNDLE
* @param isProvisioned true if the device is provisioned for the RCS capability specified,
* false otherwise.
*/
@@ -1329,31 +1621,92 @@
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setRcsProvisioningStatusForCapability(
@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
- boolean isProvisioned) {
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech, boolean isProvisioned) {
try {
getITelephony().setRcsProvisioningStatusForCapability(mSubId, capability,
- isProvisioned);
+ tech, isProvisioned);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
/**
+ * Indicates whether provisioning for the MMTEL capability and IMS registration technology
+ * specified is required or not
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+ * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+ * <li> or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
+ * @return true if provisioning is required for the MMTEL capability and IMS
+ * registration technology specified, false if it is not required.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+ public boolean isProvisioningRequiredForCapability(
+ @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+ try {
+ return getITelephony().isProvisioningRequiredForCapability(mSubId, capability, tech);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+
+ /**
+ * Indicates whether provisioning for the RCS capability and IMS registration technology
+ * specified is required or not
+ *
+ * <p> Requires Permission:
+ * <ul>
+ * <li> android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE,</li>
+ * <li>{@link android.Manifest.permission#READ_PRECISE_PHONE_STATE},</li>
+ * <li> or that the caller has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
+ * @return true if provisioning is required for the RCS capability and IMS
+ * registration technology specified, false if it is not required.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+ public boolean isRcsProvisioningRequiredForCapability(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech) {
+ try {
+ return getITelephony().isRcsProvisioningRequiredForCapability(mSubId, capability, tech);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+
+ /**
* Notify the framework that an RCS autoconfiguration XML file has been received for
* provisioning.
- * <p>
- * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has
- * carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+ *
+ * <p>Requires Permission:
+ * <ul>
+ * <li>{@link Manifest.permission#MODIFY_PHONE_STATE},</li>
+ * <li>or that the calling app has carrier privileges (see
+ * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
+ * </ul>
+ *
* @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
* @param isCompressed The XML file is compressed in gzip format and must be decompressed
* before being read.
- *
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
if (config == null) {
throw new IllegalArgumentException("Must include a non-null config XML file.");
}
+
try {
getITelephony().notifyRcsAutoConfigurationReceived(mSubId, config, isCompressed);
} catch (RemoteException e) {
@@ -1372,7 +1725,9 @@
* <p>Contains {@link #EXTRA_SUBSCRIPTION_ID} to specify the subscription index for which
* the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
* status.
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE =
@@ -1380,7 +1735,9 @@
/**
* Integer extra to specify subscription index.
+ * @hide
*/
+ @SystemApi
public static final String EXTRA_SUBSCRIPTION_ID =
"android.telephony.ims.extra.SUBSCRIPTION_ID";
@@ -1390,22 +1747,30 @@
* <p>The value can be {@link #STATUS_CAPABLE}, {@link #STATUS_DEVICE_NOT_CAPABLE},
* {@link #STATUS_CARRIER_NOT_CAPABLE}, or bitwise OR of
* {@link #STATUS_DEVICE_NOT_CAPABLE} and {@link #STATUS_CARRIER_NOT_CAPABLE}.
+ * @hide
*/
+ @SystemApi
public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
/**
* RCS VoLTE single registration is supported by the device and carrier.
+ * @hide
*/
+ @SystemApi
public static final int STATUS_CAPABLE = 0;
/**
* RCS VoLTE single registration is not supported by the device.
+ * @hide
*/
+ @SystemApi
public static final int STATUS_DEVICE_NOT_CAPABLE = 0x01;
/**
* RCS VoLTE single registration is not supported by the carrier
+ * @hide
*/
+ @SystemApi
public static final int STATUS_CARRIER_NOT_CAPABLE = 0x01 << 1;
/**
@@ -1415,11 +1780,14 @@
* provisioning is done using autoconfiguration, then these parameters shall be
* sent in the HTTP get request to fetch the RCS provisioning. RCS client
* configuration must be provided by the application before registering for the
- * provisioning status events {@link #registerRcsProvisioningCallback()}
+ * provisioning status events
+ * {@link #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)}
* When the IMS/RCS service receives the RCS client configuration, it will detect
* the change in the configuration, and trigger the auto-configuration as needed.
* @param rcc RCS client configuration {@link RcsClientConfiguration}
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
public void setRcsClientConfiguration(
@NonNull RcsClientConfiguration rcc) throws ImsException {
@@ -1440,18 +1808,21 @@
* <ul>
* <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
* <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
- * <li>or that the caller has carrier privileges (see
+ * <li>or that the calling app has carrier privileges (see
* {@link TelephonyManager#hasCarrierPrivileges()}).</li>
* </ul>
+ *
* @return true if IMS single registration is capable at this time, or false otherwise
- * @throws ImsException If the remote ImsService is not available for
- * any reason or the subscription associated with this instance is no
- * longer active. See {@link ImsException#getCode()} for more
- * information.
+ * @throws ImsException If the remote ImsService is not available for any reason or
+ * the subscription associated with this instance is no longer active.
+ * See {@link ImsException#getCode()} for more information.
* @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this
* device supports IMS single registration.
+ * @hide
*/
- @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
try {
@@ -1478,8 +1849,6 @@
* <ul>
* <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
* <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
- * <li>or that the caller has carrier privileges (see
- * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
* </ul>
*
* @param executor The {@link Executor} to call the callback methods on
@@ -1497,8 +1866,11 @@
* params (See {@link #setRcsClientConfiguration}) and re register the
* callback.
* See {@link ImsException#getCode()} for a more detailed reason.
+ * @hide
*/
- @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
public void registerRcsProvisioningCallback(
@NonNull @CallbackExecutor Executor executor,
@@ -1525,8 +1897,6 @@
* <ul>
* <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li>
* <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li>
- * <li>or that the caller has carrier privileges (see
- * {@link TelephonyManager#hasCarrierPrivileges()}).</li>
* </ul>
*
* @param callback The existing {@link RcsProvisioningCallback} to be
@@ -1534,8 +1904,11 @@
* @see #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback)
* @throws IllegalArgumentException if the subscription associated with
* this callback is invalid.
+ * @hide
*/
- @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
public void unregisterRcsProvisioningCallback(
@NonNull RcsProvisioningCallback callback) {
@@ -1556,9 +1929,10 @@
* {@link RcsProvisioningCallback} may expect to receive
* {@link RcsProvisioningCallback#onConfigurationReset}, then
* {@link RcsProvisioningCallback#onConfigurationChanged} when the new
- * RCS configuration is received and notified by
- * {@link #notifyRcsAutoConfigurationReceived}
+ * RCS configuration is received and notified by {@link #notifyRcsAutoConfigurationReceived}
+ * @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION)
public void triggerRcsReconfiguration() {
try {
diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
index c25ace0..f367e40 100644
--- a/telephony/java/android/telephony/ims/RcsClientConfiguration.java
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
@@ -34,7 +34,7 @@
/**@hide*/
@StringDef(prefix = "RCS_PROFILE_",
- value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3})
+ value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3, RCS_PROFILE_2_4})
public @interface StringRcsProfile {}
/**
@@ -45,6 +45,10 @@
* RCS profile UP 2.3
*/
public static final String RCS_PROFILE_2_3 = "UP_2.3";
+ /**
+ * RCS profile UP 2.4
+ */
+ public static final String RCS_PROFILE_2_4 = "UP_2.4";
private String mRcsVersion;
private String mRcsProfile;
@@ -58,8 +62,8 @@
* @param rcsVersion The parameter identifies the RCS version supported
* by the client. Refer to GSMA RCC.07 "rcs_version" parameter.
* @param rcsProfile Identifies a fixed set of RCS services that are
- * supported by the client. See {@link #RCS_PROFILE_1_0 } or
- * {@link #RCS_PROFILE_2_3 }
+ * supported by the client. See {@link #RCS_PROFILE_1_0 },
+ * {@link #RCS_PROFILE_2_3 } or {@link #RCS_PROFILE_2_4 }
* @param clientVendor Identifies the vendor providing the RCS client.
* @param clientVersion Identifies the RCS client version. Refer to GSMA
* RCC.07 "client_version" parameter.
@@ -80,8 +84,8 @@
* @param rcsVersion The parameter identifies the RCS version supported
* by the client. Refer to GSMA RCC.07 "rcs_version" parameter.
* @param rcsProfile Identifies a fixed set of RCS services that are
- * supported by the client. See {@link #RCS_PROFILE_1_0 } or
- * {@link #RCS_PROFILE_2_3 }
+ * supported by the client. See {@link #RCS_PROFILE_1_0 },
+ * {@link #RCS_PROFILE_2_3 } or {@link #RCS_PROFILE_2_4 }
* @param clientVendor Identifies the vendor providing the RCS client.
* @param clientVersion Identifies the RCS client version. Refer to GSMA
* RCC.07 "client_version" parameter.
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 61de3ac..154bb11 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -268,6 +268,13 @@
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
+ /**
+ * A capability update has been requested due to IMS being registered over INTERNET PDN.
+ * @hide
+ */
+ @SystemApi
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN = 12;
+
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "ERROR_", value = {
@@ -282,7 +289,8 @@
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
- CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_INTERNET_PDN
})
public @interface StackPublishTriggerType {}
diff --git a/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl
new file mode 100644
index 0000000..63ec4aa
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IFeatureProvisioningCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 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 android.telephony.ims.aidl;
+
+/**
+ * Provides callback interface for FeatureProvisioning when a value has changed.
+ *
+ * {@hide}
+ */
+oneway interface IFeatureProvisioningCallback {
+ void onFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned);
+ void onRcsFeatureProvisioningChanged(int capability, int tech, boolean isProvisioned);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index c6966b3..ae6166f 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -32,18 +32,19 @@
*/
interface IImsServiceController {
void setListener(IImsServiceControllerListener l);
- IImsMmTelFeature createMmTelFeature(int slotId);
- IImsRcsFeature createRcsFeature(int slotId);
+ IImsMmTelFeature createMmTelFeature(int slotId, int subId);
+ IImsMmTelFeature createEmergencyOnlyMmTelFeature(int slotId);
+ IImsRcsFeature createRcsFeature(int slotId, int subId);
ImsFeatureConfiguration querySupportedImsFeatures();
long getImsServiceCapabilities();
void addFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
void removeFeatureStatusCallback(int slotId, int featureType, in IImsFeatureStatusCallback c);
// Synchronous call to ensure the ImsService is ready before continuing with feature creation.
void notifyImsServiceReadyForFeatureCreation();
- void removeImsFeature(int slotId, int featureType);
- IImsConfig getConfig(int slotId);
- IImsRegistration getRegistration(int slotId);
+ void removeImsFeature(int slotId, int featureType, boolean changeSubId);
+ IImsConfig getConfig(int slotId, int subId);
+ IImsRegistration getRegistration(int slotId, int subId);
ISipTransport getSipTransport(int slotId);
- oneway void enableIms(int slotId);
- oneway void disableIms(int slotId);
+ oneway void enableIms(int slotId, int subId);
+ oneway void disableIms(int slotId, int subId);
}
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 9a3f592..ad2e9e1 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -40,16 +40,25 @@
import android.telephony.ims.stub.ImsSmsImplBase;
import android.telephony.ims.stub.ImsUtImplBase;
import android.util.ArraySet;
+import android.util.Log;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsUt;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
/**
* Base implementation for Voice and SMS (IR-92) and Video (IR-94) IMS support.
@@ -60,6 +69,7 @@
public class MmTelFeature extends ImsFeature {
private static final String LOG_TAG = "MmTelFeature";
+ private Executor mExecutor;
/**
* @hide
@@ -68,160 +78,261 @@
public MmTelFeature() {
}
+ /**
+ * Create a new MmTelFeature using the Executor specified for methods being called by the
+ * framework.
+ * @param executor The executor for the framework to use when executing the methods overridden
+ * by the implementation of MmTelFeature.
+ * @hide
+ */
+ @SystemApi
+ public MmTelFeature(@NonNull Executor executor) {
+ super();
+ mExecutor = executor;
+ }
+
private final IImsMmTelFeature mImsMMTelBinder = new IImsMmTelFeature.Stub() {
@Override
public void setListener(IImsMmTelListener l) {
- MmTelFeature.this.setListener(l);
+ executeMethodAsyncNoException(() -> MmTelFeature.this.setListener(l), "setListener");
}
@Override
public int getFeatureState() throws RemoteException {
- try {
- return MmTelFeature.this.getFeatureState();
- } catch (Exception e) {
- throw new RemoteException(e.getMessage());
- }
+ return executeMethodAsyncForResult(() -> MmTelFeature.this.getFeatureState(),
+ "getFeatureState");
}
-
@Override
public ImsCallProfile createCallProfile(int callSessionType, int callType)
throws RemoteException {
- synchronized (mLock) {
- try {
- return MmTelFeature.this.createCallProfile(callSessionType, callType);
- } catch (Exception e) {
- throw new RemoteException(e.getMessage());
- }
- }
+ return executeMethodAsyncForResult(() -> MmTelFeature.this.createCallProfile(
+ callSessionType, callType), "createCallProfile");
}
@Override
public void changeOfferedRtpHeaderExtensionTypes(List<RtpHeaderExtensionType> types)
throws RemoteException {
- synchronized (mLock) {
- try {
- MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(new ArraySet<>(types));
- } catch (Exception e) {
- throw new RemoteException(e.getMessage());
- }
- }
+ executeMethodAsync(() -> MmTelFeature.this.changeOfferedRtpHeaderExtensionTypes(
+ new ArraySet<>(types)), "changeOfferedRtpHeaderExtensionTypes");
}
@Override
public IImsCallSession createCallSession(ImsCallProfile profile) throws RemoteException {
- synchronized (mLock) {
- return createCallSessionInterface(profile);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ IImsCallSession result = executeMethodAsyncForResult(() -> {
+ try {
+ return createCallSessionInterface(profile);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return null;
+ }
+ }, "createCallSession");
+
+ if (exceptionRef.get() != null) {
+ throw exceptionRef.get();
}
+
+ return result;
}
@Override
public int shouldProcessCall(String[] numbers) {
- synchronized (mLock) {
- return MmTelFeature.this.shouldProcessCall(numbers);
+ Integer result = executeMethodAsyncForResultNoException(() ->
+ MmTelFeature.this.shouldProcessCall(numbers), "shouldProcessCall");
+ if (result != null) {
+ return result.intValue();
+ } else {
+ return PROCESS_CALL_CSFB;
}
}
@Override
public IImsUt getUtInterface() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getUtInterface();
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ IImsUt result = executeMethodAsyncForResult(() -> {
+ try {
+ return MmTelFeature.this.getUtInterface();
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return null;
+ }
+ }, "getUtInterface");
+
+ if (exceptionRef.get() != null) {
+ throw exceptionRef.get();
}
+
+ return result;
}
@Override
public IImsEcbm getEcbmInterface() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getEcbmInterface();
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ IImsEcbm result = executeMethodAsyncForResult(() -> {
+ try {
+ return MmTelFeature.this.getEcbmInterface();
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return null;
+ }
+ }, "getEcbmInterface");
+
+ if (exceptionRef.get() != null) {
+ throw exceptionRef.get();
}
+
+ return result;
}
@Override
public void setUiTtyMode(int uiTtyMode, Message onCompleteMessage) throws RemoteException {
- synchronized (mLock) {
- try {
- MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage);
- } catch (Exception e) {
- throw new RemoteException(e.getMessage());
- }
- }
+ executeMethodAsync(() -> MmTelFeature.this.setUiTtyMode(uiTtyMode, onCompleteMessage),
+ "setUiTtyMode");
}
@Override
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
- synchronized (mLock) {
- return MmTelFeature.this.getMultiEndpointInterface();
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ IImsMultiEndpoint result = executeMethodAsyncForResult(() -> {
+ try {
+ return MmTelFeature.this.getMultiEndpointInterface();
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return null;
+ }
+ }, "getMultiEndpointInterface");
+
+ if (exceptionRef.get() != null) {
+ throw exceptionRef.get();
}
+
+ return result;
}
@Override
public int queryCapabilityStatus() {
- return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+ Integer result = executeMethodAsyncForResultNoException(() -> MmTelFeature.this
+ .queryCapabilityStatus().mCapabilities, "queryCapabilityStatus");
+
+ if (result != null) {
+ return result.intValue();
+ } else {
+ return 0;
+ }
}
@Override
public void addCapabilityCallback(IImsCapabilityCallback c) {
- // no need to lock, structure already handles multithreading.
- MmTelFeature.this.addCapabilityCallback(c);
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .addCapabilityCallback(c), "addCapabilityCallback");
}
@Override
public void removeCapabilityCallback(IImsCapabilityCallback c) {
- // no need to lock, structure already handles multithreading.
- MmTelFeature.this.removeCapabilityCallback(c);
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .removeCapabilityCallback(c), "removeCapabilityCallback");
}
@Override
public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
IImsCapabilityCallback c) {
- MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .requestChangeEnabledCapabilities(request, c),
+ "changeCapabilitiesConfiguration");
}
@Override
public void queryCapabilityConfiguration(int capability, int radioTech,
IImsCapabilityCallback c) {
- queryCapabilityConfigurationInternal(capability, radioTech, c);
+ executeMethodAsyncNoException(() -> queryCapabilityConfigurationInternal(
+ capability, radioTech, c), "queryCapabilityConfiguration");
}
@Override
public void setSmsListener(IImsSmsListener l) {
- MmTelFeature.this.setSmsListener(l);
+ executeMethodAsyncNoException(() -> MmTelFeature.this.setSmsListener(l),
+ "setSmsListener");
}
@Override
public void sendSms(int token, int messageRef, String format, String smsc, boolean retry,
byte[] pdu) {
- synchronized (mLock) {
- MmTelFeature.this.sendSms(token, messageRef, format, smsc, retry, pdu);
- }
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .sendSms(token, messageRef, format, smsc, retry, pdu), "sendSms");
}
@Override
public void acknowledgeSms(int token, int messageRef, int result) {
- synchronized (mLock) {
- MmTelFeature.this.acknowledgeSms(token, messageRef, result);
- }
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .acknowledgeSms(token, messageRef, result), "acknowledgeSms");
}
@Override
public void acknowledgeSmsReport(int token, int messageRef, int result) {
- synchronized (mLock) {
- MmTelFeature.this.acknowledgeSmsReport(token, messageRef, result);
- }
+ executeMethodAsyncNoException(() -> MmTelFeature.this
+ .acknowledgeSmsReport(token, messageRef, result), "acknowledgeSmsReport");
}
@Override
public String getSmsFormat() {
- synchronized (mLock) {
- return MmTelFeature.this.getSmsFormat();
- }
+ return executeMethodAsyncForResultNoException(() -> MmTelFeature.this
+ .getSmsFormat(), "getSmsFormat");
}
@Override
public void onSmsReady() {
- synchronized (mLock) {
- MmTelFeature.this.onSmsReady();
+ executeMethodAsyncNoException(() -> MmTelFeature.this.onSmsReady(),
+ "onSmsReady");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResult(Supplier<T> r,
+ String errorLogName) throws RemoteException {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResultNoException(Supplier<T> r,
+ String errorLogName) {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "MmTelFeature Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ return null;
}
}
};
@@ -283,6 +394,13 @@
public @interface MmTelCapability {}
/**
+ * Undefined capability type for initialization
+ * This is used to check the upper range of MmTel capability
+ * {@hide}
+ */
+ public static final int CAPABILITY_TYPE_NONE = 0;
+
+ /**
* This MmTelFeature supports Voice calling (IR.92)
*/
public static final int CAPABILITY_TYPE_VOICE = 1 << 0;
@@ -308,6 +426,12 @@
public static final int CAPABILITY_TYPE_CALL_COMPOSER = 1 << 4;
/**
+ * This is used to check the upper range of MmTel capability
+ * {@hide}
+ */
+ public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_CALL_COMPOSER + 1;
+
+ /**
* @hide
*/
@Override
@@ -672,7 +796,12 @@
public IImsCallSession createCallSessionInterface(ImsCallProfile profile)
throws RemoteException {
ImsCallSessionImplBase s = MmTelFeature.this.createCallSession(profile);
- return s != null ? s.getServiceImpl() : null;
+ if (s != null) {
+ s.setDefaultExecutor(mExecutor);
+ return s.getServiceImpl();
+ } else {
+ return null;
+ }
}
/**
@@ -713,7 +842,12 @@
*/
protected IImsUt getUtInterface() throws RemoteException {
ImsUtImplBase utImpl = getUt();
- return utImpl != null ? utImpl.getInterface() : null;
+ if (utImpl != null) {
+ utImpl.setDefaultExecutor(mExecutor);
+ return utImpl.getInterface();
+ } else {
+ return null;
+ }
}
/**
@@ -721,7 +855,12 @@
*/
protected IImsEcbm getEcbmInterface() throws RemoteException {
ImsEcbmImplBase ecbmImpl = getEcbm();
- return ecbmImpl != null ? ecbmImpl.getImsEcbm() : null;
+ if (ecbmImpl != null) {
+ ecbmImpl.setDefaultExecutor(mExecutor);
+ return ecbmImpl.getImsEcbm();
+ } else {
+ return null;
+ }
}
/**
@@ -729,7 +868,12 @@
*/
public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
ImsMultiEndpointImplBase multiendpointImpl = getMultiEndpoint();
- return multiendpointImpl != null ? multiendpointImpl.getIImsMultiEndpoint() : null;
+ if (multiendpointImpl != null) {
+ multiendpointImpl.setDefaultExecutor(mExecutor);
+ return multiendpointImpl.getIImsMultiEndpoint();
+ } else {
+ return null;
+ }
}
/**
@@ -859,4 +1003,16 @@
public final IImsMmTelFeature getBinder() {
return mImsMMTelBinder;
}
+
+ /**
+ * Set default Executor from ImsService.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of MmTelFeature.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ if (mExecutor == null) {
+ mExecutor = executor;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 18cc37d..70e4ef1 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -59,9 +59,7 @@
/**
* Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
* this class and provide implementations of the RcsFeature methods that they support.
- * @hide
*/
-@SystemApi
public class RcsFeature extends ImsFeature {
private static final String LOG_TAG = "RcsFeature";
@@ -70,7 +68,7 @@
// Reference the outer class in order to have better test coverage metrics instead of
// creating a inner class referencing the outer class directly.
private final RcsFeature mReference;
- private final Executor mExecutor;
+ private Executor mExecutor;
RcsFeatureBinder(RcsFeature classRef, @CallbackExecutor Executor executor) {
mReference = classRef;
@@ -186,14 +184,14 @@
* Contains the capabilities defined and supported by a {@link RcsFeature} in the
* form of a bitmask. The capabilities that are used in the RcsFeature are
* defined as:
- * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
- * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
+ * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
+ * {RcsUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
*
* The enabled capabilities of this RcsFeature will be set by the framework
- * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
+ * using {#changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
* After the capabilities have been set, the RcsFeature may then perform the necessary bring up
* of the capability and notify the capability status as true using
- * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
+ * {#notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
* framework that the capability is available for usage.
*/
public static class RcsImsCapabilities extends Capabilities {
@@ -227,10 +225,18 @@
public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
/**
+ * This is used to check the upper range of RCS capability
+ * {@hide}
+ */
+ public static final int CAPABILITY_TYPE_MAX = CAPABILITY_TYPE_PRESENCE_UCE + 1;
+
+ /**
* Create a new {@link RcsImsCapabilities} instance with the provided capabilities.
* @param capabilities The capabilities that are supported for RCS in the form of a
* bitfield.
+ * @hide
*/
+ @SystemApi
public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super(capabilities);
}
@@ -243,23 +249,35 @@
super(capabilities.getMask());
}
+ /**
+ * @hide
+ */
@Override
+ @SystemApi
public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super.addCapabilities(capabilities);
}
+ /**
+ * @hide
+ */
@Override
+ @SystemApi
public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super.removeCapabilities(capabilities);
}
+ /**
+ * @hide
+ */
@Override
+ @SystemApi
public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
return super.isCapable(capabilities);
}
}
- private final Executor mExecutor;
+ private Executor mExecutor;
private final RcsFeatureBinder mImsRcsBinder;
private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
private CapabilityExchangeEventListener mCapExchangeEventListener;
@@ -270,13 +288,11 @@
* Method stubs called from the framework will be called asynchronously. To specify the
* {@link Executor} that the methods stubs will be called, use
* {@link RcsFeature#RcsFeature(Executor)} instead.
- *
- * @deprecated Use {@link #RcsFeature(Executor)} to create the RcsFeature.
+ * @hide
*/
- @Deprecated
+ @SystemApi
public RcsFeature() {
super();
- mExecutor = Runnable::run;
// Run on the Binder threads that call them.
mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
}
@@ -286,7 +302,9 @@
* framework.
* @param executor The executor for the framework to use when executing the methods overridden
* by the implementation of RcsFeature.
+ * @hide
*/
+ @SystemApi
public RcsFeature(@NonNull Executor executor) {
super();
if (executor == null) {
@@ -305,7 +323,7 @@
* @hide
*/
@Override
- public void initialize(Context context, int slotId) {
+ public void initialize(@NonNull Context context, @NonNull int slotId) {
super.initialize(context, slotId);
// Notify that the RcsFeature is ready.
mExecutor.execute(() -> onFeatureReady());
@@ -317,8 +335,10 @@
* requests. To change the status of the capabilities
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called.
* @return A copy of the current RcsFeature capability status.
+ * @hide
*/
@Override
+ @SystemApi
public @NonNull final RcsImsCapabilities queryCapabilityStatus() {
return new RcsImsCapabilities(super.queryCapabilityStatus());
}
@@ -328,7 +348,9 @@
* this signals to the framework that the capability has been initialized and is ready.
* Call {@link #queryCapabilityStatus()} to return the current capability status.
* @param capabilities The current capability status of the RcsFeature.
+ * @hide
*/
+ @SystemApi
public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) {
if (capabilities == null) {
throw new IllegalArgumentException("RcsImsCapabilities must be non-null!");
@@ -345,7 +367,9 @@
* @param capability The capability that we are querying the configuration for.
* @param radioTech The radio technology type that we are querying.
* @return true if the capability is enabled, false otherwise.
+ * @hide
*/
+ @SystemApi
public boolean queryCapabilityConfiguration(
@RcsUceAdapter.RcsImsCapabilityFlag int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
@@ -368,8 +392,10 @@
* be called for each capability change that resulted in an error.
* @param request The request to change the capability.
* @param callback To notify the framework that the result of the capability changes.
+ * @hide
*/
@Override
+ @SystemApi
public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
@NonNull CapabilityCallbackProxy callback) {
// Base Implementation - Override to provide functionality
@@ -389,7 +415,9 @@
* event to the framework.
* @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
* exchange if it is supported by the device.
+ * @hide
*/
+ @SystemApi
public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
@NonNull CapabilityExchangeEventListener listener) {
// Base Implementation, override to implement functionality
@@ -399,20 +427,28 @@
/**
* Remove the given CapabilityExchangeImplBase instance.
* @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be destroyed.
+ * @hide
*/
+ @SystemApi
public void destroyCapabilityExchangeImpl(
@NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
// Override to implement the process of destroying RcsCapabilityExchangeImplBase instance.
}
- /**{@inheritDoc}*/
+ /**{@inheritDoc}
+ * @hide
+ */
@Override
+ @SystemApi
public void onFeatureRemoved() {
}
- /**{@inheritDoc}*/
+ /**{@inheritDoc}
+ * @hide
+ */
@Override
+ @SystemApi
public void onFeatureReady() {
}
@@ -477,4 +513,17 @@
return mCapabilityExchangeImpl;
}
}
+
+ /**
+ * Set default Executor from ImsService.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of RcsFeature.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ if (mImsRcsBinder.mExecutor == null) {
+ mExecutor = executor;
+ mImsRcsBinder.mExecutor = executor;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index a3a6cb8..e810095 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -30,12 +30,20 @@
import android.telephony.ims.RtpHeaderExtensionType;
import android.telephony.ims.aidl.IImsCallSessionListener;
import android.util.ArraySet;
+import android.util.Log;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsVideoCallProvider;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
/**
* Base implementation of IImsCallSession, which implements stub versions of the methods available.
@@ -48,6 +56,8 @@
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsCallSession maintained by other ImsServices.
public class ImsCallSessionImplBase implements AutoCloseable {
+
+ private static final String LOG_TAG = "ImsCallSessionImplBase";
/**
* Notify USSD Mode.
*/
@@ -110,185 +120,235 @@
}
}
+ private Executor mExecutor = Runnable::run;
+
// Non-final for injection by tests
private IImsCallSession mServiceImpl = new IImsCallSession.Stub() {
@Override
public void close() {
- ImsCallSessionImplBase.this.close();
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.close(), "close");
}
@Override
public String getCallId() {
- return ImsCallSessionImplBase.this.getCallId();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallId(),
+ "getCallId");
}
@Override
public ImsCallProfile getCallProfile() {
- return ImsCallSessionImplBase.this.getCallProfile();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getCallProfile(),
+ "getCallProfile");
}
@Override
public ImsCallProfile getLocalCallProfile() {
- return ImsCallSessionImplBase.this.getLocalCallProfile();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+ .getLocalCallProfile(), "getLocalCallProfile");
}
@Override
public ImsCallProfile getRemoteCallProfile() {
- return ImsCallSessionImplBase.this.getRemoteCallProfile();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+ .getRemoteCallProfile(), "getRemoteCallProfile");
}
@Override
public String getProperty(String name) {
- return ImsCallSessionImplBase.this.getProperty(name);
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getProperty(name),
+ "getProperty");
}
@Override
public int getState() {
- return ImsCallSessionImplBase.this.getState();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.getState(),
+ "getState");
}
@Override
public boolean isInCall() {
- return ImsCallSessionImplBase.this.isInCall();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isInCall(),
+ "isInCall");
}
@Override
public void setListener(IImsCallSessionListener listener) {
- ImsCallSessionImplBase.this.setListener(new ImsCallSessionListener(listener));
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.setListener(
+ new ImsCallSessionListener(listener)), "setListener");
}
@Override
public void setMute(boolean muted) {
- ImsCallSessionImplBase.this.setMute(muted);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.setMute(muted), "setMute");
}
@Override
public void start(String callee, ImsCallProfile profile) {
- ImsCallSessionImplBase.this.start(callee, profile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.start(callee, profile), "start");
}
@Override
public void startConference(String[] participants, ImsCallProfile profile) throws
RemoteException {
- ImsCallSessionImplBase.this.startConference(participants, profile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.startConference(participants,
+ profile), "startConference");
}
@Override
public void accept(int callType, ImsStreamMediaProfile profile) {
- ImsCallSessionImplBase.this.accept(callType, profile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.accept(callType, profile),
+ "accept");
}
@Override
public void deflect(String deflectNumber) {
- ImsCallSessionImplBase.this.deflect(deflectNumber);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.deflect(deflectNumber),
+ "deflect");
}
@Override
public void reject(int reason) {
- ImsCallSessionImplBase.this.reject(reason);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.reject(reason), "reject");
}
@Override
public void transfer(@NonNull String number, boolean isConfirmationRequired) {
- ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.transfer(number,
+ isConfirmationRequired), "transfer");
}
@Override
public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
- ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
- otherSession.setServiceImpl(transferToSession);
- ImsCallSessionImplBase.this.transfer(otherSession);
+ executeMethodAsync(() -> {
+ ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
+ otherSession.setServiceImpl(transferToSession);
+ ImsCallSessionImplBase.this.transfer(otherSession);
+ }, "consultativeTransfer");
}
@Override
public void terminate(int reason) {
- ImsCallSessionImplBase.this.terminate(reason);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.terminate(reason), "terminate");
}
@Override
public void hold(ImsStreamMediaProfile profile) {
- ImsCallSessionImplBase.this.hold(profile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.hold(profile), "hold");
}
@Override
public void resume(ImsStreamMediaProfile profile) {
- ImsCallSessionImplBase.this.resume(profile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.resume(profile), "resume");
}
@Override
public void merge() {
- ImsCallSessionImplBase.this.merge();
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.merge(), "merge");
}
@Override
public void update(int callType, ImsStreamMediaProfile profile) {
- ImsCallSessionImplBase.this.update(callType, profile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.update(callType, profile),
+ "update");
}
@Override
public void extendToConference(String[] participants) {
- ImsCallSessionImplBase.this.extendToConference(participants);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.extendToConference(participants),
+ "extendToConference");
}
@Override
public void inviteParticipants(String[] participants) {
- ImsCallSessionImplBase.this.inviteParticipants(participants);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.inviteParticipants(participants),
+ "inviteParticipants");
}
@Override
public void removeParticipants(String[] participants) {
- ImsCallSessionImplBase.this.removeParticipants(participants);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.removeParticipants(participants),
+ "removeParticipants");
}
@Override
public void sendDtmf(char c, Message result) {
- ImsCallSessionImplBase.this.sendDtmf(c, result);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.sendDtmf(c, result), "sendDtmf");
}
@Override
public void startDtmf(char c) {
- ImsCallSessionImplBase.this.startDtmf(c);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.startDtmf(c), "startDtmf");
}
@Override
public void stopDtmf() {
- ImsCallSessionImplBase.this.stopDtmf();
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.stopDtmf(), "stopDtmf");
}
@Override
public void sendUssd(String ussdMessage) {
- ImsCallSessionImplBase.this.sendUssd(ussdMessage);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.sendUssd(ussdMessage), "sendUssd");
}
@Override
public IImsVideoCallProvider getVideoCallProvider() {
- return ImsCallSessionImplBase.this.getVideoCallProvider();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this
+ .getVideoCallProvider(), "getVideoCallProvider");
}
@Override
public boolean isMultiparty() {
- return ImsCallSessionImplBase.this.isMultiparty();
+ return executeMethodAsyncForResult(() -> ImsCallSessionImplBase.this.isMultiparty(),
+ "isMultiparty");
}
@Override
public void sendRttModifyRequest(ImsCallProfile toProfile) {
- ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyRequest(toProfile),
+ "sendRttModifyRequest");
}
@Override
public void sendRttModifyResponse(boolean status) {
- ImsCallSessionImplBase.this.sendRttModifyResponse(status);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttModifyResponse(status),
+ "sendRttModifyResponse");
}
@Override
public void sendRttMessage(String rttMessage) {
- ImsCallSessionImplBase.this.sendRttMessage(rttMessage);
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRttMessage(rttMessage),
+ "sendRttMessage");
}
@Override
public void sendRtpHeaderExtensions(@NonNull List<RtpHeaderExtension> extensions) {
- ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
- new ArraySet<RtpHeaderExtension>(extensions));
+ executeMethodAsync(() -> ImsCallSessionImplBase.this.sendRtpHeaderExtensions(
+ new ArraySet<RtpHeaderExtension>(extensions)), "sendRtpHeaderExtensions");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResult(Supplier<T> r,
+ String errorLogName) {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "ImsCallSessionImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ return null;
+ }
}
};
@@ -674,4 +734,14 @@
public void setServiceImpl(IImsCallSession serviceImpl) {
mServiceImpl = serviceImpl;
}
+
+ /**
+ * Set default Executor from MmTelFeature.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of ImsCallSession.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index d75da90..11fc328 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -33,12 +33,21 @@
import com.android.ims.ImsConfig;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.util.RemoteCallbackListExt;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
/**
* Controls the modification of IMS specific configurations. For more information on the supported
@@ -81,21 +90,48 @@
WeakReference<ImsConfigImplBase> mImsConfigImplBaseWeakReference;
private HashMap<Integer, Integer> mProvisionedIntValue = new HashMap<>();
private HashMap<Integer, String> mProvisionedStringValue = new HashMap<>();
+ private final Object mLock = new Object();
+ private Executor mExecutor;
@VisibleForTesting
- public ImsConfigStub(ImsConfigImplBase imsConfigImplBase) {
+ public ImsConfigStub(ImsConfigImplBase imsConfigImplBase, Executor executor) {
+ mExecutor = executor;
mImsConfigImplBaseWeakReference =
new WeakReference<ImsConfigImplBase>(imsConfigImplBase);
}
@Override
public void addImsConfigCallback(IImsConfigCallback c) throws RemoteException {
- getImsConfigImpl().addImsConfigCallback(c);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().addImsConfigCallback(c);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "addImsConfigCallback");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception addImsConfigCallback");
+ throw exceptionRef.get();
+ }
}
@Override
public void removeImsConfigCallback(IImsConfigCallback c) throws RemoteException {
- getImsConfigImpl().removeImsConfigCallback(c);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().removeImsConfigCallback(c);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "removeImsConfigCallback");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception removeImsConfigCallback");
+ throw exceptionRef.get();
+ }
}
/**
@@ -108,16 +144,34 @@
* unavailable.
*/
@Override
- public synchronized int getConfigInt(int item) throws RemoteException {
- if (mProvisionedIntValue.containsKey(item)) {
- return mProvisionedIntValue.get(item);
- } else {
- int retVal = getImsConfigImpl().getConfigInt(item);
- if (retVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
- updateCachedValue(item, retVal, false);
+ public int getConfigInt(int item) throws RemoteException {
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ int retVal = executeMethodAsyncForResult(()-> {
+ int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+ synchronized (mLock) {
+ if (mProvisionedIntValue.containsKey(item)) {
+ return mProvisionedIntValue.get(item);
+ } else {
+ try {
+ returnVal = getImsConfigImpl().getConfigInt(item);
+ if (returnVal != ImsConfig.OperationStatusConstants.UNKNOWN) {
+ mProvisionedIntValue.put(item, returnVal);
+ }
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return returnVal;
+ }
+ }
}
- return retVal;
+ return returnVal;
+ }, "getConfigInt");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
+ throw exceptionRef.get();
}
+
+ return retVal;
}
/**
@@ -129,16 +183,34 @@
* @return value in String format.
*/
@Override
- public synchronized String getConfigString(int item) throws RemoteException {
- if (mProvisionedStringValue.containsKey(item)) {
- return mProvisionedStringValue.get(item);
- } else {
- String retVal = getImsConfigImpl().getConfigString(item);
- if (retVal != null) {
- updateCachedValue(item, retVal, false);
+ public String getConfigString(int item) throws RemoteException {
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ String retVal = executeMethodAsyncForResult(()-> {
+ String returnVal = null;
+ synchronized (mLock) {
+ if (mProvisionedStringValue.containsKey(item)) {
+ returnVal = mProvisionedStringValue.get(item);
+ } else {
+ try {
+ returnVal = getImsConfigImpl().getConfigString(item);
+ if (returnVal != null) {
+ mProvisionedStringValue.put(item, returnVal);
+ }
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return returnVal;
+ }
+ }
}
- return retVal;
+ return returnVal;
+ }, "getConfigString");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception getConfigString");
+ throw exceptionRef.get();
}
+
+ return retVal;
}
/**
@@ -153,14 +225,32 @@
* {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
*/
@Override
- public synchronized int setConfigInt(int item, int value) throws RemoteException {
- mProvisionedIntValue.remove(item);
- int retVal = getImsConfigImpl().setConfig(item, value);
- if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
- updateCachedValue(item, value, true);
- } else {
- Log.d(TAG, "Set provision value of " + item +
- " to " + value + " failed with error code " + retVal);
+ public int setConfigInt(int item, int value) throws RemoteException {
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ int retVal = executeMethodAsyncForResult(()-> {
+ int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+ try {
+ synchronized (mLock) {
+ mProvisionedIntValue.remove(item);
+ returnVal = getImsConfigImpl().setConfig(item, value);
+ if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+ mProvisionedIntValue.put(item, value);
+ } else {
+ Log.d(TAG, "Set provision value of " + item
+ + " to " + value + " failed with error code " + returnVal);
+ }
+ }
+ notifyImsConfigChanged(item, value);
+ return returnVal;
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return returnVal;
+ }
+ }, "setConfigInt");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
+ throw exceptionRef.get();
}
return retVal;
@@ -178,12 +268,30 @@
* {@link #CONFIG_RESULT_FAILED} or {@link #CONFIG_RESULT_SUCCESS}.
*/
@Override
- public synchronized int setConfigString(int item, String value)
+ public int setConfigString(int item, String value)
throws RemoteException {
- mProvisionedStringValue.remove(item);
- int retVal = getImsConfigImpl().setConfig(item, value);
- if (retVal == ImsConfig.OperationStatusConstants.SUCCESS) {
- updateCachedValue(item, value, true);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ int retVal = executeMethodAsyncForResult(()-> {
+ int returnVal = ImsConfig.OperationStatusConstants.UNKNOWN;
+ try {
+ synchronized (mLock) {
+ mProvisionedStringValue.remove(item);
+ returnVal = getImsConfigImpl().setConfig(item, value);
+ if (returnVal == ImsConfig.OperationStatusConstants.SUCCESS) {
+ mProvisionedStringValue.put(item, value);
+ }
+ }
+ notifyImsConfigChanged(item, value);
+ return returnVal;
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ return returnVal;
+ }
+ }, "setConfigString");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception setConfigInt");
+ throw exceptionRef.get();
}
return retVal;
@@ -191,7 +299,19 @@
@Override
public void updateImsCarrierConfigs(PersistableBundle bundle) throws RemoteException {
- getImsConfigImpl().updateImsCarrierConfigs(bundle);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().updateImsCarrierConfigs(bundle);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "updateImsCarrierConfigs");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception updateImsCarrierConfigs");
+ throw exceptionRef.get();
+ }
}
private ImsConfigImplBase getImsConfigImpl() throws RemoteException {
@@ -206,13 +326,37 @@
@Override
public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
throws RemoteException {
- getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "notifyRcsAutoConfigurationReceived");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationReceived");
+ throw exceptionRef.get();
+ }
}
@Override
public void notifyRcsAutoConfigurationRemoved()
throws RemoteException {
- getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "notifyRcsAutoConfigurationRemoved");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception notifyRcsAutoConfigurationRemoved");
+ throw exceptionRef.get();
+ }
}
private void notifyImsConfigChanged(int item, int value) throws RemoteException {
@@ -223,50 +367,144 @@
getImsConfigImpl().notifyConfigChanged(item, value);
}
- protected synchronized void updateCachedValue(int item, int value, boolean notifyChange)
- throws RemoteException {
- mProvisionedIntValue.put(item, value);
- if (notifyChange) {
- notifyImsConfigChanged(item, value);
+ protected void updateCachedValue(int item, int value) {
+ synchronized (mLock) {
+ mProvisionedIntValue.put(item, value);
}
}
- protected synchronized void updateCachedValue(int item, String value,
- boolean notifyChange) throws RemoteException {
- mProvisionedStringValue.put(item, value);
- if (notifyChange) {
- notifyImsConfigChanged(item, value);
+ protected void updateCachedValue(int item, String value) {
+ synchronized (mLock) {
+ mProvisionedStringValue.put(item, value);
}
}
@Override
public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
- getImsConfigImpl().addRcsConfigCallback(c);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().addRcsConfigCallback(c);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "addRcsConfigCallback");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception addRcsConfigCallback");
+ throw exceptionRef.get();
+ }
}
@Override
public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
- getImsConfigImpl().removeRcsConfigCallback(c);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().removeRcsConfigCallback(c);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "removeRcsConfigCallback");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception removeRcsConfigCallback");
+ throw exceptionRef.get();
+ }
}
@Override
public void triggerRcsReconfiguration() throws RemoteException {
- getImsConfigImpl().triggerAutoConfiguration();
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().triggerAutoConfiguration();
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "triggerRcsReconfiguration");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception triggerRcsReconfiguration");
+ throw exceptionRef.get();
+ }
}
@Override
public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
- getImsConfigImpl().setRcsClientConfiguration(rcc);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ getImsConfigImpl().setRcsClientConfiguration(rcc);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "setRcsClientConfiguration");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception setRcsClientConfiguration");
+ throw exceptionRef.get();
+ }
}
@Override
public void notifyIntImsConfigChanged(int item, int value) throws RemoteException {
- notifyImsConfigChanged(item, value);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ notifyImsConfigChanged(item, value);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "notifyIntImsConfigChanged");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception notifyIntImsConfigChanged");
+ throw exceptionRef.get();
+ }
}
@Override
public void notifyStringImsConfigChanged(int item, String value) throws RemoteException {
- notifyImsConfigChanged(item, value);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(()-> {
+ try {
+ notifyImsConfigChanged(item, value);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "notifyStringImsConfigChanged");
+
+ if (exceptionRef.get() != null) {
+ Log.d(TAG, "ImsConfigImplBase Exception notifyStringImsConfigChanged");
+ throw exceptionRef.get();
+ }
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResult(Supplier<T> r,
+ String errorLogName) throws RemoteException {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(TAG, "ImsConfigImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
}
}
@@ -303,15 +541,24 @@
ImsConfigStub mImsConfigStub;
/**
- * Used for compatibility between older versions of the ImsService.
+ * Create a ImsConfig using the Executor specified for methods being called by the
+ * framework.
+ * @param executor The executor for the framework to use when executing the methods overridden
+ * by the implementation of ImsConfig.
+ */
+ public ImsConfigImplBase(@NonNull Executor executor) {
+ mImsConfigStub = new ImsConfigStub(this, executor);
+ }
+
+ /**
* @hide
*/
- public ImsConfigImplBase(Context context) {
- mImsConfigStub = new ImsConfigStub(this);
+ public ImsConfigImplBase(@NonNull Context context) {
+ mImsConfigStub = new ImsConfigStub(this, null);
}
public ImsConfigImplBase() {
- mImsConfigStub = new ImsConfigStub(this);
+ mImsConfigStub = new ImsConfigStub(this, null);
}
/**
@@ -427,8 +674,10 @@
* @param value in Integer format.
*/
public final void notifyProvisionedValueChanged(int item, int value) {
+ mImsConfigStub.updateCachedValue(item, value);
+
try {
- mImsConfigStub.updateCachedValue(item, value, true);
+ mImsConfigStub.notifyImsConfigChanged(item, value);
} catch (RemoteException e) {
Log.w(TAG, "notifyProvisionedValueChanged(int): Framework connection is dead.");
}
@@ -443,8 +692,10 @@
* @param value in String format.
*/
public final void notifyProvisionedValueChanged(int item, String value) {
+ mImsConfigStub.updateCachedValue(item, value);
+
try {
- mImsConfigStub.updateCachedValue(item, value, true);
+ mImsConfigStub.notifyImsConfigChanged(item, value);
} catch (RemoteException e) {
Log.w(TAG, "notifyProvisionedValueChanged(string): Framework connection is dead.");
}
@@ -582,4 +833,16 @@
}
});
}
+
+ /**
+ * Set default Executor from ImsService.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of ImsConfig.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ if (mImsConfigStub.mExecutor == null) {
+ mImsConfigStub.mExecutor = executor;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 8ad40ed..84b2253 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -16,14 +16,21 @@
package android.telephony.ims.stub;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.RemoteException;
import android.util.Log;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsEcbmListener;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
+
/**
* Base implementation of ImsEcbm, which implements stub versions of the methods
@@ -40,10 +47,12 @@
private final Object mLock = new Object();
private IImsEcbmListener mListener;
+ private Executor mExecutor = Runnable::run;
+
private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
@Override
public void setListener(IImsEcbmListener listener) {
- synchronized (mLock) {
+ executeMethodAsync(() -> {
if (mListener != null && !mListener.asBinder().isBinderAlive()) {
Log.w(TAG, "setListener: discarding dead Binder");
mListener = null;
@@ -62,12 +71,25 @@
+ "listener");
mListener = listener;
}
- }
+ }, "setListener");
}
@Override
public void exitEmergencyCallbackMode() {
- ImsEcbmImplBase.this.exitEmergencyCallbackMode();
+ executeMethodAsync(() -> ImsEcbmImplBase.this.exitEmergencyCallbackMode(),
+ "exitEmergencyCallbackMode");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(TAG, "ImsEcbmImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ }
}
};
@@ -123,4 +145,14 @@
}
}
}
+
+ /**
+ * Set default Executor from MmTelFeature.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of ImsEcbm.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index ec1c7b3..a723cd8b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -16,6 +16,7 @@
package android.telephony.ims.stub;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.RemoteException;
import android.telephony.ims.ImsExternalCallState;
@@ -23,9 +24,14 @@
import com.android.ims.internal.IImsExternalCallStateListener;
import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
/**
* Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
@@ -43,11 +49,13 @@
private IImsExternalCallStateListener mListener;
private final Object mLock = new Object();
+ private Executor mExecutor = Runnable::run;
+
private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
@Override
public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
- synchronized (mLock) {
+ executeMethodAsync(() -> {
if (mListener != null && !mListener.asBinder().isBinderAlive()) {
Log.w(TAG, "setListener: discarding dead Binder");
mListener = null;
@@ -67,12 +75,25 @@
+ "listener");
mListener = listener;
}
- }
+ }, "setListener");
}
@Override
public void requestImsExternalCallStateInfo() throws RemoteException {
- ImsMultiEndpointImplBase.this.requestImsExternalCallStateInfo();
+ executeMethodAsync(() -> ImsMultiEndpointImplBase.this
+ .requestImsExternalCallStateInfo(), "requestImsExternalCallStateInfo");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(TAG, "ImsMultiEndpointImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ }
}
};
@@ -108,4 +129,14 @@
public void requestImsExternalCallStateInfo() {
Log.d(TAG, "requestImsExternalCallStateInfo() not implemented");
}
+
+ /**
+ * Set default Executor from MmTelFeature.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of ImsMultiEndpoint.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 02bcdec..ac5565b 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -31,10 +31,18 @@
import android.util.Log;
import com.android.internal.telephony.util.RemoteCallbackListExt;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.ArrayUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
/**
* Controls IMS registration for this ImsService and notifies the framework when the IMS
@@ -42,9 +50,7 @@
* <p>
* Note: There is no guarantee on the thread that the calls from the framework will be called on. It
* is the implementors responsibility to handle moving the calls to a working thread if required.
- * @hide
*/
-@SystemApi
public class ImsRegistrationImplBase {
private static final String LOG_TAG = "ImsRegistrationImplBase";
@@ -85,6 +91,12 @@
*/
public static final int REGISTRATION_TECH_NR = 3;
+ /**
+ * This is used to check the upper range of registration tech
+ * {@hide}
+ */
+ public static final int REGISTRATION_TECH_MAX = REGISTRATION_TECH_NR + 1;
+
// Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current
// state.
// The unknown state is set as the initialization state. This is so that we do not call back
@@ -92,39 +104,118 @@
// yet.
private static final int REGISTRATION_STATE_UNKNOWN = -1;
+ private Executor mExecutor;
+
+ /**
+ * Create a new ImsRegistration.
+ * <p>
+ * Method stubs called from the framework will be called asynchronously. To specify the
+ * {@link Executor} that the methods stubs will be called, use
+ * {@link ImsRegistrationImplBase#ImsRegistrationImplBase(Executor)} instead.
+ * @hide This API is not part of the Android public SDK API
+ */
+ @SystemApi
+ public ImsRegistrationImplBase() {
+ super();
+ }
+
+ /**
+ * Create a ImsRegistration using the Executor specified for methods being called by the
+ * framework.
+ * @param executor The executor for the framework to use when executing the methods overridden
+ * by the implementation of ImsRegistration.
+ * @hide This API is not part of the Android public SDK API
+ */
+ @SystemApi
+ public ImsRegistrationImplBase(@NonNull Executor executor) {
+ super();
+ mExecutor = executor;
+ }
+
private final IImsRegistration mBinder = new IImsRegistration.Stub() {
@Override
public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
- synchronized (mLock) {
- return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE
- : mRegistrationAttributes.getRegistrationTechnology();
- }
+ return executeMethodAsyncForResult(() -> (mRegistrationAttributes == null)
+ ? REGISTRATION_TECH_NONE : mRegistrationAttributes.getRegistrationTechnology(),
+ "getRegistrationTechnology");
}
@Override
public void addRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
- ImsRegistrationImplBase.this.addRegistrationCallback(c);
+ AtomicReference<RemoteException> exceptionRef = new AtomicReference<>();
+ executeMethodAsync(() -> {
+ try {
+ ImsRegistrationImplBase.this.addRegistrationCallback(c);
+ } catch (RemoteException e) {
+ exceptionRef.set(e);
+ }
+ }, "addRegistrationCallback");
+
+ if (exceptionRef.get() != null) {
+ throw exceptionRef.get();
+ }
}
@Override
public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
- ImsRegistrationImplBase.this.removeRegistrationCallback(c);
+ executeMethodAsync(() -> ImsRegistrationImplBase.this.removeRegistrationCallback(c),
+ "removeRegistrationCallback");
}
@Override
public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
- ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason);
+ executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+ .triggerFullNetworkRegistration(sipCode, sipReason),
+ "triggerFullNetworkRegistration");
}
@Override
public void triggerUpdateSipDelegateRegistration() {
- ImsRegistrationImplBase.this.updateSipDelegateRegistration();
+ executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+ .updateSipDelegateRegistration(), "triggerUpdateSipDelegateRegistration");
}
@Override
public void triggerSipDelegateDeregistration() {
- ImsRegistrationImplBase.this.triggerSipDelegateDeregistration();
+ executeMethodAsyncNoException(() -> ImsRegistrationImplBase.this
+ .triggerSipDelegateDeregistration(), "triggerSipDelegateDeregistration");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private void executeMethodAsyncNoException(Runnable r, String errorLogName) {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResult(Supplier<T> r,
+ String errorLogName) throws RemoteException {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(LOG_TAG, "ImsRegistrationImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
}
};
@@ -166,7 +257,9 @@
* If the SIP delegate feature tag configuration has changed, then this method will be
* called in order to let the ImsService know that it can pick up these changes in the IMS
* registration.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public void updateSipDelegateRegistration() {
// Stub implementation, ImsService should implement this
}
@@ -182,7 +275,9 @@
* <p>
* This should not affect the registration of features managed by the ImsService itself, such as
* feature tags related to MMTEL registration.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public void triggerSipDelegateDeregistration() {
// Stub implementation, ImsService should implement this
}
@@ -200,7 +295,9 @@
* be carrier specific.
* @param sipReason The reason associated with the SIP error code. {@code null} if there was no
* reason associated with the error.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public void triggerFullNetworkRegistration(@IntRange(from = 100, to = 699) int sipCode,
@Nullable String sipReason) {
// Stub implementation, ImsService should implement this
@@ -211,7 +308,9 @@
* Notify the framework that the device is connected to the IMS network.
*
* @param imsRadioTech the radio access technology.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
onRegistered(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
}
@@ -220,7 +319,9 @@
* Notify the framework that the device is connected to the IMS network.
*
* @param attributes The attributes associated with the IMS registration.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERED);
mCallbacks.broadcastAction((c) -> {
@@ -236,7 +337,9 @@
* Notify the framework that the device is trying to connect the IMS network.
*
* @param imsRadioTech the radio access technology.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
onRegistering(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
}
@@ -245,7 +348,9 @@
* Notify the framework that the device is trying to connect the IMS network.
*
* @param attributes The attributes associated with the IMS registration.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onRegistering(@NonNull ImsRegistrationAttributes attributes) {
updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERING);
mCallbacks.broadcastAction((c) -> {
@@ -272,7 +377,9 @@
* result.
*
* @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onDeregistered(ImsReasonInfo info) {
updateToDisconnectedState(info);
// ImsReasonInfo should never be null.
@@ -293,7 +400,9 @@
* {@link #REGISTRATION_TECH_LTE}, {@link #REGISTRATION_TECH_IWLAN} and
* {@link #REGISTRATION_TECH_CROSS_SIM}.
* @param info The {@link ImsReasonInfo} for the failure to change technology.
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onTechnologyChangeFailed(@ImsRegistrationTech int imsRadioTech,
ImsReasonInfo info) {
final ImsReasonInfo reasonInfo = (info != null) ? info : new ImsReasonInfo();
@@ -312,7 +421,9 @@
*
* The {@link Uri}s are not guaranteed to be different between subsequent calls.
* @param uris changed uris
+ * @hide This API is not part of the Android public SDK API
*/
+ @SystemApi
public final void onSubscriberAssociatedUriChanged(Uri[] uris) {
synchronized (mLock) {
mUris = ArrayUtils.cloneOrNull(uris);
@@ -394,4 +505,16 @@
onSubscriberAssociatedUriChanged(c, uris);
}
}
+
+ /**
+ * Set default Executor from ImsService.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of Registration.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ if (mExecutor == null) {
+ mExecutor = executor;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index eb3e8ed..11cdeed 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -27,10 +27,17 @@
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
/**
* Base implementation of IMS UT interface, which implements stubs. Override these methods to
@@ -119,96 +126,108 @@
*/
public static final int INVALID_RESULT = -1;
+ private Executor mExecutor = Runnable::run;
+
private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
private final Object mLock = new Object();
private ImsUtListener mUtListener;
@Override
public void close() throws RemoteException {
- ImsUtImplBase.this.close();
+ executeMethodAsync(() ->ImsUtImplBase.this.close(), "close");
}
@Override
public int queryCallBarring(int cbType) throws RemoteException {
- return ImsUtImplBase.this.queryCallBarring(cbType);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallBarring(cbType),
+ "queryCallBarring");
}
@Override
public int queryCallForward(int condition, String number) throws RemoteException {
- return ImsUtImplBase.this.queryCallForward(condition, number);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallForward(
+ condition, number), "queryCallForward");
}
@Override
public int queryCallWaiting() throws RemoteException {
- return ImsUtImplBase.this.queryCallWaiting();
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCallWaiting(),
+ "queryCallWaiting");
}
@Override
public int queryCLIR() throws RemoteException {
- return ImsUtImplBase.this.queryCLIR();
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIR(), "queryCLIR");
}
@Override
public int queryCLIP() throws RemoteException {
- return ImsUtImplBase.this.queryCLIP();
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCLIP(), "queryCLIP");
}
@Override
public int queryCOLR() throws RemoteException {
- return ImsUtImplBase.this.queryCOLR();
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLR(), "queryCOLR");
}
@Override
public int queryCOLP() throws RemoteException {
- return ImsUtImplBase.this.queryCOLP();
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.queryCOLP(), "queryCOLP");
}
@Override
public int transact(Bundle ssInfo) throws RemoteException {
- return ImsUtImplBase.this.transact(ssInfo);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.transact(ssInfo),
+ "transact");
}
@Override
public int updateCallBarring(int cbType, int action, String[] barrList) throws
RemoteException {
- return ImsUtImplBase.this.updateCallBarring(cbType, action, barrList);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallBarring(
+ cbType, action, barrList), "updateCallBarring");
}
@Override
public int updateCallForward(int action, int condition, String number, int serviceClass,
int timeSeconds) throws RemoteException {
- return ImsUtImplBase.this.updateCallForward(action, condition, number, serviceClass,
- timeSeconds);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallForward(
+ action, condition, number, serviceClass, timeSeconds), "updateCallForward");
}
@Override
public int updateCallWaiting(boolean enable, int serviceClass) throws RemoteException {
- return ImsUtImplBase.this.updateCallWaiting(enable, serviceClass);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCallWaiting(
+ enable, serviceClass), "updateCallWaiting");
}
@Override
public int updateCLIR(int clirMode) throws RemoteException {
- return ImsUtImplBase.this.updateCLIR(clirMode);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIR(clirMode),
+ "updateCLIR");
}
@Override
public int updateCLIP(boolean enable) throws RemoteException {
- return ImsUtImplBase.this.updateCLIP(enable);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCLIP(enable),
+ "updateCLIP");
}
@Override
public int updateCOLR(int presentation) throws RemoteException {
- return ImsUtImplBase.this.updateCOLR(presentation);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLR(presentation),
+ "updateCOLR");
}
@Override
public int updateCOLP(boolean enable) throws RemoteException {
- return ImsUtImplBase.this.updateCOLP(enable);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this.updateCOLP(enable),
+ "updateCOLP");
}
@Override
public void setListener(IImsUtListener listener) throws RemoteException {
- synchronized (mLock) {
+ executeMethodAsync(() -> {
if (mUtListener != null
&& !mUtListener.getListenerInterface().asBinder().isBinderAlive()) {
Log.w(TAG, "setListener: discarding dead Binder");
@@ -229,29 +248,59 @@
+ "listener");
mUtListener = new ImsUtListener(listener);
}
- }
- ImsUtImplBase.this.setListener(mUtListener);
+ ImsUtImplBase.this.setListener(mUtListener);
+ }, "setListener");
}
@Override
public int queryCallBarringForServiceClass(int cbType, int serviceClass)
throws RemoteException {
- return ImsUtImplBase.this.queryCallBarringForServiceClass(cbType, serviceClass);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+ .queryCallBarringForServiceClass(cbType, serviceClass),
+ "queryCallBarringForServiceClass");
}
@Override
public int updateCallBarringForServiceClass(int cbType, int action,
String[] barrList, int serviceClass) throws RemoteException {
- return ImsUtImplBase.this.updateCallBarringForServiceClass(
- cbType, action, barrList, serviceClass);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+ .updateCallBarringForServiceClass(cbType, action, barrList, serviceClass),
+ "updateCallBarringForServiceClass");
}
@Override
public int updateCallBarringWithPassword(int cbType, int action, String[] barrList,
int serviceClass, String password) throws RemoteException {
- return ImsUtImplBase.this.updateCallBarringWithPassword(
- cbType, action, barrList, serviceClass, password);
+ return executeMethodAsyncForResult(() -> ImsUtImplBase.this
+ .updateCallBarringWithPassword(cbType, action, barrList, serviceClass,
+ password), "updateCallBarringWithPassword");
+ }
+
+ // Call the methods with a clean calling identity on the executor and wait indefinitely for
+ // the future to return.
+ private void executeMethodAsync(Runnable r, String errorLogName) throws RemoteException {
+ try {
+ CompletableFuture.runAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor).join();
+ } catch (CancellationException | CompletionException e) {
+ Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
+ }
+
+ private <T> T executeMethodAsyncForResult(Supplier<T> r,
+ String errorLogName) throws RemoteException {
+ CompletableFuture<T> future = CompletableFuture.supplyAsync(
+ () -> TelephonyUtils.runWithCleanCallingIdentity(r), mExecutor);
+ try {
+ return future.get();
+ } catch (ExecutionException | InterruptedException e) {
+ Log.w(TAG, "ImsUtImplBase Binder - " + errorLogName + " exception: "
+ + e.getMessage());
+ throw new RemoteException(e.getMessage());
+ }
}
};
@@ -470,4 +519,14 @@
public IImsUt getInterface() {
return mServiceImpl;
}
+
+ /**
+ * Set default Executor from MmTelFeature.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of ImsUT.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
index 13ea9973..52538cb 100644
--- a/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/SipTransportImplBase.java
@@ -86,10 +86,21 @@
}
};
- private final Executor mBinderExecutor;
+ private Executor mBinderExecutor;
private final ArrayList<SipDelegateAidlWrapper> mDelegates = new ArrayList<>();
/**
+ * Create a new SipTransport.
+ * <p>
+ * Method stubs called from the framework will be called asynchronously. To specify the
+ * {@link Executor} that the methods stubs will be called, use
+ * {@link SipTransportImplBase#SipTransportImplBase(Executor)} instead.
+ */
+ public SipTransportImplBase() {
+ super();
+ }
+
+ /**
* Create an implementation of SipTransportImplBase.
*
* @param executor The executor that remote calls from the framework will be called on. This
@@ -212,4 +223,16 @@
public ISipTransport getBinder() {
return mSipTransportImpl;
}
+
+ /**
+ * Set default Executor from ImsService.
+ * @param executor The default executor for the framework to use when executing the methods
+ * overridden by the implementation of SipTransport.
+ * @hide
+ */
+ public final void setDefaultExecutor(@NonNull Executor executor) {
+ if (mBinderExecutor == null) {
+ mBinderExecutor = executor;
+ }
+ }
}
diff --git a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
index f5f67bd..416096b 100644
--- a/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
+++ b/telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl
@@ -23,11 +23,11 @@
* {@hide}
*/
oneway interface IImsServiceFeatureCallback {
- void imsFeatureCreated(in ImsFeatureContainer feature);
+ void imsFeatureCreated(in ImsFeatureContainer feature, int subId);
// Reason defined in FeatureConnector.UnavailableReason
void imsFeatureRemoved(int reason);
// Status defined in ImsFeature.ImsState.
- void imsStatusChanged(int status);
+ void imsStatusChanged(int status, int subId);
//Capabilities defined in ImsService.ImsServiceCapability
void updateCapabilities(long capabilities);
}
\ No newline at end of file
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 409c838cb..2470887 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -114,6 +114,7 @@
public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 54;
public static final int EVENT_SIM_STATE_UPDATED = BASE + 55;
public static final int EVENT_APN_UNTHROTTLED = BASE + 56;
+ public static final int EVENT_TRAFFIC_DESCRIPTORS_UPDATED = BASE + 57;
/***** Constants *****/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 167aa07f..0ac7cf9 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -55,6 +55,7 @@
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.RcsClientConfiguration;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.aidl.IFeatureProvisioningCallback;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
@@ -2027,6 +2028,18 @@
void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback);
/**
+ * Register an IMS provisioning change callback with Telephony.
+ */
+ void registerFeatureProvisioningChangedCallback(int subId,
+ IFeatureProvisioningCallback callback);
+
+ /**
+ * unregister an existing IMS provisioning change callback.
+ */
+ void unregisterFeatureProvisioningChangedCallback(int subId,
+ IFeatureProvisioningCallback callback);
+
+ /**
* Set the provisioning status for the IMS MmTel capability using the specified subscription.
*/
void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
@@ -2040,19 +2053,12 @@
/**
* Get the provisioning status for the IMS Rcs capability specified.
*/
- boolean getRcsProvisioningStatusForCapability(int subId, int capability);
+ boolean getRcsProvisioningStatusForCapability(int subId, int capability, int tech);
/**
* Set the provisioning status for the IMS Rcs capability using the specified subscription.
*/
- void setRcsProvisioningStatusForCapability(int subId, int capability,
- boolean isProvisioned);
-
- /** Is the capability and tech flagged as provisioned in the cache */
- boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech);
-
- /** Set the provisioning for the capability and tech in the cache */
- void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech,
+ void setRcsProvisioningStatusForCapability(int subId, int capability, int tech,
boolean isProvisioned);
/**
@@ -2555,4 +2561,18 @@
* @return the service name of the modem service which bind to.
*/
String getModemService();
+
+ /**
+ * Is Provisioning required for capability
+ * @return true if provisioning is required for the MMTEL capability and IMS
+ * registration technology specified, false if it is not required.
+ */
+ boolean isProvisioningRequiredForCapability(int subId, int capability, int tech);
+
+ /**
+ * Is RCS Provisioning required for capability
+ * @return true if provisioning is required for the RCS capability and IMS
+ * registration technology specified, false if it is not required.
+ */
+ boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech);
}
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
index 4ec86b186..56848b8 100644
--- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -15,20 +15,19 @@
*/
package com.android.tests.dataidle;
+import static android.net.NetworkStats.METERED_YES;
+
+import android.app.usage.NetworkStats;
+import android.app.usage.NetworkStatsManager;
import android.content.Context;
-import android.net.INetworkStatsService;
-import android.net.INetworkStatsSession;
-import android.net.NetworkStats;
-import android.net.NetworkStats.Entry;
import android.net.NetworkTemplate;
-import android.net.TrafficStats;
import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.telephony.TelephonyManager;
import android.test.InstrumentationTestCase;
import android.util.Log;
+import java.util.Set;
+
/**
* A test that dumps data usage to instrumentation out, used for measuring data usage for idle
* devices.
@@ -36,7 +35,7 @@
public class DataIdleTest extends InstrumentationTestCase {
private TelephonyManager mTelephonyManager;
- private INetworkStatsService mStatsService;
+ private NetworkStatsManager mStatsManager;
private static final String LOG_TAG = "DataIdleTest";
private final static int INSTRUMENTATION_IN_PROGRESS = 2;
@@ -44,8 +43,7 @@
protected void setUp() throws Exception {
super.setUp();
Context c = getInstrumentation().getTargetContext();
- mStatsService = INetworkStatsService.Stub.asInterface(
- ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ mStatsManager = c.getSystemService(NetworkStatsManager.class);
mTelephonyManager = (TelephonyManager) c.getSystemService(Context.TELEPHONY_SERVICE);
}
@@ -53,7 +51,9 @@
* Test that dumps all the data usage metrics for wifi to instrumentation out.
*/
public void testWifiIdle() {
- NetworkTemplate template = NetworkTemplate.buildTemplateWifiWildcard();
+ final NetworkTemplate template = new NetworkTemplate
+ .Builder(NetworkTemplate.MATCH_WIFI)
+ .build();
fetchStats(template);
}
@@ -61,8 +61,11 @@
* Test that dumps all the data usage metrics for all mobile to instrumentation out.
*/
public void testMobile() {
- String subscriberId = mTelephonyManager.getSubscriberId();
- NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
+ final String subscriberId = mTelephonyManager.getSubscriberId();
+ NetworkTemplate template = new NetworkTemplate
+ .Builder(NetworkTemplate.MATCH_MOBILE)
+ .setMeteredness(METERED_YES)
+ .setSubscriberIds(Set.of(subscriberId)).build();
fetchStats(template);
}
@@ -72,49 +75,26 @@
* @param template {@link NetworkTemplate} to match.
*/
private void fetchStats(NetworkTemplate template) {
- INetworkStatsSession session = null;
try {
- mStatsService.forceUpdate();
- session = mStatsService.openSession();
- final NetworkStats stats = session.getSummaryForAllUid(
- template, Long.MIN_VALUE, Long.MAX_VALUE, false);
- reportStats(stats);
- } catch (RemoteException e) {
+ mStatsManager.forceUpdate();
+ final NetworkStats.Bucket bucket =
+ mStatsManager.querySummaryForDevice(template, Long.MIN_VALUE, Long.MAX_VALUE);
+ reportStats(bucket);
+ } catch (RuntimeException e) {
Log.w(LOG_TAG, "Failed to fetch network stats.");
- } finally {
- TrafficStats.closeQuietly(session);
}
}
/**
* Print network data usage stats to instrumentation out
- * @param stats {@link NetworkorStats} to print
+ * @param bucket {@link NetworkStats} to print
*/
- void reportStats(NetworkStats stats) {
+ void reportStats(NetworkStats.Bucket bucket) {
Bundle result = new Bundle();
- long rxBytes = 0;
- long txBytes = 0;
- long rxPackets = 0;
- long txPackets = 0;
- for (int i = 0; i < stats.size(); ++i) {
- // Label will be iface_uid_tag_set
- Entry statsEntry = stats.getValues(i, null);
- // Debugging use.
- /*
- String labelTemplate = String.format("%s_%d_%d_%d", statsEntry.iface, statsEntry.uid,
- statsEntry.tag, statsEntry.set) + "_%s";
- result.putLong(String.format(labelTemplate, "rxBytes"), statsEntry.rxBytes);
- result.putLong(String.format(labelTemplate, "txBytes"), statsEntry.txBytes);
- */
- rxPackets += statsEntry.rxPackets;
- rxBytes += statsEntry.rxBytes;
- txPackets += statsEntry.txPackets;
- txBytes += statsEntry.txBytes;
- }
- result.putLong("Total rx Bytes", rxBytes);
- result.putLong("Total tx Bytes", txBytes);
- result.putLong("Total rx Packets", rxPackets);
- result.putLong("Total tx Packets", txPackets);
+ result.putLong("Total rx Bytes", bucket.getRxBytes());
+ result.putLong("Total tx Bytes", bucket.getTxBytes());
+ result.putLong("Total rx Packets", bucket.getRxPackets());
+ result.putLong("Total tx Packets", bucket.getTxPackets());
getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, result);
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/close/OWNERS
new file mode 100644
index 0000000..f7c0a87
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/OWNERS
@@ -0,0 +1,2 @@
+# window manager > animations/transitions
+# Bug component: 316275
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OWNERS
new file mode 100644
index 0000000..301fafa
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OWNERS
@@ -0,0 +1,2 @@
+# ime
+# Bug component: 34867
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OWNERS
new file mode 100644
index 0000000..2c414a2
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OWNERS
@@ -0,0 +1,4 @@
+# System UI > ... > Overview (recent apps) > UI
+# Bug template url: https://b.corp.google.com/issues/new?component=807991&template=1390280 = per-file *Overview*
+# window manager > animations/transitions
+# Bug template url: https://b.corp.google.com/issues/new?component=316275&template=1018192
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/OWNERS
new file mode 100644
index 0000000..897fe5d
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/OWNERS
@@ -0,0 +1,2 @@
+# System UI > ... > Launcher > Gesture nav
+# Bug component: 565144
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/OWNERS b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/OWNERS
new file mode 100644
index 0000000..f7c0a87
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/OWNERS
@@ -0,0 +1,2 @@
+# window manager > animations/transitions
+# Bug component: 316275
diff --git a/tests/SilkFX/AndroidManifest.xml b/tests/SilkFX/AndroidManifest.xml
index c30d761..21256d8 100644
--- a/tests/SilkFX/AndroidManifest.xml
+++ b/tests/SilkFX/AndroidManifest.xml
@@ -20,17 +20,20 @@
<uses-sdk android:minSdkVersion="30"/>
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application android:label="SilkFX"
android:theme="@android:style/Theme.Material">
<activity android:name=".Main"
android:label="SilkFX Demos"
+ android:banner="@drawable/background1"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
@@ -41,13 +44,16 @@
<activity android:name=".materials.GlassActivity"
android:label="Glass Examples"
- android:banner="@drawable/background1"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name=".materials.BackgroundBlurActivity"
+ android:theme="@style/Theme.BackgroundBlurTheme"
+ android:exported="true">
+ </activity>
+
</application>
</manifest>
diff --git a/tests/SilkFX/res/drawable/background_blur_drawable.xml b/tests/SilkFX/res/drawable/background_blur_drawable.xml
new file mode 100644
index 0000000..173ca99
--- /dev/null
+++ b/tests/SilkFX/res/drawable/background_blur_drawable.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="#20FFFFFF"/>
+ <corners android:radius="10dp"/>
+</shape>
diff --git a/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml b/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml
new file mode 100644
index 0000000..bd8942d
--- /dev/null
+++ b/tests/SilkFX/res/drawable/blur_activity_background_drawable_white.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="10dp"/>
+</shape>
diff --git a/tests/SilkFX/res/layout/activity_background_blur.xml b/tests/SilkFX/res/layout/activity_background_blur.xml
new file mode 100644
index 0000000..f13c088
--- /dev/null
+++ b/tests/SilkFX/res/layout/activity_background_blur.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/background"
+ android:layout_width="390dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:padding="15dp"
+ android:orientation="vertical"
+ tools:context=".materials.BackgroundBlurActivity">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:padding="10dp"
+ android:textColor="#ffffffff"
+ android:text="Hello blurry world!"/>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="#ffffffff"
+ android:text="Background blur"/>
+
+ <SeekBar
+ android:id="@+id/set_background_blur"
+ android:min="0"
+ android:max="300"
+ android:layout_width="160dp"
+ android:layout_height="wrap_content"/>
+ <TextView
+ android:id="@+id/background_blur_radius"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#ffffffff"
+ android:ems="3"
+ android:gravity="center"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:text="TODO"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="#ffffffff"
+ android:text="Background alpha"/>
+
+ <SeekBar
+ android:id="@+id/set_background_alpha"
+ android:min="0"
+ android:max="100"
+ android:layout_width="160dp"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/background_alpha"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#ffffffff"
+ android:ems="3"
+ android:gravity="center"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:text="TODO"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="#ffffffff"
+ android:text="Blur behind"/>
+
+ <SeekBar
+ android:id="@+id/set_blur_behind"
+ android:min="0"
+ android:max="300"
+ android:layout_width="160dp"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/blur_behind_radius"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="#ffffffff"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:ems="3"
+ android:text="TODO"/>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:textColor="#ffffffff"
+ android:text="Dim amount"/>
+
+ <SeekBar
+ android:id="@+id/set_dim_amount"
+ android:min="0"
+ android:max="100"
+ android:layout_width="160dp"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/dim_amount"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:textColor="#ffffffff"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:ems="3"
+ android:text="TODO"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:layout_marginTop="5dp"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <Button
+ android:id="@+id/toggle_blur_enabled"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Disable blur"
+ android:onClick="toggleForceBlurDisabled"/>
+
+ <Button
+ android:id="@+id/toggle_battery_saving_mode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="TODO"
+ android:onClick="toggleBatterySavingMode"/>
+ </LinearLayout>
+ <requestFocus/>
+
+</LinearLayout>
diff --git a/tests/SilkFX/res/values/style.xml b/tests/SilkFX/res/values/style.xml
new file mode 100644
index 0000000..66edbb5
--- /dev/null
+++ b/tests/SilkFX/res/values/style.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<!-- Styles for immersive actions UI. -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <style name="Theme.BackgroundBlurTheme" parent= "Theme.AppCompat.Dialog">
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBlurBehindEnabled">true</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:windowElevation">0dp</item>
+ <item name="buttonStyle">@style/AppTheme.Button</item>
+ <item name="colorAccent">#bbffffff</item>
+ </style>
+ <style name="AppTheme.Button" parent="Widget.AppCompat.Button">
+ <item name="android:textColor">#ffffffff</item>
+ </style>
+
+</resources>
diff --git a/tests/SilkFX/src/com/android/test/silkfx/Main.kt b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
index 9ed8d2f..7132ae8 100644
--- a/tests/SilkFX/src/com/android/test/silkfx/Main.kt
+++ b/tests/SilkFX/src/com/android/test/silkfx/Main.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -30,6 +30,7 @@
import com.android.test.silkfx.app.EXTRA_TITLE
import com.android.test.silkfx.hdr.GlowActivity
import com.android.test.silkfx.materials.GlassActivity
+import com.android.test.silkfx.materials.BackgroundBlurActivity
import kotlin.reflect.KClass
class Demo(val name: String, val makeIntent: (Context) -> Intent) {
@@ -51,7 +52,8 @@
Demo("Blingy Notifications", R.layout.bling_notifications)
)),
DemoGroup("Materials", listOf(
- Demo("Glass", GlassActivity::class)
+ Demo("Glass", GlassActivity::class),
+ Demo("Background Blur", BackgroundBlurActivity::class)
))
)
@@ -126,4 +128,4 @@
AllDemos.forEachIndexed { index, _ -> list.expandGroup(index) }
}
-}
\ No newline at end of file
+}
diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt
new file mode 100644
index 0000000..9d17d38
--- /dev/null
+++ b/tests/SilkFX/src/com/android/test/silkfx/materials/BackgroundBlurActivity.kt
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.test.silkfx.materials
+
+import android.app.Activity
+import android.content.Intent
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.graphics.Color
+import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.PaintDrawable
+import android.graphics.drawable.Drawable
+import android.os.Bundle
+import android.provider.Settings
+import android.util.TypedValue
+import android.view.View
+import android.view.WindowManager
+import android.widget.ImageView
+import android.widget.SeekBar
+import android.widget.Switch
+import android.widget.TextView
+import com.android.test.silkfx.R
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable
+import android.widget.LinearLayout
+import android.widget.Button
+
+import android.view.ViewRootImpl
+
+class BackgroundBlurActivity : Activity(), SeekBar.OnSeekBarChangeListener {
+ var mBackgroundDrawable = PaintDrawable(Color.WHITE)
+ var mBackgroundBlurRadius = 50
+ var mAlphaWithBlur = 0.2f
+ var mAlphaNoBlur = 0.5f
+
+ var mBlurBehindRadius = 10
+ var mDimAmountWithBlur = 0.2f
+ var mDimAmountNoBlur = 0.2f
+
+ var mBlurForceDisabled = false
+ var mBatterySavingModeOn = false
+
+ lateinit var blurBackgroundSeekBar: SeekBar
+ lateinit var backgroundAlphaSeekBar : SeekBar
+ lateinit var blurBehindSeekBar : SeekBar
+ lateinit var dimAmountSeekBar : SeekBar
+
+ val blurEnabledListener = { enabled : Boolean ->
+ blurBackgroundSeekBar.setProgress(mBackgroundBlurRadius)
+ blurBehindSeekBar.setProgress(mBlurBehindRadius)
+
+ if (enabled) {
+ setBackgroundBlur(mBackgroundBlurRadius)
+ setBackgroundColorAlpha(mAlphaWithBlur)
+
+ setBlurBehind(mBlurBehindRadius)
+ setDimAmount(mDimAmountWithBlur)
+
+ backgroundAlphaSeekBar.setProgress((mAlphaWithBlur * 100).toInt())
+ dimAmountSeekBar.setProgress((mDimAmountWithBlur * 100).toInt())
+ } else {
+ setBackgroundColorAlpha(mAlphaNoBlur)
+ setDimAmount(mDimAmountNoBlur)
+
+ backgroundAlphaSeekBar.setProgress((mAlphaNoBlur * 100).toInt())
+ dimAmountSeekBar.setProgress((mDimAmountNoBlur * 100).toInt())
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_background_blur)
+
+ window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
+ window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+ mBackgroundDrawable.setCornerRadius(30f)
+ window.setBackgroundDrawable(mBackgroundDrawable)
+
+ mBatterySavingModeOn =
+ Settings.Global.getInt(getContentResolver(), Settings.Global.LOW_POWER_MODE, 0) == 1
+ setBatterySavingModeOn(mBatterySavingModeOn)
+
+ blurBackgroundSeekBar = requireViewById(R.id.set_background_blur)
+ backgroundAlphaSeekBar = requireViewById(R.id.set_background_alpha)
+ blurBehindSeekBar = requireViewById(R.id.set_blur_behind)
+ dimAmountSeekBar = requireViewById(R.id.set_dim_amount)
+
+ arrayOf(blurBackgroundSeekBar, backgroundAlphaSeekBar, blurBehindSeekBar, dimAmountSeekBar)
+ .forEach {
+ it.setOnSeekBarChangeListener(this)
+ }
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ getWindowManager().addCrossWindowBlurEnabledListener(blurEnabledListener)
+ }
+
+ override fun onDetachedFromWindow() {
+ super.onDetachedFromWindow()
+ getWindowManager().removeCrossWindowBlurEnabledListener(blurEnabledListener)
+ }
+
+ override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+ when (seekBar) {
+ blurBackgroundSeekBar -> setBackgroundBlur(progress)
+ backgroundAlphaSeekBar -> setBackgroundColorAlpha(progress / 100.0f)
+ blurBehindSeekBar -> setBlurBehind(progress)
+ dimAmountSeekBar -> setDimAmount(progress / 100.0f)
+ else -> throw IllegalArgumentException("Unknown seek bar")
+ }
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar?) {}
+ override fun onStopTrackingTouch(seekBar: SeekBar?) {}
+
+ fun setBlurDisabled(disabled: Boolean) {
+ mBlurForceDisabled = disabled
+ Settings.Global.putInt(getContentResolver(), Settings.Global.DISABLE_WINDOW_BLURS,
+ if (mBlurForceDisabled) 1 else 0)
+ (findViewById(R.id.toggle_blur_enabled) as Button)
+ .setText(if (mBlurForceDisabled) "Enable blurs" else "Disable blurs")
+ }
+
+ fun toggleForceBlurDisabled(v: View) {
+ setBlurDisabled(!mBlurForceDisabled)
+ }
+
+ fun setBackgroundBlur(radius: Int) {
+ mBackgroundBlurRadius = radius
+ (findViewById(R.id.background_blur_radius) as TextView).setText(radius.toString())
+ window.setBackgroundBlurRadius(mBackgroundBlurRadius)
+ }
+
+ fun setBlurBehind(radius: Int) {
+ mBlurBehindRadius = radius
+ (findViewById(R.id.blur_behind_radius) as TextView).setText(radius.toString())
+ window.getAttributes().setBlurBehindRadius(mBlurBehindRadius)
+ window.setAttributes(window.getAttributes())
+ }
+
+ fun setDimAmount(amount: Float) {
+ if (getWindowManager().isCrossWindowBlurEnabled()) {
+ mDimAmountWithBlur = amount
+ } else {
+ mDimAmountNoBlur = amount
+ }
+ (findViewById(R.id.dim_amount) as TextView).setText("%.2f".format(amount))
+ window.getAttributes().dimAmount = amount
+ window.setAttributes(window.getAttributes())
+ }
+
+ fun setBatterySavingModeOn(on: Boolean) {
+ mBatterySavingModeOn = on
+ Settings.Global.putInt(getContentResolver(),
+ Settings.Global.LOW_POWER_MODE, if (on) 1 else 0)
+ (findViewById(R.id.toggle_battery_saving_mode) as Button).setText(
+ if (on) "Exit low power mode" else "Enter low power mode")
+ }
+
+ fun toggleBatterySavingMode(v: View) {
+ setBatterySavingModeOn(!mBatterySavingModeOn)
+ }
+
+ fun setBackgroundColorAlpha(alpha: Float) {
+ if (getWindowManager().isCrossWindowBlurEnabled()) {
+ mAlphaWithBlur = alpha
+ } else {
+ mAlphaNoBlur = alpha
+ }
+ (findViewById(R.id.background_alpha) as TextView).setText("%.2f".format(alpha))
+ mBackgroundDrawable.setAlpha((alpha * 255f).toInt())
+ getWindowManager().updateViewLayout(window.getDecorView(), window.getAttributes())
+ }
+}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnTest.java b/tests/vcn/java/com/android/server/vcn/VcnTest.java
index 5d2f9d7..6d26968 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnTest.java
@@ -58,6 +58,7 @@
import com.android.server.VcnManagementService.VcnCallback;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
+import com.android.server.vcn.Vcn.VcnUserMobileDataStateListener;
import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
import org.junit.Before;
@@ -208,6 +209,13 @@
}
@Test
+ public void testMobileDataStateListenersRegistered() {
+ // Validate state from setUp()
+ verify(mTelephonyManager, times(3))
+ .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class));
+ }
+
+ @Test
public void testMobileDataStateCheckedOnInitialization_enabled() {
// Validate state from setUp()
assertTrue(mVcn.isMobileDataEnabled());
@@ -263,6 +271,24 @@
assertFalse(mVcn.isMobileDataEnabled());
}
+ @Test
+ public void testSubscriptionSnapshotUpdatesMobileDataStateListeners() {
+ final TelephonySubscriptionSnapshot updatedSnapshot =
+ mock(TelephonySubscriptionSnapshot.class);
+
+ doReturn(new ArraySet<>(Arrays.asList(2, 4)))
+ .when(updatedSnapshot)
+ .getAllSubIdsInGroup(any());
+
+ mVcn.updateSubscriptionSnapshot(updatedSnapshot);
+ mTestLooper.dispatchAll();
+
+ verify(mTelephonyManager, times(4))
+ .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class));
+ verify(mTelephonyManager, times(2))
+ .unregisterTelephonyCallback(any(VcnUserMobileDataStateListener.class));
+ }
+
private void triggerVcnRequestListeners(NetworkRequestListener requestListener) {
for (final int[] caps : TEST_CAPS) {
startVcnGatewayWithCapabilities(requestListener, caps);
@@ -402,24 +428,17 @@
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
}
- private void verifyMobileDataToggled(boolean startingToggleState, boolean endingToggleState) {
- final ArgumentCaptor<ContentObserver> captor =
- ArgumentCaptor.forClass(ContentObserver.class);
- verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture());
- final ContentObserver contentObserver = captor.getValue();
-
+ private void setupForMobileDataTest(boolean startingToggleState) {
// Start VcnGatewayConnections
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
mVcn.setMobileDataEnabled(startingToggleState);
triggerVcnRequestListeners(requestListener);
- final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways =
- mVcn.getVcnGatewayConnectionConfigMap();
+ }
- // Trigger data toggle change.
- doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled();
- contentObserver.onChange(false /* selfChange, ignored */);
- mTestLooper.dispatchAll();
-
+ private void verifyMobileDataToggledUpdatesGatewayConnections(
+ boolean startingToggleState,
+ boolean endingToggleState,
+ Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways) {
// Verify that data toggle changes restart ONLY INTERNET or DUN networks, and only if the
// toggle state changed.
for (Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry : gateways.entrySet()) {
@@ -433,29 +452,98 @@
}
}
+ final NetworkRequestListener requestListener = verifyAndGetRequestListener();
if (startingToggleState != endingToggleState) {
verify(mVcnNetworkProvider).resendAllRequests(requestListener);
}
assertEquals(endingToggleState, mVcn.isMobileDataEnabled());
}
- @Test
- public void testMobileDataEnabled() {
- verifyMobileDataToggled(false /* startingToggleState */, true /* endingToggleState */);
+ private void verifyGlobalMobileDataToggled(
+ boolean startingToggleState, boolean endingToggleState) {
+ setupForMobileDataTest(startingToggleState);
+ final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways =
+ mVcn.getVcnGatewayConnectionConfigMap();
+
+ // Trigger data toggle change
+ final ArgumentCaptor<ContentObserver> captor =
+ ArgumentCaptor.forClass(ContentObserver.class);
+ verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture());
+ final ContentObserver contentObserver = captor.getValue();
+
+ doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled();
+ contentObserver.onChange(false /* selfChange, ignored */);
+ mTestLooper.dispatchAll();
+
+ // Verify resultant behavior
+ verifyMobileDataToggledUpdatesGatewayConnections(
+ startingToggleState, endingToggleState, gateways);
}
@Test
- public void testMobileDataDisabled() {
- verifyMobileDataToggled(true /* startingToggleState */, false /* endingToggleState */);
+ public void testGlobalMobileDataEnabled() {
+ verifyGlobalMobileDataToggled(
+ false /* startingToggleState */, true /* endingToggleState */);
}
@Test
- public void testMobileDataObserverFiredWithoutChanges_dataEnabled() {
- verifyMobileDataToggled(false /* startingToggleState */, false /* endingToggleState */);
+ public void testGlobalMobileDataDisabled() {
+ verifyGlobalMobileDataToggled(
+ true /* startingToggleState */, false /* endingToggleState */);
}
@Test
- public void testMobileDataObserverFiredWithoutChanges_dataDisabled() {
- verifyMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */);
+ public void testGlobalMobileDataObserverFiredWithoutChanges_dataEnabled() {
+ verifyGlobalMobileDataToggled(
+ false /* startingToggleState */, false /* endingToggleState */);
+ }
+
+ @Test
+ public void testGlobalMobileDataObserverFiredWithoutChanges_dataDisabled() {
+ verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */);
+ }
+
+ private void verifySubscriptionMobileDataToggled(
+ boolean startingToggleState, boolean endingToggleState) {
+ setupForMobileDataTest(startingToggleState);
+ final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways =
+ mVcn.getVcnGatewayConnectionConfigMap();
+
+ // Trigger data toggle change.
+ final ArgumentCaptor<VcnUserMobileDataStateListener> captor =
+ ArgumentCaptor.forClass(VcnUserMobileDataStateListener.class);
+ verify(mTelephonyManager, times(3)).registerTelephonyCallback(any(), captor.capture());
+ final VcnUserMobileDataStateListener listener = captor.getValue();
+
+ doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled();
+ listener.onUserMobileDataStateChanged(false /* enabled, ignored */);
+ mTestLooper.dispatchAll();
+
+ // Verify resultant behavior
+ verifyMobileDataToggledUpdatesGatewayConnections(
+ startingToggleState, endingToggleState, gateways);
+ }
+
+ @Test
+ public void testSubscriptionMobileDataEnabled() {
+ verifyGlobalMobileDataToggled(
+ false /* startingToggleState */, true /* endingToggleState */);
+ }
+
+ @Test
+ public void testSubscriptionMobileDataDisabled() {
+ verifyGlobalMobileDataToggled(
+ true /* startingToggleState */, false /* endingToggleState */);
+ }
+
+ @Test
+ public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataEnabled() {
+ verifyGlobalMobileDataToggled(
+ false /* startingToggleState */, false /* endingToggleState */);
+ }
+
+ @Test
+ public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataDisabled() {
+ verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */);
}
}